프로그램 실행

프로세스의 생성 fork

-호출한 프로세스와 동일한 프로세스를 새로 생성하여 새로운 프로세스 ID를 할당

-부모(parent) 프로세스: fork를 호출한 프로세스

-자식(child) 프로세스: fork에 의해 생성되는 프로세스

 

프로그램의 실행 exec

-호출한 프로세스를 새로운 프로세스로 변경한다.

-호출 후의 프로세스 ID는 변하지 않는다.

-새로운 프로그램의 내용이 실행된다.

 

프로세스의 식별

#include <sys/types.h>

#include <unistd.h>

pid_t getpid(void); 호출한 프로세스의 프로세스 ID를 반환

pid_t getppid(void); 호출한 프로세스의 부모 프로세스 ID를 반환

uid_t getuid(void); 실제 사용자 (real user) ID를 반환

uid_t geteuid(void); 유효 사용자 (effective user) ID를 반환

gid_t getgid(void); 실제 그룹 (real group) ID를 반환

gid_t getegid(void); 유효 그룹 (effective group) ID를 반환

pid_t, uid_t, gid_t는 typedef에 의해 int로 선언

 

프로세스의 생성 (fork)

-새로운 프로세스를 생성

-리턴 값 성공한 경우 자식 프로세스의 PID (부모), 0 (자식), 실패하면 -1, errno에 에러의 내용을 저장

-에러 값 EAGAIN: 시스템에서 허용하는 최대 프로세스의 수를 초과

ENOMEM: 새로운 프로세스를 위한 스왑(swap) 공간 부족

-fork 성공, 생성된 자식 프로세스와 부모 프로세스와 동일한 프로그램, fork 호출 다음 문장부터 동시에 실행

-자식 프로세스의 메모리 공간

//커널은 자식 프로세스를 프로세스 테이블에 등록하고 메모리를 할당

//텍스트 영역은 공유하고, 데이터, 힙, 스택 영역은 복사

//대부분의 시스템에서 데이터,힙,스택 영역을 바로 복사하지 않는다. fork 이후에 보통 exec이 호출되기 때문

//변형 시에 복사 (copy-on-write, COW) 방법을 사용

 

자식과 부모 프로세스의 구분, 리턴 값으로 구분 부모:생성된 자식 프로세스의 PID, 자식:0

 

for 함수의 반환 값

-부모 프로세스: 여러 자식 프로세스를 각 fork의 리턴 값으로 구분

-자식 프로세스 : getppid 함수를 이용하여 부모 프로세스 식별

-PID가 0인 프로세스: swapper(sched)로서 시스템 부팅 시 생성되며 fork에 의해 다시 생성되지 않는다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
static int glob=6// 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){
        perror("write error"); return -1;}
    printf("before fork\n"); //we don't flush stdout
 
    if((pid=fork())<0)
        perror("fork error");
    else if(pid==0){ //child
        glob++//modify variables
        var++;
    }else
        sleep(2); //parent
 
    printf("pid=%d, glob=%d, var=%d\b",getpid(),glob,var);
    return 0;
}
 
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none; color:white">cs

 

 

fork 후에 달라지는 속성

-fork 함수의 리턴 값

-프로세스 ID, 부모 프로세스 ID

-자식 프로세스의 tms_utime,tms_stime,tms_cutime,tms_cstime 값은 0으로 초기화

-부모 프로세스의 파일 잠금(file locks)은 상속되지 않는다.

-처리되지 않은 (pending) 알람(alarm)과 시그널은 자식 프로세스에서 초기화

 

for 함수의 일반적인 용도

- 동일한 프로그램의 실행, 같은 프로그램을 복제하여 부모와 자식이 각각 다른 코드 부분을 동시에 실행해야 하는 경우

예: 네트워크 서버 (network servers)

- 새로운 프로그램의 실행, 자식 프로세스는 fork후에 exec 함수를 호출하여 새로운 프로그램을 실행한다. 

예: 쉘 (shells)

 

vfork 함수

-vfork 함수는 exec 함수를 통해 새로운 프로그램을 실행시킬 목적으로 자식 프로세스를 생성, 부모 프로세스의 메모리 영역을 모두 복사 하지 않는다.

-자식 프로세스는 exec 이나 exit 호출을 할 때가지 부모 프로세스의 메모리 영역에서 실행되며, 부모 프로세스는 실행을 멈춘다. 자식 프로세스가 항상 먼저 실행되는 것을 보장

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>
#include <sys/types.h>
 
static int glob=6//external variable in initalized data
 
int main(void)
{
    int var; //automatic variable on the stack
    pid_t pid;
    var=88;
 
    printf("before vfork\n"); //we don't flush stdio
 
    if((pid=vfork())<0){
        perror("vfork error");
        return -1;
    }
    else if(pid==0){ //child
        glob++//modify parent's variables
        var++;
        _exit(0); //child terminates
    }
 
    //parent
    printf("pid=%d,glob=%d,var=%d\n",getpid(),glob,var);
    return 0;
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none; color:white">cs

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <sys/types.h>
 
static void f1(void),f2(void);
 
int main(void)
{
    f1();
    f2();
    _exit(0);
}
 
static void f1(void)
{
    pid_t pid;
 
    if((pid=vfork())<0)
        perror("vfork error");
    //child and parent both return
}
 
static void f2(void)
{
    char buf[1000]; //automatic variables
    int i;
    for(i=0;i<sizeof(buf);i++) buf[i]=0;\
}
 
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none; color:white">cs

 

 

프로세스에 대한 대기 (wait)

- 자식 프로세스의 종료 상태 값을 얻어내는 방법

- 프로세스가 종료하면 부모 프로세스에게 SIGCHLD 시그널을 전달하여 대기(block) 사애를 해제

- wait 함수의 동작

// 모든 자식 프로세스가 실행되고 있는 동안 대기한다(block).

//자식 프로세스가 종료하면 종료 상태 값과 함께 즉시 리턴

// 에러 발생시에는 즉시 리턴(자식 프로세스가 없는 경우)

 

#include <sys/types.h>

#include <sys/wait.h>

pid_t wait(int *statloc);

pid_t waitpid(pid_t, int *statloc, int options);

- 종료된 자식 프로세스가 있으면 종료 상태 값을 statloc에 저장, 리턴 값은 종료된 자식 프로세스의 PID

- 자식 프로세스가 여럿인 경우 그 중 하나만 종료해도 리턴

- 자식 프로세스가 없을 경우에는 -1을 리턴

- 시그널에 의해서도 리턴되며 errno에 EINTR 값을 저장

- waitpid 함수는 특정 자식 프로세스를 지정하여 기다릴 수 있으며, 단순 대기 (blocking)를 방지하는 옵션가능

 

waitpid 함수

- wait 함수와 다른 기능

//여러 자식 프로세스 중에서 특정 자식의 종료 상태 값을 얻을 수 있다.

//단순 대기(blocking)를 방지할 수 있다. (WNOHANG 옵션, pid로 지정한 프로세스가 아직 종료하지 않았더라도 대기하지 않고 바로 리턴한다. 리턴값은 0이다.)

//작업 제어를 지원한다. (WUNTRACED 옵션, 작업 제어가 지원되는 시스템에서 pid로 지정한 프로세스가 잠시 중단된 경우에도 리턴한다.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
void errors(char *msg, int code);
void cleanupaction(void);
 
int main(int argc,char **argv)
{
    pid_t pid;
    int status;
 
    if((pid=fork())>0){ //부모프로세스가 수행하는 부분
 
        while(!waitpid(pid,&status, WNOHANG)){
            printf("parent stauts : %d\n",status++);
            sleep(1);
            }
        printf("parent child exit:%d\n",status);
    }
    else if(pid==0){ //child
        sleep(5);
        printf("bye child\n");
        exit(1);
    }
    else
    {
        printf("failed to fork\n");
    }
 
    printf("Buy buy\n");
    return 0;
}
 
void cleanupaction(void)
{
    printf("Clean-up action\n");
}
void error(char *msg, int code)
{
    perror(msg);
    exit(code);
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none; color:white">cs

 

 

경쟁조건(race conditions)

- 제한된 자원에 대한 임의적 접근

//여러 개의 프로세스가 공유된 데이터에 대해 작업을 수행하려고 할 때, 수행 결과는 각 프로세스의 실행 순서에 따라 다르다.

//경쟁 조건의 해결, 프로세스 간의 통신 (시그널, IPC 등), 자원 잠금(lock)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <sys/types.h>
#include <stdio.h>
static void charatatime(char *);
 
int main(void)
{
    pid_t pid;
    if((pid=fork())<0){
        perror("fork error"); return -1; }
    else if (pid==0){
        charatatime("output from child\n");
    } else {
        charatatime("output from parent\n");
    }
 
    return 0;
}
 
static void charatatime(char *str)
{
    char *ptr;
    int c;
    setbuf(stdout,NULL); //set unbuffered
    for(ptr=str;c=*ptr++;)
        putc(c,stdout);
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none; color:white">cs

+ Recent posts