5.4 Multitsaking ( 한번에여러개의클라이언트다루기 ) 5.4.1 Per-Client Process 클라이언트별접속을프로세스로담당하기 5.4.2 Per-Client Thread 클라이언트별접속을쓰레드로담당하기 5.4.3 Constrained Multitasking 프로세스 쓰레드의수를제한하여시스템부하줄이기
5.4.1 Per-Client Processes ( 클라이언트당프로세스들 ) (1) 클라이언트로부터들어오는연결을받아들인다. (2) 그연결을다루기위한새프로세서를생성한다. * 프로세서들은서버호스트의자원들을공유하며자신의클라이언트를담당할프로세서복사본을생성하여각각병행적으로서비스한다. 단점 : 자원을많이소모하는단점이있다.
fork() 자식프로세서를만든다. 1. 설명 자신만의 PID 를가지게되며, PPID 는부모프로세스의 PID 를가진다. 그밖에 PGID PGID, SID 를상속받으며, 파일지시자, 시그널등을상속받는다. * 단파일잠금 (lock) 와시그널팬딩은상속받지않는다. 2. 반환값성공할경우자식프로세스의 PID 가부모에게리턴 0 이자식에게리턴실패할경우 -1 이리턴, errno (errornumber) 값설정. EAGAIN 자식프로세스를위한테스크구조체를할당할수없을경우 주로메모리문제 ( 시스템자원 ) 와연관.
3. 사용법 #include <unistd.h> pid_t fork(void); pid = fork(); If( pid == 0 ) { /* 자식프로세서가할일 */ } else { /* 부모프로세서가할일 */ }
waitpid() 프로세스의종료를기다린다. 1. 설명 waitpid 함수는인수로주어진 pid 번호의자식프로세스가종료되거나, 시그널함수를호출하는신호가전달될때까지 waitpid 호출한영역에서일시중지된다. 만일 pid 로지정된자식이 waitpid() 호출전에이미종료되었다면, 함수는즉시리턴하고자식프로세스는 " 좀비프로세스 " 로남는다. * pid 값 < -1 프로세서그룹 ID 가 pid 의절대값과같은자식프로세스를기다린다. -1 임의의자식프로세스를기다린다. 이것은 wait() 와동일하다. 0 프로세스그룹 ID 가호출프로세스의 ID 와같은 자식프로세스를기다린다. #include <sys/types.h> > 0 프로세스 ID가 pid 의값과같은자식프로세스를기다린다. #include <sys/wait.h> pid_t waitpid(pid_t pid, int *status, int options);
options WNOHANG 어떠한자식도종료되지않았더라도리턴 WUNTRACED 멈추거나상태가보고되지않은자식들을위해리턴 status NULL이아닐경우에 status가가리키는곳에프로세스의상태를저장
5.4.2 Per-Client Thread ( 클라이언트당쓰레드 ) 프로세스내의멀티태스킹을이용하여클라이언트의비용을줄인다. 새로생성된쓰레드는부모와같은주소공간 ( 코드및데이터 ) 을공유하고, 부모의상태를복제할필요성을배제한다.
pthread_creat() 새로운쓰레드를생성 1.2 절. 설명 pthread_exit() 을호출하거나또는 start_rutine 에서 return 할경우제거할수있다. attr 아규먼트는쓰레드와관련된특성을지정하기위한용도로사용 attr 을 NULL 로할경우기본특성으로지정리눅스에서의쓰레드는 joinable 과 non real-time 스케쥴정책을기본특성으로한다. 1.3 절. 반환값성공할경우쓰레드식별자인 thread 에쓰레드식별번호를저장하고, 0 을리턴실패했을경우 0 이아닌에러코드값을리턴 1.4 절. 에러 EAGAIN 쓰레드생성을위한자원이부족하거나, PTHREAD_THREADS_MAX 를초과해서쓰레드생성을요청할경우
사용법 #include <pthread.h> int pthread_create(pthread_t * thread, pthread_attr_t * attr, void * (*start_routine)(void *), void * arg);
5.4.3 Constrained Multitasking ( 제한멀티태스킹 ) 프로세스나쓰레드의생성숫자를사용자가임의의제한을두어시스템성능을유지. Line23 For(processCt=0; processct < processlimit; processct++) 사용자가지정
5.5 멀티플렉싱 (Multiplexing) 하나의전송로를여러사용자가동시에사용해서효율성을극대화함
1. 개념하나의통신회선을통하여여러개의입력이결합된형태로서데이터신호를전송한후수신측에서는전송된원래형태의데이터신호로분해하여주는것이다. 이것은음성과데이터, 그리고영상데이터를동시에안전하고신속하게서비스해주는데있다.
2. 기능 1) 가입자측에서다양한속도로접속되는인터페이스기능 2) 음성, 데이터, 영상서비스기능 3) 시스템사이의전송선로자동우회기능 4) 데이터의멀티드롭기능 5) 대용량고속전송기능
3. 특징여러채널의신호를한채널에보내야하므로하나의전송채널은일반적으로 n 배의넓은대역폭을가져야한다. 여기서대역폭이라는것은단위가시간다중화에서는 bits per second(bps) 가되고, 주파수다중화에서는 Hz 가된다. -- 보통대역폭이라고하면주파수의대역폭을말하지만, 시분할다중화에서는데이터전송속도즉, bps 를대역폭이라고도한다. 이것은통신을처음공부하는사람에게상당한혼동을일으킬수도있는점이다.
4. 종류 1) 시분할다중화 (Time Division Multiplexing, TDM) : 디지털신호에대해서베이스밴드에서사용한다. 2) 주파수분할다중화 (Frequency Division Multiplexing, FDM): 아날로그신호에대해서브로드밴드에서사용한다.
시분할다중화 시간을여러개의조각 ( 타임슬롯 ) 으로나누어서거기에각채널의데이터를넣어서보내는방식이다. 디지털신호로전송되며, 아날로그데이터에는직접적으로사용하지못하므로양자화하고코드화해서디지털신호로만든후에사용할수있다.
1) 동기식 (Synchronous) TDM 이방식은고전적인회선교환 (circuitswitching) 에서사용되는것으로각입력에버퍼를두지않고, 타임슬롯을모든이용자에게규칙적으로할당한다. 즉, 각채널에서데이터를보내던안보내던타임슬롯을미리할당하고고정시킨다. 장점 : 구현이간단하다. 단점 : 입력이없는채널이있어도계속대역폭은낭비되어야한다. 적용예 : DS-1 프레임포맷, ISDN, SONET/SDH
2) 비동기식 (Asynchronous) 또는통계적 (Statistical) TDM 이방식은인터넷에서사용되는패킷교환에적용되는방식으로각입력에버퍼를두고입력이있는채널에만타임슬롯을할당하는동적할당방식이다. 장점 : 입력이있는채널에만타임슬롯을할당하기때문에대역폭이남을수있고, 그남는대역폭동안다른일을할수있다. 단점 : 각채널마다헤드를삽입하기때문에구현이다소복잡하다. 적용예 :HDLC 프레임포멧
주파수분할다중화 1. 개념주파수를여러개로나누어서동시에한채널로전송하는방식으로아날로그신호를변조해서각대역폭을합해서보내다. 흔히볼수있는예가방송국에서보내는전파이다. 이전파에는TV나라디오의각채널에있는변조된신호들이공중에서동시에전송된다. 여기서는공중이바로하나의채널이되는것이다.
select 를사용한서버설계 Select 함수의소개프로세스가 kernel 에게여러사건중에서하나이상이발생할때까지기다리다가하나이상의사건 (accpet,recve 등 ) 이발생하거나또는지정된시간이경과할때만프로세스를깨우라고지시서버가어떤일을하는동안블록실행을하는것을허락해줌 #include <sys/select.h> #include <sys/time.h> Int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, const struct timeval * timeout);
Select 함수를사용한서버설계 Select 인수 1. 최대숫자 (n) 파일기술자에서테스트. 2. 파일기술자집합 (readfds) 읽는자료로부터테스트 3. 파일기술자집합 (writefds) 쓰기가능으로부터테스트 4. 파일기술자집합 (exceptfds) 예외에관한테스트. 5. 포인터 timeout 요구는함수호출을선정, 포인터가 null 이면 no timeout 을지시한다.
Select 함수를사용한서버 설계 select 함수리턴값 -1 함수호출에에러발생 0 아무것도발생하지않고 timeout 시 0 보다큰숫자는파일기술자가무언가를생성 Timeval 구조 struct timeval { long tv_sec; long tv_use; };
Select 함수를사용한서버설계 Int select(int maxfdp1, &rx_set, fd_set*writeset, fd_set *exceptset, const struct timeval * timeout); FD_ZERO(&rx_set); 초기화 FD_SET(s,&rx_set); Turn on bit FD_ISSET(z,&rx_set) test FD_CLR(c,&rx_set); clear
Select() 의개요 select() int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); select() waits for a number of file descriptors to change status Macros for manipulating fd_set FD_ZERO(fd_set *set); FD_SET(int fd, fd_set *set); FD_CLEAR(int fd, fd_set *set); FD_ISSET(int fd, fd_set *set);
5.6 여러수신자들 (Multiple Recipients) 5.6.1 브로드캐스트 5.6.2 멀티캐스트
- 5.6.1 브로드캐스트 (Broadcast) 전송방식. UDP를기반으로하는전송방식 ( 멀티캐스트와같다 ). 일반적인 UDP 패킷과의차이점은전송목적지 IP주소뿐이다. 동일네트워크에속하는모든호스트에동시전송 ( 멀티캐스트와의차이점 ). 인터넷상에서는지역네트워크내에서만브로드캐스트를허용한다 ( 네트워크의부하를고려 ).
주소선택에따른브로드캐스트방식의구분. 지정된브로드캐스트 : 예 192.12.31.255 192 12 31 xxx 네트워크 IP 호스트 IP 192 12 31 255 브로드캐스트 address 지역적브로드캐스트 : 예 255.255.255.255 255 255 255 255 브로드캐스트 address
브로드캐스트 Sender 예제 : send_sock=socket(pf_inet, SOCK_DGRAM, 0); /* 브로드캐스트를위해 UDP 소켓생성 */ : state=setsockopt(send_sock, SOL_SOCKET, SO_BROADCAST, (void*)&so_broadcast, sizeof(so_broadcast)); : if((fp=fopen("news.txt", "r"))==null) /* news 파일오픈 */ error_handling("fopen() error"); while(!feof(fp)){ /* news 방송 */ fgets(buf, BUFSIZE, fp); sendto(send_sock, buf, strlen(buf), 0, (struct sockaddr*)&broad_addr, sizeof(broad_addr)); :
브로드캐스트 Sender 의실행결과
브로드캐스트 Receiver 예제 : recv_sock=socket(pf_inet, SOCK_DGRAM, 0); /* 브로드캐스트를위한 UDP소켓생성 */ : memset(&addr, 0, sizeof(addr)); addr.sin_family=af_inet; addr.sin_addr.s_addr=htonl(inaddr_any); addr.sin_port=htons(atoi(argv[1])); /* 브로드캐스트 port 설정 */ if(bind(recv_sock, (struct sockaddr*)&addr, sizeof(addr))==-1) error_handling("bind() error"); :
브로드캐스트 Receiver 의실행결과
- 5.6.2 멀티캐스트 (Multicast) 전송방식 UDP 를기반으로하는 전송방식. 멀티캐스트그룹을기반으로멀티캐스트패킷을주고받음. 하나의멀티캐스트패킷은라우터를통해서다수의호스트에전송.
라우팅 (Routing) 과 TTL(Time To Live) 라우터에의해서패킷이경로를찾는과정을라우팅이라한다. 멀티캐스트패킷내에는 TTL 정보가포함된다. TTL은거쳐갈수있는라우터의수를의미한다
멀티캐스트 Sender 와 Receiver. Sender : 임의의멀티캐스트그룹에데이터를전송하는호스트 Receiver : 임의의멀티캐스트그룹으로부터데이터를수신하는호스트 멀티캐스트 Sender 와 Receiver 의구현 Sender UDP 소켓생성. TTL 설정 ( 소켓옵션설정 ). 멀티캐스트그룹으로데이터전송. Receiver UDP 소켓생성. 멀티캐스트그룹지정 (ip_mreq 구조체 ). 멀티캐스트그룹가입 ( 소켓옵션설정 ).
멀티캐스트 Sender 예제 : #define TTL 64 : send_sock=socket(pf_inet, SOCK_DGRAM, 0); /* 멀티캐스트를위한 UDP소켓생성 */ if(send_sock == -1) error_handling("socket() error"); memset(&multi_addr, 0, sizeof(multi_addr)); multi_addr.sin_family=af_inet; multi_addr.sin_addr.s_addr=inet_addr(argv[1]); /* 멀티캐스트 IP 설정 */ multi_addr.sin_port=htons(atoi(argv[2])); /* 멀티캐스트 port 설정 */ state=setsockopt(send_sock, IPPROTO_IP, IP_MULTICAST_TTL, (void*) &multi_ttl, sizeof(multi_ttl)); :
멀티캐스트 Sender 예제 : if((fp=fopen("news.txt", "r"))==null) /* news 파일오픈 */ error_handling("fopen() error"); while(!feof(fp)){ /* news 방송 */ fgets(buf, BUFSIZE, fp); sendto(send_sock, buf, strlen(buf), 0, (struct sockaddr*)&multi_addr, sizeof(multi_addr)); sleep(2); } :
멀티캐스트 Sender 의실행결과
멀티캐스트 Reciver 예제 int recv_sock; : struct sockaddr_in addr; int state, str_len; char buf[bufsize]; struct ip_mreq join_addr; : recv_sock=socket(pf_inet, SOCK_DGRAM, 0); /* 멀티캐스트를위해 UDP소켓생성 */ if(recv_sock == -1) error_handling("socket() error"); : addr.sin_port=htons(atoi(argv[2])); /* 멀티캐스트 port 설정 */ :
멀티캐스트 Receiver 예제 : join_addr.imr_multiaddr.s_addr=inet_addr(argv[1]); join_addr.imr_interface.s_addr=htonl(inaddr_any); state=setsockopt(recv_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void*)&join_addr, sizeof(join_addr)); : while(1){ str_len=recvfrom(recv_sock, buf, BUFSIZE-1, 0, NULL, 0); if(str_len<0) break; buf[str_len]=0; fputs(buf, stdout); } :
멀티캐스트 Receiver 의실행결과