• 한 디바이스에서는 매우 많은 프로세스들이 스위칭되면서 실행중
  • Running 시간을 정해서 스위칭 주기를 정할 수 있음
  • 가상메모리를 이용하여 메모리 테이블을 스위칭 -> 스위칭 전에 상태를 저장 후 다시 되돌아 왔을 때, 저장한 곳 부터 실행
  • 가상메모리란? - 프로세스를 스위칭 할 때 이전에 실행했던 프로세스의 상태를 저장하는 실제 메모리보다는 느린 것
    • ex) 4GB 중 일부만 사용하지만 4GB를 모두 사용하는 것 처럼 보임
  • 리눅스에서 많은 프로세스들의 조상은 딱 1개 -> Init
  • fork(A)후 exec(B)를 하면 전혀 다른 프로세스가 만들어짐
  • exit(status)로 parent process로 status를 넘겨줄 수 있음 -> wait상태에서 받으면 다시 실행
  • fork(2)를 하고 나면 같은 프로세스가 2개가 돌고 있음 -> return되는 pid값이 다름 -> 생성된 프로세스는 0, 부모 프로세스는 다른 숫자, -1은 에러
  • status코드는 앞 8bit에 저장
  • status를 wait로 받음
  • Ophan process : parent process가 없어지면 남아있는 child process가 남음 -> Init으로 부모 프로세스를 바꿔줌
  • zombie process : child process가 종료되면 parent가 wait를 해야하는데 wait를 하지 못하는 경우 -> child는 parent가 wait를 할 때 까지 완전히 끝나지 못함
  • 자세한 내용 : https://giantpark197cm.tistory.com/44?category=767121

  • ps -ef를 쳐보면

  • PID와 PPID, CMD같은 것들이 출력됨
  • 이것은 현재 실행중인 프로세스들의 PID, PPID 등의 정보들을 출력하는 것
  • ps -ef | wc -l -> 현재 실행중인 프로세스들의 숫자

  • ps -ef | more : 많은 수의 프로세스들이 있으므로 한줄씩 추가로 보여주는 기능, 엔터마다 넘어감

  • ps -ef | grep bash : bash라는 이름이 있는 것만 찾음 -> grep으로 PPID를 검색하며 거슬러 올라가다보면 1이 나옴

  • proc 파일시스템 : 시스템의 정보를 알려줌 -> 시스템에서 돌고있는 프로세스의 여러가지 상태정보
    • cd /proc/(PID) 로 들어갈 수 있음

 

  • cat status -> sleeping모드로 cat을 기다리고 있음 -> cat은 출력해주는 함수이고 status는 현재 상태인데 cat을 실행하는 순간 status는 멈추고 cat을 실행하기 때문에 sleeping모드로 기다리는 것

 


fork()를 사용하여 child를 만드는 프로그램

  • 부모와 자식을 구분하여 printf
  • 부모 프로세스는 wait를 이용해 자식프로세스를 기다림
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 <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
 
int main()
{
        pid_t pid = fork();
 
        if(pid == 0)
        {
                printf("I'm child process\n");
                exit(0);
        }
        else if(pid == -1)
        {
                perror("fork");
                exit(0);
        }
        else
        {
                printf("I'm parent process\n");
                printf("my child process PID is %ld\n",(long)pid);
                wait(NULL);
        }
}
cs
  1. fork()로 자식 프로세스 생성
  2. pid가 0이면 자식프로세스 -> pirntf
  3. -1이면 오류 -> 오류 메시지 출력
  4. 나머지는 부모프로세스 -> printf(pid포함), wait

 


fork, wait 종료 상태값 파악

  • fork()시스템 콜을 사용하는 간단한 프로그램 작성
  • WEXITSTATUS매크로를 사용하여 자식프로세스가 반환한 종료 상태값을 반환
  • waitpid(특정 child process를 지정하여 기다릴 수 있음)
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
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
 
int main()
{
        pid_t pid = fork();
        pid_t wpid;
        int child_status;
 
        if(pid == -1)
        {
                perror("fork");
                exit(0);
        }
        else if(pid == 0)
        {
                printf("I'm child process\n");
                exit(55);
        }
        else
        {
                printf("I'm parent process\n");
                printf("my child process PID is %ld\n",(long)pid);
                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);
                }
 
        }
}
 
cs

 

  1. fork()로 자식 프로세스 생성
  2. 자식과 에러는 위와 동일 -> 자식프로세스는 55를 반환
  3. wait로 자식프로세스의 status를 받음
  4. WIDEXITED를 이용하여 정상종료되었는지 정보를 return -> 정상종료시 1 아니면 0
  5. WEXITSTATUS : status코드 중에서 status부분만 추출(앞 8bit)
  6. 정상종료 되지 않은 경우 printf

 


fork(2) : 부모/자식 프로세스간의 race condition

  • fork()로 프로세스 복제
  • 자식은 for로 1부터 10000까지 출력
  • 부모는 for로 101부터 20000까지 출력
  • printf()뒤에는 fflush(NULL)를 호출하여 출력이 버퍼링 없이 화면에 출력되도록 하자
  • 부모 프로세스가 wait()를 이용해 자식 프로세스가 종료되기를 기다릴떄와 기다리지 않을 때의 차이 확인
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
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
 
int main()
{
        pid_t pid = fork();
        int child_status;
 
        if(pid == -1)
        {
                perror("fork");
                exit(0);
        }
        else if(pid == 0)
        {
                for(int i=1;i<10001;i++)
                {
                        printf("%d ",i);
                        fflush(NULL);
                }
        // exit(55);
        }
 
        else
        {
        //      wait(&child_status);
                for(int j=10001;j<20001;j++)
                {
                        printf("%d ",j);
                        fflush(NULL);
                }
        }
 
}
cs
  1. fork()로 자식 프로세스 생성
  2. 에러시 에러메시지 출력
  3. 자식 프로세스일 경우 1에서 10000까지 출력 -> fflush로 버퍼를 비움으로써 딜레이가 없게 함
  4. 부모 프로세스일 경우 10001에서 20000까지 출력 -> 마찬가지로 fflush사용
  5. exit(55), wait(&child_status)를 넣었을 경우와 넣지 않았을 경우 비교
  • 넣지 않았을 때 -> 처음엔 잘 실행 되나 나중에 race condition이 일어남을 확인

 

  • 넣었을 때 -> 순차적으로 진행되는 것을 확인

 


fork/exec() : 실행파일 실행하기

  • 자식프로세스 생성
  • 자식프로세스가 ps명령어를 ef옵션을 주어서 실행 execl()사용
  • 부모프로세스는 자식이 종료하기를 wait함수를 이용해 기다림
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
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
 
int main()
{
        int child_status;
        pid_t pid = fork();
 
        if(pid == -1){
                perror("fork");
                exit(0);
        }
        else if(pid == 0){
                //child
                execl("/bin/ps","ps","-ef",NULL);
        }
        else{
                wait(&child_status);
                printf("child process = %d \n",WEXITSTATUS(child_status));
        }
        return 0;
}
 
cs
  1. 자식 프로세스 생성
  2. execl 함수를 사용하여 ps폴더의 ps함수를 자식프로세스의 소스로 넣어줌 -> argument도 함께
  3. 부모 프로세스는 자식프로세스의 상태를 wait하고 이를 printf로 출력
  4. execl함수 외에도 다른 방법으로 사용 가능 -> execv : argument를 받아서 통째로 넣을 수 있음
1
2
argv[] = {"ps","-ef",NULL};
execv("/bin/ps",argv[]);
cs

 

 


system(3)함수 구현

  • system(3)함수가 하는 일

  • system() 함수는 /bin/sh -c string를 호출하여 string에 지정된 명령어를 실행하고, 명령어가 끝난 후 반환한다.

  • my_system()함수를 fork와 exec를 이용하여 구현
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
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
 
int my_system(char *command)
{
        int child_status;
        pid_t pid = fork();
 
        if(pid == 0)
        {
                execl("/bin/sh","sh","-c",command,(char *0);
        }
        else if(pid == -1)
        {
                perror("fork");
                exit(0);
        }
        else
        {
                wait(&child_status);
                return child_status;
        }
 
}
 
int main(void)
{
        int status;
        status = my_system("ls -l | wc");
        printf("exit code %d\n",WEXITSTATUS(status));
 
        return 0;
}
cs
  1. my_system에서 command를 받음
  2. fork로 자식 프로세스를 생성
  3. execl을 이용하여 매뉴얼대로 argument들 입력
  4. child_status를 기다린 후 그 값을 return
  5. my_system("ls -l | wc") : ls -l | wc를 실행 후 반환
  6. main문에서 리턴 값을 받아 WEXITSTATUS에 넣어 그 값을 출력 -> WEXITSTATUS : status코드 중에서 status부분만 추출(앞 8bit)
  • 실행 결과

 

 

 

 

+ Recent posts