56
Week5~7 : 운운운운 Chapter 4~6: 운운운운운 운운운 fork() – wait() – exec() 운운운운 : 운 운 운

Week5~7 : 운영체제 Chapter 4~6: 프로세스와 쓰레드 fork() – wait() – exec()

Embed Size (px)

DESCRIPTION

Week5~7 : 운영체제 Chapter 4~6: 프로세스와 쓰레드 fork() – wait() – exec(). 담당교수 : 최 윤 정. 병행처리 를 위한 Basic Function. fork spawns new process Called once, returns twice exit terminates own process Called once, never returns Puts it into “zombie” status - PowerPoint PPT Presentation

Citation preview

Page 1: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

Week5~7 : 운영체제

Chapter 4~6: 프로세스와 쓰레드

fork() – wait() – exec()

담당교수 : 최 윤 정

Page 2: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

2

병행처리를 위한 Basic Function

fork spawns new process

Called once, returns twice

exit terminates own process

Called once, never returns

Puts it into “zombie” status

wait and waitpid wait for and reap terminated

children

execve runs new program in existing process

Called once, (normally) never returns

Page 3: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

3

fork: Creating New Processes

int fork(void)

creates a new process (child process) that is identical to the call-

ing process (parent process)

returns 0 to the child process

returns child’s pid to the parent process

Fork is interesting (and often confusing) because

it is called once but returns twice

pid_t pid = fork();if (pid == 0) { printf("hello from child\n");} else { printf("hello from parent\n");}

Page 4: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

4

Understanding fork

pid_t pid = fork();if (pid == 0) { printf("hello from child\n");} else { printf("hello from parent\n");}

Process npid_t pid = fork();if (pid == 0) { printf("hello from child\n");} else { printf("hello from parent\n");}

Child Process m

pid_t pid = fork();if (pid == 0) { printf("hello from child\n");} else { printf("hello from parent\n");}

pid = m

pid_t pid = fork();if (pid == 0) { printf("hello from child\n");} else { printf("hello from parent\n");}

pid = 0

pid_t pid = fork();if (pid == 0) { printf("hello from child\n");} else { printf("hello from parent\n");}

pid_t pid = fork();if (pid == 0) { printf("hello from child\n");} else { printf("hello from parent\n");}

hello from parent hello from childWhich one is first?

Page 5: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

5

Fork Example #1

Parent and child both run same code Distinguish parent from child by return value from fork

Start with same state, but each has private copy Including shared output file descriptor Relative ordering of their print statements un-

definedvoid fork1(){ int x = 1; pid_t pid = fork(); if (pid == 0) {

printf("Child has x = %d\n", ++x); } else {

printf("Parent has x = %d\n", --x); } printf("Bye from process %d with x = %d\n", getpid(), x);}

Page 6: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

6

Fork Example #2

Both parent and child can continue forking

void fork2(){ printf("L0\n"); fork(); printf("L1\n"); fork(); printf("Bye\n");}

L0 L1

L1

Bye

Bye

Bye

Bye

Page 7: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

7

Fork Example #3

Both parent and child can continue forking

void fork3(){ printf("L0\n"); fork(); printf("L1\n"); fork(); printf("L2\n"); fork(); printf("Bye\n");} L1 L2

L2

Bye

Bye

Bye

Bye

L1 L2

L2

Bye

Bye

Bye

Bye

L0

Page 8: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

8

Fork Example #4

Both parent and child can continue forkingvoid fork4(){ printf("L0\n"); if (fork() != 0) {

printf("L1\n"); if (fork() != 0) { printf("L2\n"); fork();}

} printf("Bye\n");}

L0 L1

Bye

L2

Bye

Bye

Bye

Page 9: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

9

Fork Example #5

Both parent and child can continue forkingvoid fork5(){ printf("L0\n"); if (fork() == 0) {

printf("L1\n"); if (fork() == 0) { printf("L2\n"); fork();}

} printf("Bye\n");}

L0 Bye

L1

Bye

Bye

Bye

L2

Page 10: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

10

exit: Ending a process

void exit(int status) exits a process

Normally return with status 0 atexit() registers functions to be executed

upon exitvoid cleanup(void) { printf("cleaning up\n");}

void fork6() { atexit(cleanup); fork(); exit(0);}

Page 11: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

11

Zombies

Idea When process terminates, still consumes system re-

sources Various tables maintained by OS

Called a “zombie” Living corpse, half alive and half dead

Reaping Performed by parent on terminated child Parent is given exit status information Kernel discards process

What if parent doesn’t reap? If any parent terminates without reaping a child, then

child will be reaped by init process So, only need explicit reaping in long-run-

ning processes e.g., shells and servers

Page 12: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

12

linux> ./forks 7 &[1] 6639Running Parent, PID = 6639Terminating Child, PID = 6640linux> ps PID TTY TIME CMD 6585 ttyp9 00:00:00 tcsh 6639 ttyp9 00:00:03 forks 6640 ttyp9 00:00:00 forks <defunct> 6641 ttyp9 00:00:00 pslinux> kill 6639[1] Terminatedlinux> ps PID TTY TIME CMD 6585 ttyp9 00:00:00 tcsh 6642 ttyp9 00:00:00 ps

ZombieExample

ps shows child process as “defunct”

Killing parent allows child to be reaped by init

void fork7(){ if (fork() == 0) {

/* Child */printf("Terminating Child, PID = %d\n", getpid());exit(0);

} else {printf("Running Parent, PID = %d\n", getpid());while (1) ; /* Infinite loop */

}}

Page 13: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

13

linux> ./forks 8Terminating Parent, PID = 6675Running Child, PID = 6676linux> ps PID TTY TIME CMD 6585 ttyp9 00:00:00 tcsh 6676 ttyp9 00:00:06 forks 6677 ttyp9 00:00:00 pslinux> kill 6676linux> ps PID TTY TIME CMD 6585 ttyp9 00:00:00 tcsh 6678 ttyp9 00:00:00 ps

NonterminatingChild Example

Child process still active even though parent has terminated

Must kill explicitly, or else will keep running indefinitely

void fork8(){ if (fork() == 0) {

/* Child */printf("Running Child, PID = %d\n", getpid());while (1) ; /* Infinite loop */

} else {printf("Terminating Parent, PID = %d\n", getpid());exit(0);

}}

Page 14: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

14

wait: Synchronizing with Chil-dren

int wait(int *child_status) suspends current process until one of its

children terminates return value is the pid of the child process

that terminated if child_status != NULL, then the object it

points to will be set to a status indicating why the child process terminated

Page 15: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

15

wait: Synchronizing with Chil-dren

void fork9() { int child_status;

if (fork() == 0) { printf("HC: hello from child\n"); } else { printf("HP: hello from parent\n"); wait(&child_status); printf("CT: child has terminated\n"); } printf("Bye\n"); exit();}

HP

HC Bye

CT Bye

Page 16: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

16

wait() Example

If multiple children completed, will take in arbitrary order Can use macros WIFEXITED and WEXITSTATUS to get informa-

tion about exit status

void fork10(){ pid_t pid[N]; int i; int child_status; for (i = 0; i < N; i++)

if ((pid[i] = fork()) == 0) exit(100+i); /* Child */

for (i = 0; i < N; i++) {pid_t wpid = wait(&child_status);if (WIFEXITED(child_status)) printf("Child %d terminated with exit status %d\n",

wpid, WEXITSTATUS(child_status));else printf("Child %d terminate abnormally\n", wpid);

}}

Page 17: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

17

waitpid(): Waiting for a Specific Process

waitpid(pid, &status, options) suspends current process until specific process termi-

nates various options (see textbook)

void fork11(){ pid_t pid[N]; int i; int child_status; for (i = 0; i < N; i++)

if ((pid[i] = fork()) == 0) exit(100+i); /* Child */

for (i = N-1; i >= 0; i--) {pid_t wpid = waitpid(pid[i], &child_status, 0);if (WIFEXITED(child_status)) printf("Child %d terminated with exit status %d\n",

wpid, WEXITSTATUS(child_status));else printf("Child %d terminated abnormally\n", wpid);

}}

Page 18: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

18

execve: Loading and Running Pro-grams

int execve(

char *filename,

char *argv[],

char *envp[]

)

Loads and runs in current process:

Executable filename

With argument list argv

And environment variable list envp

Does not return (unless error)

Overwrites code, data, and stack

keeps pid, open files and signal con-

text

Environment variables:

“name=value” strings

getenv and putenv

Null-terminatedenv var strings

unused

Null-terminatedcmd line arg strings

envp[n] == NULLenvp[n-1]

envp[0]…

Linker vars

argv[argc] == NULLargv[argc-1]

argv[0]…

envp

argcargv

Stack bottom

Stack frame for main Stack top

environ

Page 19: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

19

execve Example

if ((pid = Fork()) == 0) { /* Child runs user job */ if (execve(argv[0], argv, environ) < 0) { printf("%s: Command not found.\n", argv[0]); exit(0); } }

envp[n] = NULLenvp[n-1]

envp[0]…

argv[argc] = NULLargv[argc-1]

argv[0]…

“ls”“-lt”“/usr/include”

“USER=droh”“PRINTER=iron”“PWD=/usr/droh”

environ

argv

Page 20: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

20

Unix Process Hierarchy

Login shell

ChildChildChild

GrandchildGrandchild

[0]

Daemone.g. httpd

init [1]

Page 21: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

21

Shell Programs : MultiTasking A shell is an application program that runs programs

on behalf of the user. sh Original Unix shell (Stephen Bourne, AT&T Bell

Labs, 1977) csh BSD Unix C shell (tcsh: enhanced csh at CMU and

elsewhere) bash “Bourne-Again” Shell int main() { char cmdline[MAXLINE];

while (1) {/* read */printf("> "); Fgets(cmdline, MAXLINE, stdin); if (feof(stdin)) exit(0);

/* evaluate */eval(cmdline);

} }

Execution is a sequence of read/evaluate steps

Page 22: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

22

Simple Shell eval Functionvoid eval(char *cmdline) { char *argv[MAXARGS]; /* argv for execve() */ int bg; /* should the job run in bg or fg? */ pid_t pid; /* process id */

bg = parseline(cmdline, argv); if (!builtin_command(argv)) {

if ((pid = Fork()) == 0) { /* child runs user job */ if (execve(argv[0], argv, environ) < 0) {

printf("%s: Command not found.\n", argv[0]);exit(0);

}}

if (!bg) { /* parent waits for fg job to terminate */ int status;

if (waitpid(pid, &status, 0) < 0)unix_error("waitfg: waitpid error");

}else /* otherwise, don’t wait for bg job */ printf("%d %s", pid, cmdline);

}}

Page 23: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

23

What Is a “Background Job”?

Users generally run one command at a timeType command, read output, type another command

Some programs run “for a long time”Example: “delete this file in two hours”

A “background” job is a process we don't want to wait for

unix> sleep 7200; rm /tmp/junk # shell stuck for 2 hours

unix> (sleep 7200 ; rm /tmp/junk) &[1] 907unix> # ready for next command

Page 24: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

24

Problem with Simple Shell Example

Our example shell correctly waits for and reaps fore-ground jobs

But what about background jobs? Will become zombies when they terminate Will never be reaped because shell (typically) will not terminate Will create a memory leak that could run the kernel out of memory Modern Unix: once you exceed your process quota, your shell can't

run any new commands for you: fork() returns -1

unix> limit maxproc # csh syntaxmaxproc 202752unix> ulimit -u # bash syntax202752

Page 25: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

25

ECF to the Rescue!

Problem

The shell doesn't know when a background job will finish

By nature, it could happen at any time

Regular control flow is “wait until running job completes,

then reap it”

Solution: Exceptional control flow

The kernel will interrupt regular processing to alert us when a

background process completes

In Unix, the alert mechanism is called a signal

Page 26: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

26

Signals A signal is a small message that notifies a process that an

event of some type has occurred in the system

akin to exceptions and interrupts

sent from the kernel (sometimes at the request of another process) to

a process

signal type is identified by small integer ID’s (1-30)

only information in a signal is its ID and the fact that it arrivedID Name Default Action Corresponding Event

2 SIGINT Terminate Interrupt (e.g., ctl-c from keyboard)

9 SIGKILL Terminate Kill program (cannot override or ignore)

11 SIGSEGV Terminate & Dump Segmentation violation

14 SIGALRM Terminate Timer signal

17 SIGCHLD Ignore Child stopped or terminated

Page 27: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

27

Sending Signal

Kernel sends (delivers) a signal to a des-

tination process by updating some state

in the context of the destination process

Page 28: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

28

Receiving a Signal

A destination process receives a signal when it is forced by

the kernel to react in some way to the delivery of the sig-

nal

Three possible ways to react:

Ignore the signal (do nothing)

Terminate the process (with optional core dump)

Catch the signal by executing a user-level function called signal han-

dler

Akin to a hardware exception handler being called in response to

an asynchronous interrupt

Page 29: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

29

GO!

Page 30: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

30

들어가기 전에 ..동기와 비동기의 의미를 실행으로 알아봅니다 .

그동안의 C code 는

1. 위에서 아래로 흘러내려오는 흐름 . 즉 , flow 가 있었습니다 .

폭포처럼 한번 떨어져 내려온 이상

for(),while(), goto 등 jump 하는 기능이 없으면 다시는 위로 올라갈 수 없는

구조였습니다 .

2. 게다가 동기적인 흐름을 따랐습니다 .

printf(“ 데이터를 입력하세요 : ”);

scanf(“%d”, &data);

printf(“ 입력을 받기 전까지 이후 구문은 출력되지 않습니다 .\n”);

printf(“ ######\n”);

그러나 , system call 은 , fork() 나 signal() 은 달랐습니다 . 동기 / 비동기적으로

수행됩니다 .

동기적 : wait(), sleep(), pause(), fopen().. 등

비동기적 : signal() // 시그널 받을 때까지 기다리지 않아요 .

다음의 코드를 다운받아 Visual C++ 에서 수행해보도록 하세요 .

http://home.konkuk.ac.kr/~cris/Class/2011/sp/fork-code/block.zip

방향키를 눌러서 bar 를 움직여 보세요 .

Page 31: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

31

source : http://home.konkuk.ac.kr/~cris/Class/2011/sp/fork-code/block.zip

이 소스의 동작은 별을 출력하면서도 Bar 를 욺직이고 있어요 .Bar 을 욺직이기 위해 방향 key 를 입력하는 동안별을 출력하는 부분이 멈추어 있지 않습니다 .만약 키를 입력받고자 scanf(); 나 getchar() 를 썼다면 ?입력받기전 출력부분도 ‘대기’합니다 . Why?!

while 루프 내부를 보면 ,GetAsyncKetState() 라는 함수가 쓰여져 있어요 .비동기식으로 키를 입력받아라 . 하는 함수죠 .(Khbit() 과 마찬가지 )해당 키가 눌려졌는지 아닌지를 catch 하여 눌려졌다면 동작합니다 . 동작상으로는 system call 에서 signal 과 유사한 부분이 있죠 ?

과제를 통해 조사해 보았겠지만 , 실행예를 통해 확인해 보세요 .

while(1){

…( 중략 )

if( GetAsyncKeyState(LEFT) ) bar_x--;else if(GetAsyncKeyState(RIGHT))

bar_x++;else if(GetAsyncKeyState(ESCAPE)) {

system("cls"); gotoxy(25,10);system(" 종료합니다 ."); break;

}….

}return 0;

Page 32: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

32

실습 전 알아두어야 할 것 process 에 대한 이해

프로세스 상태 : Ready , Running, Waiting, Terminated

ps 명령어로 status 보기 (#man ps 로 확인하세요 )

fork() – exec 계열함수 () 의 동작

부모 - 자식프로세스

자식은 .. 기본적으로 부모가 관리해야 한다 . (Reaping.)

만약 , 외부에서 부모프로세스만 kill -9 하면 부모만 종료 . 자식은 부모를 잃었으므로 ppid 도 함께 잃음 . ( 후 ppid

= 1)

따라서 강제종료 시에는 가장 하위자식부터 kill -9. ( 이제 하지 마세요 ^^)

부모는 자식을 작업 종료시 까지 기다려주고 , 자식프로세스는 부모프로세스에게 종료 요청을 해주자 .

자식은 낳는 것보다 잘 키우는 것이 더 어렵고도 중요합니다 . 자식이 어떻게 자라는지 (status) 죽음에 대해서도

관심을 가져야 해요 .

SIGNAL 을 이용하여 process 에 신호 (message) 를 보낼 수 있습니다 .

( 리눅스 : /usr/include/bits/signum.h 에 signal macro 정의 )

process 가 죽는 경우는 다양합니다 . 예 ) Kill -9 pid //kill –SIGKILL pid( 강제종료 ) vs. Kill -SIGTERM pid // terminated

System call

일반 C- 라이브러리 함수와 system call 함수는 다릅니다 .! fork(), execl(), wait(), signal( ) 등 ..

fork 함수 호출을 통한 프로세스 생성

Page 33: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

33

ps : process status Option :

-a : 모든 프로세스 상태 출력 -e : 현재 실행중인 모든 프로세서 상태 출력 -f : 프로세스 상태 full list 로 출력 -l : 프로세스 상태 long list 로 출력 -m : 메모리 정보를 출력 -t TTY : 지정한 TTY 를 가진 프로세스 정보 출력 -u : 사용자 이름 , 시작시간을 보여준다 -p PID : 지정한 PID 를 가진 프로세스 정보 출력 -u UID : 지정한 UID 를 가진 프로세스 정보 출력 -g GID : 지정한 GID 를 가진 프로세스 정보 출력

프로세스 상태보기 PID(Process ID) : 프로세스마다 주어지는 번호 TTY(Tele TYpewrite) : 명령어가 실행되는 터미널의 번호 STAT(STATe) : 실행되고 있는 프로세스 상태 R : 실행 중 혹은 실행될 수 있는 상태 S : sleep I : idle ( 비활동 상태 : BSD / 중간적 상태 : sysV) T : 정지된 상태 (suspend) Z : 좀비 (zombie) 프로세스 D : 디스크 관련 대기 상태 (BSD) P : 페이지 관련 대기 상태 (BSD) X : 메모리 확보를 위해 대기 중 (sys V) K : 사용 가능한 커널 프로세스 (aix) W : 스왑 out 된 상태 N : nice 되어진 상태 > : 우선 순위가 인위적으로 높아진 상태

START(START) : 프로세스가 시작된 시간

TIME(TIME) : CPU 가 사용한 시간

USER(USER) : 사용자의 이름

COMMAND(COMMAND) : 사용자가 실행한 명령어

UID(User ID) : 사용자의 ID

(Parent Group ID) : 사용자 부모 프로세스의 그룹 ID

SID(Session ID) : 세션 ID

PRI(PRIority) : 실행하는 우선 순위에 따른 프로세스

NI(Nice) : nice 에 의한 우선 순위에 따른 프로세스

RSS(Resident Set Size) : 프로세스가 사용하는 메모리의

크기

SZ(SiZe) : 프로세스가 사용하는 자료와 스택의

크기

SHRD(ShaReD) : 프로세스가 사용하는 공유 메모리

%CPU : 프로세스가 사용하는 CPU 점유율

%MEM : 프로세스가 사용하고 있는 메모리 점유율

WCHAN : 프로세스가 실행하고 있는 커널 루틴

Page 34: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

34

kill : 현재 수행중인 프로세서에게 시그널을 보낸다 # kill [ -signal ID ] PID // 보통 kill 명령은 프로세서를 죽이는 데에 사용된다 .

# kill –L // 시그널 종류 나열 , /usr/include/bits/signum.h 에 정의됨 시그널의 종류를 지정하지 않으면 프로세서를 종료시키는 의미로 디폴트 시그널 ID 15 번을 보내게 된다 .

1. SIGHUP(HUP) : 연결 끊기 . 프로세스의 설정파일을 다시 읽는데 사용된다 . 2. SIGINT(INT) : 인터럽트 3. SIGQUIOT(QUIT) : 종료 4. SIGILL(ILL) : 잘못된 명령 5. SIGTRAP(TRAP) : 6. SIGIOT(IOT) : IOT 명령 7. SIGBUS(BUS) : 버스 에러 8. SIGFPE(FPE) : 고정 소수점 예외 9. SIGKILL(KILL) : 죽이기 . 이 시그널은 잡히지 않는다 . 10. SIGUSR1(USR1) : 사용자 정의 시그널 1 11. SIGSEGV(SEGV) : 세그멘테이션 위반 12. SIGUSR2(USR2) : 사용자 정의 시그널 2 13. SIGPIPE(PIPE) : 읽을 것이 없는 파이프에 대한 시그널 14. SIGALRM(ALRM) : 경고 클럭 15. SIGTERM(TERM) : 소프트웨어 종료 시그널 , 일반적으로 kill 시그널이 전송되기 전에 전송된다 . 16. SIGKFLT : 코프로세서 스택 실패 17. SIGCHLD(CHLD) : 자식 프로세스의 상태변화 18. SIGCONT(CONT) : STOP 시그널 이후 계속 진행할 때 사용 19. SIGSTOP(STOP) : 정지 . 이 시그널 역시 잡을 수 없다 . 20. SIGTSTP(TSTP) : 키보드에 의해 발생하는 시그널로 Ctrl+Z 로 생성된다 .

Page 35: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

35

kill 시스템 콜 : Sending Sig-nals

void fork12(){ pid_t pid[N]; int i, child_status; for (i = 0; i < N; i++)

if ((pid[i] = fork()) == 0) while(1); /* Child infinite loop */

/* Parent terminates the child processes */ for (i = 0; i < N; i++) {

printf("Killing process %d\n", pid[i]);kill(pid[i], SIGINT);

}

/* Parent reaps terminated children */ for (i = 0; i < N; i++) {

pid_t wpid = wait(&child_status);if (WIFEXITED(child_status)) printf("Child %d terminated with exit status %d\n",

wpid, WEXITSTATUS(child_status));else printf("Child %d terminated abnormally\n", wpid);

}}

Page 36: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

36

Zombie 만들기 :// 부모는 종료했으나 , 죽지 않는 child, 이 child 는 어떻게 될가요 ?

void fork8(){ if (fork() == 0) { /* Child */ printf("Running Child, PID = %d\n",getpid()); while (1) ; /* Infinite loop */ } else { printf("Terminating Parent, PID = %d\n",getpid()); exit(0); }}

// 부모는 종료되기 전 , 종료하는 child - zombie 가 되죠 . void fork7(){ if (fork() == 0) {

/* Child */ printf("Terminating Child, PID = %d\n", getpid()); exit(0); } else { printf("Running Parent, PID = %d\n", getpid()); while(1)

//do something ; /* Infinite loop */ }}

부모보다 먼저 ( 아무 말없이 ) 종료되어 status 가 전달되지 않아서 , 자식 프로세스를 reaping 하지 못하는 경우 발생 . - 자식 process 를 기다려주거나 SIGNAL 을 이용하여 처리한다 . !

자식 프로세스는 종료되면서 성공적인 종료를 알리기 위해 0 값을 커널에 리턴합니다 .

그러나 , 이 때 , 커널은 자식 프로세스를 바로 종료시키지 않고 , 부모 프로세스에게 자식이 죽으며 전해준 값 (0) 이 전달될 때까지 기다려줘요 .

자식의 상태정보 값은 부모 프로세스가 커널에게 요청할 때에만 전달됩니다 .

부모가 요청없이 종료했으므로 자식의 신호는 부모에게 전달될 수 없고 , 이 때 자식은 작업은 종료했으나 메모리는 남아있는 zombie 상태가 됩니다 .

Page 37: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

37

앞 페이지의 두 예제 소스를 보면

부모와 자식간 오고 가는 대화가 없어도 너무 없어요 .

자식이 무엇을 하는지 말든지에 관심없이 자기일 끝났다고 그냥 종료하는 부모와 ..

-> 자식은 ppid() 부모를 잃고 떠돌다가 init 의 자식으로 들어가죠

부모가 있는 자식이되 일련의 허락없이 ( 제멋대로 ) 종료해버리는 자식이 있죠 .

무릇 , 참된 부모는 ..

자식이 어떤 상황에 놓여있는지 파악해야 하며

자식을 기다릴 줄 알아야 하고

무릇 , 자식이라면

자신의 현재 상황을 부모에게 알려주어야 하겠습니다 .

부모에게는 기다림을 권고하고

자식의 학교생활이 궁금할 때 선생님의 도움을 받아

자식 프로세스의 상황을 알아볼 수 있듯이

시스템의 도움을 받습니다 . system call

( C 라이브러리 함수가 아니에요 !)

wait() 와 signal()

Page 38: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

38

wait() 시스템 콜

* fork 를 사용하여 child process 를 생성하는 경우 parent process 는 child

process 를 wait 하여 child process 가 zombie 가 되는 것을 막아야 한다 . 자식 프로세스가 종료되면 , 리눅스 커널은 그것의 메모리를 해제하고 파일을 닫는다 . 종료상태는

프로세스의 프로세스 테이블에 저장된다 .

but, 부모프로세스가 자식프로세스의 종료에 대한 관심없이 계속 동작을 수행하는 동안 하나 이상의

이유로 자식프로세스가 종료됐을 때 , 부모프로세스가 이 정보를 가져갈 때까지의 상태에 있는

자식프로세스를 좀비라고 한다 . (Reaping 되지 않은 )

일반적으로는 SIGCHLD 처리 함수안에서 wait, waitpid 함수를 사용하여

child process 가 zombie 가 되는 것을 막는다 .

wait(), waitpid() : process 의 종료나 signal 함수호출신호를 기다리는 경우

호출한 영역에서 일시중지

pause() : signal 을 기다리는 경우

모르는 명령어가 있다면

무작정 모른다 . 버티지 말고

# man 2 wait 를 실행해보도록 .!

Page 39: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

39

#man 사용법 보는 방법 # man man : man 명령어에 대한 manual.

The table below shows the section numbers of the manual fol-lowed by the types of pages they contain.

1 Executable programs or shell commands 2 System calls (functions provided by the kernel) 3 Library calls (functions within program libraries) 4 Special files (usually found in /dev) 5 File formats and conventions eg /etc/passwd 6 Games 7 Miscellaneous (including macro packages and conventions), e.g. man(7), groff(7) 8 System administration commands (usually only for root) 9 Kernel routines [Non standard]

따라서 쉘명령어 wait 에 대한 manual # man 1 wait

시스템 콜 wait 에 대한 manual # man 2 wait

Page 40: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

40

wait(), waitpid() 함수를 통해 알 수 있는 child 정보 (앞으로는 헤매지만 말고 스스로 찾아보세요… .!!!!!!!!!!)

(#man 2 wait 중 .)

wait 함수 : 자식이 종료될 때까지 , 또는 현재 프로세스를 종료시키거나 시그널 처리 함수를

호출하는 행동을 하는 신호가 전달될 때까지 현재 프로세 스의 실행을 일시 중지시킨다 . 만일

자식이 호출 시간에 이미 종료되었다면 ( 좀비 프로세스 ), 함수는 즉시 리턴한다 . 자식이

사용한 시스템 자원들은 모두 풀어진다 .

waitpid 함수 : pid 인자가 가리키는 자식이 종료될 때 까지 , 또는 현재 프로세스를

종료시키거나 시그널 처리 함수를 호출하는 행동을 하는 신호가 전달될 때까지 현재 프로세스의

실행을 일시 중지시킨다 . 만일 pid 로 지정된 자식이 호출 시간에 이미 종료되었다면 ( 좀비

프로세스 ), 함수는 즉시 리턴한다 .

status, 와 option ( 뒷장 )

pid_t wait(int *status)pid_t waitpid(pid_t pid, int *status, int op-tions);

상태정보를 담아오기 위한 그릇 . 주소 ! 를 보내야 겠죠 ?

Page 41: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

41

… ( 이어서 )

리턴되는 pid 값은 다음 중 하나이다 . < -1 : 프로세스 그룹 ID 가 pid 의 절대 값과 같은 어떤 자식 프로세스를 기다리라는 의미이다 . -1 : 어떤 자식 프로세스를 기다리라는 의미이다 ; 이것은 wait 에서 나타난 것과 같은 행동을 한다 . 0 : 프로세스 그룹 ID 가 호출 프로세스의 ID 와 같은 어떤 자식 프로세스를 기다리라는 의미이다 . > 0 : 프로세스 ID 가 pid 의 값과 같은 자식을 기다리라는 의미이다 .

options 의 값은 0 이거나 다음 상수의 어떤 것과 OR 이다 .

WNOHANG : 이것은 어떤 자식도 종료되지 않았다면 즉시 리턴하라는 의미이다 .

WUNTRACED : 이것은 멈추거나 상태가 보고되지 않은 자식들을 위해 역시 리턴하라는 의미이다 . 만일 status 가

NULL 이 아니라면 wait 또는 waitpid 는 status 가 가리키는 위치에 상태 정보를 저장한다 . 이 상태는 다음

매크로들로 평가된다 .( 이들 매크로는 인자로써 stat 버퍼 (int 값 !) 를 가지고 있다 . -- 버퍼에 대한 포인터가 아니다 !)

WIFEXITED(status) : 자식이 정상적으로 종료되었다면 non-zero 이다 .

WEXITSTATUS(status) : exit() 를 호출하기 위한 인자나 주 프로그램에서 return 문장을 위한 인자로써 설정되고 종료된

자식의 반환 코드의 최하위 8 비트를 평가한다 . 이 매크로는 WIFEXITED 가 non-zero 를 반환할 때만 평가된다 .

WIFSIGNALED(status) : 만일 자식 프로세스가 잡혀지지 않은 신호때문에 종료되었다면 참을 반환한다 .

WTERMSIG(status) : 자식 프로세스를 종료하도록 야기한 신호의 숫자를 반환한다 . 이 매크로는 만일 WIFSIGNALED 가

non-zero 를 반환할 경우만 평가된다 .

WIFSTOPPED(status) : 반환의 원인이 된 자식 프로세스가 현재 정지되어 있다면 참을 반환한다 .; 이것은 이 함수가 WUN-

TRACED 를 사용했을 때만 가능하다 .

WSTOPSIG(status) : 자식을 정지하도록 야기한 신호의 숫자를 반환한다 . 이 매크로는 WIFSTOPPED 가 non-zero 를 반환할

경우만 평가된다 .

pid_t wait(int *status)pid_t waitpid(pid_t pid, int *status, int op-tions);

Page 42: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

42

이제 wait( ) 를 적용해 봅시다 . (1) : int wait(int *child_status).

// 부모는 종료했으나 , 죽지 않는 child, 이 child 는 어떻게 될가요 ?

void fork8(){ int i = 0; if (fork() == 0) {

/* Child */printf("Running Child, PID = %d\n",getpid());while (i < 20) printf(“I want to play~!”);

} else {printf("Terminating Parent, PID = %d\n", getpid());exit(0);

}}

// 자식이 종료되기를 기다렸다가 부모도 종료합니다 .

void fork8-1(){ int status; if (fork() == 0) {

/* Child */printf("Running Child, PID = %d\n",getpid());while (i < 20) printf(“[%d] : I want to play~! \n”, i);

} else {printf(“Good Parent, PID = %d\n", getpid());

wait(&status);printf(“Terminating.! \n”);exit(0); // 이 라인이 없어도 종료는 됩니다 .

}}

무한루프를 마냥 기다릴 수는 없으므로 변경

여기서 , 자식이 종료되기를 wait.!

Page 43: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

43

이제 wait( ) 를 적용해 봅시다 . (2) : int wait(int *child_status).#define N 5int main(){ pid_t pid[N]; // 여러 개의 자식을 만들어 pid 를 저장하기 위한 배열 . int i, child_status;

for (i = 0; i < N; i++){ if ((pid[i] = fork()) == 0){ sleep(1); printf("child : %d \n", getpid()); exit(100+i); /* Child 가 종료되면서 100+i 를 들고 갑니다 . } else printf("parent[%d]:%d \n", i, getpid()); }

for (i = 0; i < N; i++) { wpid = wait(&child_status); if (WIFEXITED(child_status)) printf("Child %d terminated with exit status %d\n", wpid, WEXITSTATUS(child_status)); else printf("Child %d terminate abnormally\n", wpid); }}

parent[0]:11136parent[1]:11136parent[2]:11136parent[3]:11136parent[4]:11136child : 11137child : 11139child : 11141Child 11137 terminated with exit status 100Child 11139 terminated with exit status 102Child 11141 terminated with exit status 104child : 11138Child 11138 terminated with exit status 101child : 11140Child 11140 terminated with exit status 103

Page 44: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

44

wait() 로는 부족한 일

언제 자식 프로세스가 종료될 것인지를 커널이 예측할 수 있을가 ?

무작정 기다리말고 , 자식 프로세스가 종료되는 순간에

커널이 부모 프로세스에게 자식 프로세스가 종료됨을 알려주도록 하자 !

시그널 핸들링 개념의 동기 : code 에 여러 시그널 핸들러를 설치하여 테스트해 봅니다 .

시그널이 발생했을 때 , 미리 준비해 놓은 함수가 호출되도록 연결해주는 작업

signal 함수 / sigaction 함수를 통한 핸들링

(sigaction 함수가 시스템 입장에서는 보다 안정적 .)

Page 45: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

45

이제 Signal 을 받아 처리해봅시다 .SIGNAL 과 Handler 의 간단한 예 : #include <stdio.h>#include <unistd.h>#include <sys/types.h>#include <sys/wait.h>#include <sys/stat.h>#include <signal.h>

void handler1(int sig){

printf(” process(%d) 에 signal[%d] 이 전달됨 \n”, getpid(), sig);// exit(0); 이 부분을 주석처리 할 때와 하지 않을 때의 차이를 알 수 있겠지요 ?

}

int main(){

pid_t pid, ppid;

signal(SIGINT, handler1); //SIGINT 가 들어오면 handler 를 호출signal(SIGCHLD, handler1); //SIGCHLD 가 들어오면 handler 를 호출 , handler2 를 만들어 호출할 수도 있겠죠 ?

// …..

if (fork() == 0) {

printf("Running Child, PID = %d\n", getpid());

while(1) ; //무한루프} else {

printf("Running Parent, PID = %d\n", getpid());

while(1) ; //무한루프 }

}

// 부모와 자식 둘 다 무한 루프 상태 , wait() 는 적합하지 않아요 . Why?!

// signal 을 이용하여 어떤 처리를 할 수 있을까 .

// 일단 , 백그라운드 동작 상태 , 혹은 다른 쉘에서 SIGNAL 을 보내주어야 합니다 .

// 1. kill -9 를 이용하여 각각의 프로세스를 강제종료가 가능하다 . 단 자식먼

저 .

// 2. SIGNAL handler 를 설치하여 처리한다 .

// 또는 , 소스 내부에서 kill() 함수를 통해 SIGNAL 을 전달해야 합니다 .(slide

18, 22)

Page 46: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

46

이제 wait() 와 SIGNAL()을 적용해 봅시다 .

#include <unistd.h>#include <string.h>#include <stdio.h>#include <sys/types.h>#include <sys/wait.h>#include <signal.h>

void zombie_handler(){ int status; int spid;

spid = wait(&status);

printf(" 자식프로세스 wait 성공 \n");

printf("========================\n");

printf("PID : %d\n", spid);

printf("Exit Value : %d\n", WEXITSTATUS(status));

printf("Exit Stat : %d\n", WIFEXITED(status));}

int main(){ int pid; int status; int spid; int i;

// SIGCHLD 에 대해서 시그널핸들러를 설치한다 . signal(SIGCHLD, zombie_handler);

for (i = 0; i < 3; i++) { pid = fork(); int random_value = (random()%5)+3; if (pid == 0) { // 랜덤 값을 이용하여 기다린 후 종료한다 . printf("I will be back %d %d\n", random_value, getpid()); sleep(random_value); return random_value; } } // ( 동기함수 ) 키보드 대기 , ( 모든 자식이 죽을 때 즈음 키 입력 ) getchar(); // 너무 빨리 치면 어떤 상황이 올까요 ?

printf(" 종료합니다 .\n\n");}

Page 47: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

47

wait(&status) 만으로도 상태정보를 읽어와 해석할 수 있는데

waitpid() 는 왜 사용할까요 ?

자식이 여러 개인 경우라면 wait() 로는 곤란하겠죠 ?

이미 종료했는데 마냥 임의의 자식을 wait() 하라고 하면 이제 block-

ing 상태에 이릅니다 .

waitpid() 의 적용예는 여러분이 조사해보도록 하세요 .

( 중간 / 기말에 반영하도록 하겠습니다 .)

Page 48: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

48

이제 다양한 SIGNAL 을 보내봅니다 . SIGSEGV 유발하는 scanf.c

void handler(int sig){ printf(” process(%d) 에 signal[%d] 이 전달됨 \n”, getpid(), sig); exit(0);}int main() { int i=0; int a[5]={0}; char str[5]; printf("scanf 명령 중 SIGSEGV, SIGABRT \n");

signal(SIGSEGV, handler); signal(SIGABRT, handler); while(1) { scanf("%s", str); printf("str = %s \n", str); a[i] = i; printf("a[%d] = %d \n", i, i); i++; }}

[root@localhost test]# ./scanfscanf 명령 중 SIGSEGV, SIGABRT1346798abcdefgad;kja;dksfja;kdsfadsfsdafadsfsdfadsfasdfasdfstr = %Error : Segmentation Fault !!

[root@localhost test]# ^C

Page 49: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

49

Kill() 를 통해 Signal 을 보내봅니다 . void int_handler(int sig) {

printf("Process %d received signal %d\n", getpid(), sig);

exit(0);

}

void fork13() {

pid_t pid[N];

int i, child_status;

signal(SIGINT, int_handler);

for (i = 0; i < N; i++) {

if ((pid[i] = fork()) == 0) while(1) ; /* child infinite loop

}

for (i = 0; i < N; i++) {

printf("Killing process %d\n", pid[i]);

kill(pid[i], SIGINT);

}

for (i = 0; i < N; i++) {

pid_t wpid = wait(&child_status);

if (WIFEXITED(child_status)) printf("Child %d terminated with exit status %d\n", ,

WEXITSTATUS(child_status));

else printf("Child %d terminated abnormally\n", wpid);

}

}

# ./forksKilling process 25417Killing process 25418Killing process 25419Killing process 25420Killing process 25421Process 25417 received signal 2Process 25418 received signal 2Process 25420 received signal 2Process 25421 received signal 2Process 25419 received signal 2Child 25417 terminated with exit status 0Child 25418 terminated with exit status 0Child 25420 terminated with exit status 0Child 25419 terminated with exit status 0Child 25421 terminated with exit status 0#

Page 50: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

50

Internal Signal 의 예 : Alarm ( 동기식 signal)/* * internal.c - A program that responds to interally generated events (SIGALARM signals) */#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <signal.h>

int beeps = 0;

/* SIGALRM handler */void handler(int sig) {

printf("BEEP\n"); fflush(stdout);

if (++beeps < 10) alarm(2); //2초마다 SIGALRM 전송 else { printf("BOOM!\n"); exit(0); }}

int main() {

printf(" alarm(0) 일 때 종료 "); signal(SIGALRM, handler); alarm(2); /* send SIGALRM in 1 second */

while (1) { sleep(1); printf(".");

if(beeps > 3) alarm(0); // 알람 끄기 /* handler returns here */ }}

Page 51: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

51

External Signal : ( 비동기식 sig-nal)

/* * external.c - A program that responds to externally * generated events (ctrl-c) */#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <signal.h>

void handler(int sig) { printf("You think hitting ctrl-c will stop the bomb?\n"); sleep(2); printf("Well..."); fflush(stdout); printf("OK\n"); // exit(0); 여러 번의 시그널을 받아보기 위해서 주석처리하고 수행해 보세요 .}

int main() {

printf(" backround 수행후 ctrl+c 또는 kill -SIGINT pid 로 SIGINT 를 전송 \n"); signal(SIGINT, handler); /* installs ctl-c handler */ while(1) { }}

[root@localhost test]# ./external &[root@localhost test]# ps PID TTY TIME CMD10907 pts/12 00:00:00 bash11217 pts/12 00:00:03 external11223 pts/12 00:00:00 ps[root@localhost test]# kill -2 11217[root@localhost test]# You think hitting ctrl-c will stop the bomb?kill -2 11217Well...OK [root@localhost test]# kill -2 11217[root@localhost test]# You think hitting ctrl-c will stop the bomb?Well...OK[root@localhost test]# fg./external^CYou think hitting ctrl-c will stop the bomb?^CWell...OKYou think hitting ctrl-c will stop the bomb?^CWell...OKYou think hitting ctrl-c will stop the bomb?Well...

Page 52: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

52

시스템 콜 함수에 대해서는 더 조사해 보세요

http://

www.joinc.co.kr/modules/moniwiki/wiki.php/Site/Assembly/Documents/a

rticle_linux_systemcall_quick_reference

파일 및 파이프

open(), read(), write(), close() …

seek(), fstat(); ..

popen() //process 의 stdout 을 파일로 받는다 .

chmod(), chown();

pipe() …

Proccess 제어

fork(), getpid(), kill(), signal(), semaphore() 등

기타

공유메모리 관련 : shmget()

시스템 시간 : time()

(Non-Logical Jump 는 skip 합니다 .) 수고했습니다 .!!!

Page 53: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

53

SIGNAL 읽어보기 :

기본 1 : 시그널 처리기 http://

www.joinc.co.kr/modules/moniwiki/wiki.php/Site/system_programing/Signal/SignalHow

기본 2 : 시그널 처리기 http://

www.joinc.co.kr/modules/moniwiki/wiki.php/Site/system_programing/Signal/SignalHow2

sigaction : 좀더 잘 처리하기 http://

www.joinc.co.kr/modules/moniwiki/wiki.php/man/2/sigaction?cx=002661009167463862046%3A8oq6cxlfibu&cof=FORID%3A9&q=sigaction&sa=Search&ie=EUC-KR#1257

Page 54: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

54

A,B 반 Q&A

Q1) 기본이해는 쉬운데 시험문제가 과제 , 응용이 어렵습니다

A) 매무 평이한 질문이면서 또 , 매우 심각한 질문이기도 합니다 .

진정 ‘기본’을 이해할 수 있었다면 이제 다음으로 진행할 수 있어야 합니다 . 예를 들어 ‘숫자’를 알고 ‘더하기’의 의미를 이해했다면 , 그리고

1+2, 3+4, 5+6 을 연습했다면 8+9 도 , 21+34 에 대해서도 계산할 수 있어야 합니다 .

다음으로 진행하기가 힘들다면 .., 지금 내가 ‘기본’을 이해하고 있는 것이 사실인가 ?

이해했다고 믿는 것은 아닌가 ? 에 대해 한번쯤 의문을 가져야 하겠습니다 . 그 후 , 다시

개념의 추상화 구체화 하여 이해하려는 시도가 있어야 하겠습니다 .

Page 55: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

55

Q2) 부모프로세스가 죽을 때 자식프로세스가 같이 죽는게 맞나요 ?

A) 일반적으로는 , 부모가 정상종료 / 비정상종료 할 때 , 멀쩡히 살아있는

자식을 데려가 함께 죽여버리지는 않습니다 . Reaping. 즉 자식이

사용하던 자원을 거두어주는 역할을 해야하므로 먼저 죽는 일은 없도록

해야 합니다 .!

( 일부러 죽는 경우는 있습니다만 , 그전에 어떠한 처리가 필요한 거죠 )

그래서 부모는 자식이 살아있는 한 죽지않도록 waiting 을 해주어야 하고

자식이 최소한 죽었는지 살았는지의 signal 을 요청하여 catch 해야

합니다 .

슬라이드 앞장부터 큰 제목을 위주고 다시 읽어본 후 , 소스를 분석해보도록

하세요 .

Page 56: Week5~7  :  운영체제 Chapter  4~6:  프로세스와 쓰레드 fork() – wait() – exec()

56

Q3) fork() 는 어떤 프로그램 만들 때 자주 쓰이나요 ?

A) 흔히 .. 할 일은 많은데 시간은 제한되어있고 몸은 하나밖에 없어서 아쉬울 때가 많습니다 . 몸이

하나만 더 있었다면 작업에 대한 역할을 분담할 수 있을 겁니다 . 크게 말하면 fork() 는 작업의

역할을 분담할 수 있도록 별도의 process 를 생성하는 거죠 . ( 반면 , Thread 는 한 프로세스

내에서의 작업을 분담하여 같이 한다는 의미가 더 큽니다 .)

흔히 요즘의 프로그램들은 ‘다중 xx 시스템’ ‘멀티 xx 시스템’이라는 타이틀이 많이 붙어요 .

연습문제 수준을 벗어나면 , 무조건 돌아가게만 만드는 프로그램이 아니라 , 복잡한 작업

네트웍상에서 여러 개의 프로그램이 서로 잘 동작하도록 하려면 새로운 일꾼도 필요합니다 .

시스템 서버와 협력하여 일련의 signal 도 송수신 해주어야 할 것입니다 . 내년에 많이 쓰게

되겠죠 ? ^^

Q4) fork(),sigaction() 등의 함수에 대한 사용법을 모르겠습니다 . 인자와 예제설명이

필요합니다 .

B) 음…요런 내용은 .. 사탕 줄 테니까 개별 방문 하세요 .!!