학번 : 이름 1. 다음프로그램실행결과를예측하시오. $./a.out & [1] 7216 $ kill -USR1 7216 $ kill -USR2 7216 2. 아래학생이작성한쓰레드코드의문제점을설명하시오. void* thread_main() pthread_mutex_t lock=pthread_mutex_initializer; pthread_mutex_lock(&lock); // access some shared resources pthread_mutex_unlock(&lock);
3. 다음프로그램의출력물과출력순서를변수별, 스레드별로예측하시오. #include "apue.h" int var=1; void* mythread(void* arg) sleep((int)(intptr_t)arg); static int glob = 31; int nvar=30; glob++; /* modify variables */ var++; nvar++; printf("%d %d %d\n", glob, var, nvar); return NULL; int main(void) void* res; pthread_t thread[2]; pthread_create(&thread[0], NULL, mythread, 1); pthread_create(&thread[1], NULL, mythread, 2); pthread_join(&thread[0], &res); pthread_join(&thread[1], &res); return 0; 4. (a) 다음프로그램의출력을예측하시오. #include <stdio.h> int main() int pip[2]; FILE* fp0; FILE* fp1; char buffer[100]="a"; pipe(pip); fp0=fdopen(pip[0], "r"); fp1=fdopen(pip[1], "w"); fprintf(fp1, "%s", "c"); fclose(fp1); fscanf(fp0, "%s\n", buffer); fprintf(stdout, buffer); printf("\n");
(b). 사용자가터미널에서다음명령을입력했을때, 다음세개의프로세스에서호출되는함수를아래보기중나열하시오. 단, 모든 dup2 명령은 Child process 가수행한다고가정하시오. 명령 : $ cat < main.c grep main 보기 : (1) pipe(rd, WR) // 파일디스크립터 RD ( 입력 ) 와 WR( 출력 ) 을연결하는파이프생성 (2) fork, (3) waitpid, (4) FD=open('main.c'), (5) dup2(wr,1) (6) dup2(fd,0), (7) dup2(rd,0) Shell process: Child process 1( exec( cat )) : Child process 2( exec( grep )) : sigprocmask 함수설명 ( 문제 5 용 ):
5. 이전장에나오는 sigprocmask 함수의설명을참고하여다음프로그램의출력물과그출력물이화면이표시되는시점을예측하세요. ( 힌트 : 각줄이표시되는시점은다음 6 가지중하나. (1) 프로그램수행직후, (2) 5 초후 (3) 10 초후 (4) 15 초후 (5) 20 초후 (6) 30 초후 ) #include "apue.h" #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"); sleep(15); printf("done!\n"); exit(0); 실행내용 : $./a.out & [1] 21413 ( 21413 이라는 process id 로백그라운드에서수행중.) $ kill -USR1 21413 (5 초가지난후이명령이실행된다고가정.) $ kill -USR1 21413 (10 초가지난후이명령이실행된다고가정.) $ kill -USR1 21413 (20 초가지난후이명령이실행된다고가정.) ( 모든시간은프로그램시작시간기준임 ) 결과물및각줄의출력시점 :
6. 다음은클라이언트가보낸메시지를처리하는간단한서버프로그램의소스코드이다. #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); printf("0\n"); bind(server_sockfd, (struct sockaddr *)&server_address, server_len); printf("1\n"); listen(server_sockfd, 5); printf("2\n"); client_sockfd=accept(server_sockfd, (struct sockaddr *)&client_address, &client_len); printf("3\n"); read(client_sockfd, string, 256); printf("%s\n", string);... 만약클라이언트가서버에연결후아래코드를실행했을때각줄실행전후서버의출력을예측하세요. connect(sockfd, (struct sockaddr *)&address, sizeof(address)); // 연결된다고가정. write(sockfd, "asdf", 5);
7. 다음두개의소스코드를보고, 아래명령문의출력을예측하세요. ( 단 real user-id 는 1000 가정, 공란총 2 개채우세요 ) a.out (a.c): #include "apue.h" int main(int argc, char *argv[]) system(argv[1]); exit(0); b.out (b.c): #include "apue.h" int main(void) printf("real uid=%d effective uid=%d\n", getuid(), geteuid()); return 0; $./a.out./b.out $ sudo chown root./a.out $ sudo chmod +s./a.out $./a.out./b.out 8. a. 위에서만들어진 a.out 은보안상위험하다. 그이유를설명하고, 그위험성을피하기위해 a.c 를수정하시오. Hint: seteuid(new_effective_user_id) 함수사용할것. b. Saved SUID 개념이필요한이유를위시나리오와관련하여설명하세요. a.c 는반드시 effective root 권한이필요한프로그램이지만, 때때로임의의다른프로그램을호출해야한다고가정하세요.
9. 다음 4 가지프로그램이구현되어있다고가정하자../tolower ( stdin 입력을소문자로변환해 stdout 으로출력하는프로그램 )./toupper ( stdin 입력을대문자로변환해 stdout 으로출력하는프로그램 )./tomixed ( stdin 입력을소문자와대문자로번갈아가면서변환해 stdout 으로출력 ) tee ( stdin 입력을파일과 stdout 으로동시에출력 ) 또한다음두개의파일이있다고가정하자. File1: asdf ASDF File2: povijh 다음각과정에서화면출력, 파일출력, 프로그램종료등을 모두 예측하세요 : $./tolower < File1 $ mkfifo fifo1 $./tolower < fifo1 > File3 & $./toupper < File1 tee fifo1 $ cat File3 $./toupper < File3 > fifo1 아래정의를참고하여 10 번문항을푸세요.
10. 다음은채팅프로그램의클라이언트소스코드이다. 공란을채우시오. ( 총 6 개 ) void prompt() printf("<you> "); fflush(stdout); main (int argc, char *argv[]) int len, rc, sockfd, max_sd; char send_buf[4096], recv_buf[4096]; struct sockaddr_in serv_addr; fd_set master_set, select_result; sockfd = socket(af_inet, SOCK_STREAM, 0)); memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(server_port); inet_pton(af_inet, argv[1], &serv_addr.sin_addr); connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr); FD_ZERO(&master_set); FD_SET(, & master_set); FD_SET(, & master_set); max_sd=max(, ); printf("connected to remote host. Start sending messages.\n"); prompt(); while(1) memcpy(&select_result, &master_set, sizeof(master_set)); rc = select(max_sd + 1, &select_result, NULL, NULL, NULL); if( ) gets(send_buf); send(sockfd, send_buf, strlen(send_buf), 0); prompt(); else if( ) rc = recv(sockfd, recv_buf, 4096, 0); if (rc < 0) exit(-9); // recv failed if (rc == 0) printf("server disconnected\n"); close(sockfd); exit(0); recv_buf[rc]=0; // make null terminated string printf("\r%s\n", recv_buf); prompt(); else // timed out close(sockfd); return 0; close(sockfd); return 0;
11. 위프로그램을 select 를사용하지않고구현할경우, 아래와같이구현이가능하다. int main() 생략... if( connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) exit(4); pthread_t a, b; pthread_create(&a, NULL, threada, NULL); pthread_create(&b, NULL, threadb, NULL); pthread_join(a, NULL); pthread_join(b,null); close(sockfd); if(n < 0) exit(5); 아래에 threada 와 threadb 함수의 pseudo code 를작성하시오.