문제:
다음 UNIX 시스템 호출을 이용하는 프로그램(UNIX System V 기준)을 보고 물음에 답하시오.
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
void fatal(char *p) {
perror(p);
exit(1);
}
int main() {
int p_id;
switch (p_id = fork()) {
case -1: // fork 실패
fatal("실패");
break;
case 0: // 자식 프로세스
execl("/bin/ps", "ps", "-ed", (char *)0);
fatal("execl 실패");
break;
default: // 부모 프로세스
wait((int *)0);
printf("ps 수행 완료\n");
exit(0);
}
}
가) 위 프로그램의 동작 과정 설명 (fork, execl 시스템 호출 중심)
답변:
프로그램의 동작 과정
1. fork 시스템 호출:
• 이 프로그램은 fork() 시스템 호출을 통해 프로세스를 복제하여 자식 프로세스를 생성합니다.
• fork()는 실행 시점에 호출한 프로세스를 복제하고, 부모 프로세스와 자식 프로세스를 생성합니다. 호출이 성공하면 부모 프로세스에서는 자식 프로세스의 PID가 반환되고, 자식 프로세스에서는 0이 반환됩니다. 만약 fork()가 실패하면 -1이 반환됩니다.
2. switch 문을 통한 분기 처리:
• fork()의 반환값을 switch 문으로 나눠, 부모 프로세스와 자식 프로세스의 동작을 구분합니다.
• case -1: fork() 실패 처리
• 만약 fork()가 실패하여 -1을 반환하면, fatal("실패") 함수를 호출하여 오류 메시지를 출력하고 프로그램을 종료합니다.
• case 0: 자식 프로세스
• 자식 프로세스에서는 execl() 시스템 호출을 사용하여 새로운 프로그램을 실행합니다.
• execl("/bin/ps", "ps", "-ed", (char *)0);은 /bin/ps 프로그램을 실행하여, 현재 시스템에 실행 중인 모든 프로세스를 리스트로 출력합니다. 옵션 -e는 모든 프로세스를 표시하고, -d는 데몬 프로세스를 제외한 프로세스를 표시하는 옵션입니다.
• 만약 execl() 호출이 실패하면, 자식 프로세스는 fatal("execl 실패") 함수를 호출하여 오류 메시지를 출력하고 종료합니다.
• execl을 호출하면 이전의 프로세스 이미지가 새로운 프로그램(ps 명령어)으로 대체되므로, execl 이후의 코드는 실행되지 않습니다.
• default: 부모 프로세스
• 부모 프로세스는 wait() 시스템 호출을 통해 자식 프로세스가 종료될 때까지 대기합니다.
• 자식 프로세스가 정상적으로 ps 명령어를 실행하고 종료되면, 부모 프로세스는 wait() 호출을 통해 자식 프로세스의 종료를 확인한 후, "ps 수행 완료" 메시지를 출력하고 종료됩니다.
요약:
• 이 프로그램은 fork()를 통해 자식 프로세스를 생성하고, 자식 프로세스에서 execl()을 사용하여 ps 명령어를 실행합니다. 부모 프로세스는 wait()를 통해 자식이 ps 명령을 완료할 때까지 대기한 후, “ps 수행 완료” 메시지를 출력하고 종료합니다.
나) 동일한 결과를 얻기 위한 UNIX 명령어
위 프로그램의 동작과 동일한 결과를 얻기 위해 다음과 같은 UNIX 명령어를 사용할 수 있습니다.
ps -ed
echo "ps 수행 완료"
설명:
1. ps -ed: 현재 시스템에 실행 중인 모든 프로세스를 표시하며, 데몬 프로세스를 제외합니다.
2. echo "ps 수행 완료": “ps 수행 완료” 메시지를 출력하여 프로그램이 완료되었음을 알립니다.
이 명령어는 위의 프로그램이 수행하는 동작과 동일한 결과를 제공합니다.