학번 : 이름 : 1. 다음가정하에서아래프로그램의출력물을예측하세요. 가정 : 부모프로세스의 process id=20100, 자식프로세스의 process id=20101. int glob = 31; /* external variable in initialized data */ char buf[] = "a write to stdout\n"; int main(void) int var; /* automatic variable on the stack */ pid_t pid; var = 88; if (write(stdout_fileno, buf, sizeof(buf)-1)!= sizeof(buf)-1) err_sys("write error"); printf("before fork\n"); /* we don't flush stdout */ if ((pid = fork()) < 0) err_sys("fork error"); else if (pid == 0) glob++; /* modify variables */ var++; else sleep(2); printf("cpid=%d, pid=%d, glob = %d, var = %d\n", pid, getpid(), glob, var); 2. 위프로그램에서 fork 를 vfork 로바꾸면출력물이어떻게바뀔지아래설명을참고하여예측하시오. 이하생략.
3. 다음장에나오는 sigprocmask 함수의설명을참고하여다음프로그램의출력물과그출력물이화면이표시되는시점을예측하세요. ( 힌트 : 각줄이표시되는시점은다음 4 가지중하나. (1) 프로그램수행직후, (2) kill 명령실행직후, (3) 15 #include <signal.h> #include <unistd.h> #include <stdio.h> static void sig_usr1(int signo) printf("caught SIGUSR1\n"); int main(void) sigset_t newmask, oldmask, pendmask; if (signal(sigusr1, sig_usr1) == SIG_ERR) err_sys("can't catch SIGUSR1"); sigemptyset(&newmask); sigaddset(&newmask, SIGUSR1); if (sigprocmask(sig_block, &newmask, &oldmask) < 0) err_sys("sig_block error"); sleep(15); /* Reset signal mask */ if (sigprocmask(sig_setmask, &oldmask, NULL) < 0) err_sys("sig_setmask error"); 초후또는 (4) 30 초후 ) sleep(15); printf("done!\n"); 실행내용 : $./a.out & [1] 21413 ( 21413 이라는 process id 로백그라운드에서수행중.) $ kill -USR1 21413 (15 초가지나기전에이명령이실행된다고가정하세요.) 결과물및출력시점 :
sigprocmask 함수설명 ( 문제 3 용 ): 4. 다음프로그램의수행결과를예측하세요. #include <pthread.h> pthread_t ntid[8]; ////////////////////////////////////////////////////////////////// void * thr_fn(void *arg) int count=0; for (i=0; i<10000; i++) count++; return((void *)count); int main(void) void* res; for (i=0; i<2; i++) pthread_create(&ntid[i], NULL, thr_fn,null); for (i=0; i<2; i++) pthread_join(ntid[i], &res); printf("count= %d\n", (int)res); 5. 위프로그램에서 int count=0 부분을 /////// 주석이있는부분으로윗줄로옮기면결과가어떻게될까요?
6. 다음프로그램의수행결과를예측하고, 그렇게예측하는이유를구체적인예를들어설명하세요. ( 예를들어 1 번쓰레드와 2 번쓰레드에서특정변수값의시간에따른변화를나열.) #include <pthread.h> pthread_t ntid[8]; struct SharedData int count; pthread_mutex_t lock; ; void * thr_fn(void *arg) struct SharedData* pd=(struct SharedData*) arg; for (i=0; i<10000; i++) pd->count=pd->count+1; return((void *)0); int main(void) struct SharedData d; struct SharedData *pd=&d; d.count=0; for (i=0; i<8; i++) pthread_create(&ntid[i], NULL, thr_fn, (void*)pd); for (i=0; i<8; i++) pthread_join(ntid[i], NULL); printf("count= %d\n", d.count); 7. 위프로그램의수행결과가 80000 이나오도록하려면, 아래세줄을위프로그램에추가해야하는데, 각각어느위치에추가하는것이좋을지표시하세요. pthread_mutex_init(&pd->lock, NULL); pthread_mutex_lock(&pd->lock); pthread_mutex_unlock(&pd->lock);
8. 다음은무한루프를돌면서클라이언트가보낸메시지를처리하는서버프로그램의소스코드이다. #include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> int main() int server_sockfd, jlient_sockfd; int server_len, client_len; char string[256]; struct sockaddr_in server_address; struct sockaddr_in client_address; server_sockfd = socket(af_inet, SOCK_STREAM, 0); server_address.sin_family = AF_INET; server_address.sin_addr.s_addr = htonl(inaddr_any); server_address.sin_port = htons(9734); server_len = sizeof(server_address); bind(server_sockfd, (struct sockaddr *)&server_address, server_len); listen(server_sockfd, 5); while(1) printf("server waiting\n"); client_sockfd=accept(server_sockfd, (struct sockaddr *)&client_address, &client_len); while(1) read(client_sockfd, string, 256); printf("from client = %s\n", string); write(client_sockfd, string, 256); a. 만약클라이언트가서버에연결후아래코드를실행했을때서버와클라이언트프로그램의화면출력을예측하세요. char string[256] connect(sockfd, (struct sockaddr *)&address, sizeof(address)); // 연결된다고가정. write(sockfd, "asdf", 5); read(sockfd, string2, 256); printf("from server = %s\n", string2); b. 아래코드를수행했을때의수행결과를예측하세요. char string[256] connect(sockfd, (struct sockaddr *)&address, sizeof(address)); // 연결된다고가정. read(sockfd, string2, 256); write(sockfd, "asdf", 5); printf("from server = %s\n", string2);
c. 위서버프로그램은단한명의클라이언트만을다룰수있다. 이프로그램을여러클라이언트를지원하도록개선하려면, 크게 multi-threading 을사용하는방법과 I/O multiplexing 을이용하는방법이있다. Multi-threading 을사용해서각쓰레드가한명의클라이언트를전담하도록구현하는경우소스코드의어느부분을 thread 의 main 으로옮겨야하는가? pthread_create 함수의적절한위치와인자 (parameter) 로전달되어야하는데이타는? ( 글로벌변수를사용하지않고, 모든데이타가 pthread_create 함수의마지막파라미터로전달된다고가정하세요.) d. 반면 I/O Multiplexing 을이용하여여러클라이언트를지원하는경우, select 함수를이용할수있다. 즉 select 함수의입력으로파일서술자 (file descriptor) 의목록이저장된 fd_set 을넘겨주고, 그중사용가능한파일서술자가생길때까지차단되어 (block) 기다리는방식으로구현할수있다. 다음 select 함수의설명을참조하여예를들어클라이언트가 4 명접속되어있는경우, select 함수의인자로들어가는 readfds 에어떤 file descriptor 가선택되어있어야하는지나열하세요.
9. 다음 4 가지프로그램이구현되어있다고가정하자../tolower ( stdin 입력을소문자로변환해 stdout 으로출력하는프로그램 )./toupper ( stdin 입력을대문자로변환해 stdout 으로출력하는프로그램 )./tomixed ( stdin 입력을소문자와대문자로번갈아가면서변환해 stdout 으로출력 ) tee ( stdin 입력을파일과 stdout 으로동시에출력 ) 또한다음두개의파일이있다고가정하자. File1: asdf ASDF File2: povijh 다음각과정에서화면출력 ( 또는파일출력 ) 을예측하세요 : $./tolower < File1 $ mkfifo fifo1 $./toupper < File1 tee File3 $./tolower < fifo1 & $./toupper < File1 > fifo1 $./tomixed < File1./toupper