티스토리 뷰
출처 : http://bluelimn.tistory.com/m/post/763
IPC : pipe, named pipe, semaphore, message queue, shared memory, futex, socket
Futex : fast userspace mutex(Spinlock 방식)
- 장점 : 빠름 (sleep 대신 while),
lock이 user space에 있기 때문에 접근성이 좋음(공유 메모리나 Thread 및 Process간 공유 가능)
- 단점 : 기본적으로 loop를 계속 돌고 있기 때문에 core수가 뒷받침되어야 한다.
(single core에서는 소용 없음.)
pthread mutex vs pthread spinlock
Pasted from <http://www.alexonlinux.com/pthread-mutex-vs-pthread-spinlock>
Pselect()
int pselect(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, const struct timespec *timeout,
const sigset_t *sigmask);
• pselect는 struct timespec 구조체 사용한다. timespec 구조체를 사용함으로써 나노초까지 세밀하게 조정할 수 있게 되었다.
struct timespec {
long tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
• pselect 는 Linux(:12) 커널 2.6.16에 추가되었다. 이전에는 glibc에서 애뮬레이트한
함수가 제공되었으나 버그를 가지고 있었다.
• sigmask를 사용해서 시그널을 블럭시킬 수 있다. select의 경우 수행되는 도중에 시그널에 의한 인터럽트가 발생하게 되면, race condition 혹은 무한 블록킹 상태에 놓일 수 있었다. pselect를 사용하면 이러한 문제를 제거할 수 있다.
Pasted from <http://www.joinc.co.kr/modules/moniwiki/wiki.php/man/2/select>
Pselect가 select와 다른 점
- Nano sec단위로 사용하므로 이론적으로는 타이머 해상도가 정밀하나 실전에서는
micro sec단위도 안정적으로 제공하지 못한다.
- Timeout parameter를 변경하지 않는다. 사용할 때마다 timeout을 다시 설정할
필요가 없음
- Signal parameter가 추가됨(sigmask) : signal 을 차단함.
Select() : 동기식 다중 입출력 제공
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
Int select (int n,
fd_set *readfds,
fd_set *writefds,
fd_set *execptfds,
struct timeval *timeout);
FD_CLR(int fd, fd_set *set); /* delete FD */
FD_ISSET(int fd, fd_set *set); /* select의 결과에 해당 fd가 있는지 */
FD_SET(int fd, fd_set *set); /* add FD*/
FD_ZERO(fd_set *set);
#include <sys/time.h>
Struct timeval {
long tv_sec; /* sec */
long tv_usec; /* micro sec */
};
Poll() : select를 보완 (fd set을 하나로 통일)
#include <sys/poll.h>
Int poll (struct pollfd *fds, unsigned int nfds, int timeout);
#include <sys/poll.h>
Struct pollfd {
int fd;
short events; /* 감시 대상 요청 */
short revents; /* returned event */
}
Events:
POLLIN : Data other than high-priority data may be read without blocking.
POLLRDNORM : Normal data may be read without blocking.
POLLRDBAND : Priority data may be read without blocking.
POLLPRI : High-priority data may be read without blocking.
POLLOUT : Normal data may be written without blocking.
POLLWRNORM : Equivalent to POLLOUT.
POLLWRBAND : Priority data may be written.
POLLERR : An error has occurred on the device or stream. This flag is only valid in the revents bitmask; it shall be ignored in the events member.
POLLHUP : The device has been disconnected. This event and POLLOUT are mutually-exclusive; a stream can never be writable if a hangup has occurred. However, this event and POLLIN, POLLRDNORM, POLLRDBAND, or POLLPRI are not mutually-exclusive. This flag is only valid in the revents bitmask; it shall be ignored in the events member.
POLLNVAL : The specified fd value is invalid. This flag is only valid in the revents member; it shall ignored in the events member.
Ppoll() : pselect 처럼 만든 것, 나노초 단위, sigmask 제공, linux 전용
#define _GNU_SOURCE
#include <sys/poll.h>
Int ppoll (struct pollfd *fds,
nfds_t nfds,
const struct timespec *timeout,
const sigset_t *sigmask);
server.c
#include <sys/time.h> #include <sys/types.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <sys/stat.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h>
#define TIMEOUT 10 /* timeout : seconds */ #define FD_MAX_CLIENT 3 #define BUF_SIZE 1024 #define EXIT_STR "exit" /* * error - wrapper for perror */ void error(char *msg) { perror(msg); exit(1); } int main(int argc, char **argv) { int server_sockfd; int client_sockfd; int max_fd; /* for using select */ struct sockaddr_in serveraddr; struct sockaddr_in clientaddr; int clientlen; int client[FD_MAX_CLIENT]; char buf[BUF_SIZE]; /* message buffer */ int n; /* message byte size */ struct timeval tv; fd_set readfds, temp_fds;
int notdone; int i, ret; /* socket: create the parent socket */ server_sockfd = socket(AF_INET, SOCK_STREAM, 0); if (server_sockfd < 0) error("ERROR opening socket"); max_fd = server_sockfd; bzero((char*)&serveraddr, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); serveraddr.sin_port = htons(9000);
if(bind(server_sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0) error("ERROR on binding");
if(listen(server_sockfd, 5) < 0) /* allow 5 requests(backlog) to queue up */ error("ERROR on listen");
for (i = 0; i < FD_MAX_CLIENT; i++) { client[i] = -1; }
/* initialize some things for the main loop */ clientlen = sizeof(clientaddr); notdone = 1; printf("TCP Server Waiting ...\n"); fflush(stdout); FD_ZERO(&readfds); /* initialize the fd set */ FD_SET(server_sockfd, &readfds); /* add socket fd */ while(notdone) { temp_fds = readfds; tv.tv_sec = TIMEOUT; tv.tv_usec = 0; ret = select(max_fd+1, &temp_fds, 0, 0, &tv); if (ret < 0) error("ERROR in select"); else if(ret == 0) { printf("waiting...\n"); continue; } if (FD_ISSET(server_sockfd, &temp_fds)) { /* accept: wait for a connection request */ client_sockfd = accept(server_sockfd, (struct sockaddr *)&clientaddr, &clientlen); if(client_sockfd < 0) error("ERROR on accept");
printf("connection from (%s , %d)\n", inet_ntoa(clientaddr.sin_addr),ntohs(clientaddr.sin_port)); for (i = 0; i < FD_MAX_CLIENT; i++) { if (client[i] < 0) { client[i] = client_sockfd; printf("\nclient_idx=%d, client_sockfd=%d\n", i, client_sockfd); break; } } if(i >= FD_MAX_CLIENT) { printf("too many clients. so, closing client fd[%d]\n", client_sockfd); close(client_sockfd); continue; } FD_SET(client_sockfd, &readfds); /* add socket fd */ max_fd = (client_sockfd > max_fd)?(client_sockfd):(max_fd); } for (i = 0; i <= FD_MAX_CLIENT; i++) { if (client[i] < 0) continue;
client_sockfd = client[i]; if (FD_ISSET(client_sockfd, &temp_fds)) { bzero(buf, BUF_SIZE);
/* n = recv(client_sockfd, buf, BUF_SIZE, 0); */ n = read(client_sockfd, buf, BUF_SIZE); if (n <= 0) { printf("Close client_sockfd : %d", client_sockfd); close(client_sockfd); FD_CLR(client_sockfd, &readfds); client[i] = -1; } printf("[%d]RECV %s\n", client_sockfd, buf); if(strncmp(buf,EXIT_STR,strlen(EXIT_STR)) == 0) { notdone = 0; break; } /* send(client_sockfd,buf,strlen(buf), 0); */ write(client_sockfd, buf, strlen(buf)); break; } } }
/* clean up */ printf("\nTerminating server.\n"); close(server_sockfd); exit(0); }
|
'program' 카테고리의 다른 글
aws tomcat java timezone 오류 (0) | 2016.10.15 |
---|---|
소켓 프로그래밍에서 적절한 버퍼의 크기 (0) | 2016.03.15 |
linux 에서 gcc,g++,glibc 설치하기 (0) | 2015.10.14 |
모바일웹에서 App 실행 및 설치여부 확인 (1) | 2015.05.18 |
[펌]Q_웹에서 어플 설치 여부 확인 (0) | 2015.05.18 |