호야의 블로그
[C언어] 리눅스 환경에서 fork()함수를 이용한 자식 및 자손 프로세스 생성하기
헤더 선언
stdio.h를 추가로 unistd.h를 선언합니다.
#include <stdio.h>
#include <unistd.h>
unistd.h는 유닉스 계열에서 동작하는 C 컴파일러에 있는 헤더 파일입니다. 윈도우 환경에는 없는 헤더 파일이므로 저와 같은 리눅스 환경을 구성하지 않으시면 제대로 된 결과를 불 수 없습니다.
이후 메인 함수를 선언하고, pid_t 형식으로 pid라는 변수를 선언합니다. pid가 아니어도 무방합니다.
pid_t pid; //프로세스 ID로 변수 pid를 선언 pid = fork(); //fork함수 실행(실행 실패 시 -1, 부모에게 새로운 pid, 자식 프로세스에는 0이 반환)
변수 PID에 fork() 함수를 실행하고, 반환 값을 PID에 저장합니다. fork 함수가 실패하면 PID에 -1을 반환하며, 부모 프로세스에는 새로운 자식 프로세스 PID가 반환되고, 자식 프로세스에는 0이 반환됩니다.
이를 활용하여 다양한 조건문을 통해 각 프로세스에 다른 연산 혹은 동작을 줄 수 있습니다.
PID의 값이 0보다 큰 경우(부모 프로세스) 동작하는 조건문으로 부모프로세스가 getpid()를 통해 자신의 프로세스 아이디 즉 PID를 출력합니다. 참고로 getppid() 함수로 부모의 PID도 출력이 가능하니 한 번 테스트해보시며 이해하시길 추천합니다.
if(pid>0){ //부모 프로세스 들어감 printf("parent process %d\n",getpid()); //getpid로 현재 프로세스 pID, getppid로 부모 PID 출력 }
아래 코드는 PID가 0일 경우 즉, 자식 프로세스의 동작 조건문으로 getpid()로 자신의 PID를 출력합니다.
하지만 저의 목적은 자손 프로세스의 생성이므로 여기서 끝나지 않고, 다시 한 번 PID에 fork() 함수를 실행합니다. 이제 자식의 자식 프로세스가 생성되어, 현재의 조건문을 동작하게 됩니다.
즉 현재 상황은 제일 처음 생성된 프로세스 부모 A, 이후 생성된 자식 B, 그 이후 자식이 생성한 자식 C(A의 자손)가 존재합니다.
else if(pid==0){ //자식 프로세스 들어감 printf("child process %d\n",getpid()); pid =fork(); //fork함수 한 번 더 실행(자식이 손자 프로세스를 생성) if(pid>0){ //자식 프로세스 들어감 printf("child process %d\n",getpid()); } else printf("grand child %d\n",getpid()); //pid가 0인 경우(손자가 들어감) }
else if(PID==0) 문 안을 보시면, fork() 이후에 다시 조건문이 생겼습니다. 이는 B와 C의 동작을 위한 코드이며 B가 이제 부모가 되었으므로 PID>0 조건에 부합합니다. else 조건은(else if PID ==0 이어도 같은 동작을 합니다.) C 프로세스가 들어가 자신의 PID를 출력하는 동작을 하고 프로그램은 종료합니다.
아래 코드는 fork() 함수의 실행 실패 시, 즉 PID가 -1인 경우 에러처리 하는 코드와 현재 동작하는 프로세스를 볼 수 있는 시스템 코드로 되어있습니다. grep부분은 아래에 구현 화면에서 자세히 설명해드리겠습니다.
else printf("error\n"); //pid -1인 경우 에러 처리 system("ps | grep (C파일 있는 디렉토리 이름)");
프로그램 코드는 이렇게 끝났습니다. 아래에 전체 코드를 올려드리겠습니다.
#include <stdio.h> #include <unistd.h> int main() { pid_t pid; //프로세스 ID로 변수 pid를 선언 pid = fork(); //fork함수 실행(실행 실패 시 -1, 부모에게 새로운 pid, 자식 프로세스에는 0이 반환) if(pid>0){ //부모 프로세스 들어감 printf("parent process %d\n",getpid()); //getpid로 현재 프로세스 pID, getppid로 부모 PID 출력 } else if(pid==0){ //자식 프로세스 들어감 printf("child process %d\n",getpid()); pid =fork(); //fork함수 한 번 더 실행(자식이 손자 프로세스를 생성) if(pid>0){ //자식 프로세스 들어감 printf("child process %d\n",getpid()); } else printf("grand child %d\n",getpid()); //pid가 0인 경우(손자가 들어감) } else printf("error\n"); //pid -1인 경우 에러 처리 system("ps | grep (C파일 있는 디렉토리 이름)"); return 0; }
구현 및 동작 화면
ps명령어는 현재 동작 중인 프로세스를 보여주는 시스템 명령어로 system() 함수로 코드 내에서 동작하게 하였습니다. 또한, grep 코드로 실행 후 `~~`에 해당하는 문구가 들어간 프로세스만 출력합니다. ps명령어 실행 시에는 주요한 PID, PPID, PGID, COMMAND를 보시면 됩니다. PID와 PPID는 각각 현재, 부모 프로세스이며, PGID는 조상 프로세스입니다. 마지막으로 COMMAND는 현재 동작 중인 프로그램 주소를 나타냅니다.
※ 예) 만약, 실행 프로그램 이름이 'fork_test.exe'일 경우
system("ps | grep fork_test");
'fork_test 프로그램에서 동작 중인 프로세스를 출력해라'라는 뜻이 됩니다.
프로그램 동작 화면을 보시면 먼저 부모 프로세스 21032가 동작하고, 자식 프로세스 12864가 동작합니다. 이후 else로 빠진 후에 시스템 명령어 "ps | grep ~~"을 실행합니다. 이후 자식 프로세스가 fork()를 통해 자손을 만들고 다음 시스템 명령어 ps를 실행합니다. 최종적으로 아래와 비슷한 화면이 출력되는데 PID는 무작위로 생성되어 프로그램을 실행시킬 때마다 다르게 되는 점 참고 바랍니다.
<Cygwin에서 프로그램 동작화면>
후기 및 정리
fork() 함수 실습으로 프로세스를 생성하는 테스트를 해보았습니다. 저는 자손까지 생성하는 코드를 구현했지만, 여러분들은 한 프로세스로 여러 자식 프로세스를 만드는 코드도 연습해보시면 좋을 것 같습니다. 읽어주셔서 감사합니다.
리눅스 개발 환경이므로 Cygwin에서 개발 및 테스트 한 점 참고 부탁하겠습니다. 다음에 리눅스 환경을 구축하는 방법과 Cygwin 설치에 대한 글도 올리겠습니다.
C 4번째 글: 2018/11/02 - [IT/C] - [C] 운영체제-Page Replacement 알고리즘 만들기
C 3번째 글: 2018/10/31 - [IT/C] - [C] 운영체제-CPU 스케줄링 시뮬레이터 만들기
C 2번째 글: 2018/10/30 - [IT/C] - [C++] 영상처리-이미지 Sobel 경계 검출 및 영상 이진화
C 1번째 글: 2018/10/19 - [IT/C] - [C] 리눅스 환경에서 fork() 함수를 이용한 자식 프로세스 생성하기
조금의 도움이 되셨다면 로그인 없이도 가능한
왼쪽 아래 ♥공감 버튼을 꾹 눌러주세요!
'IT > C' 카테고리의 다른 글
Page Replacement 알고리즘 C로 만들기 (1) | 2018.11.02 |
---|---|
CPU 스케줄링 시뮬레이터 C로 만들기 (10) | 2018.10.31 |
영상처리-C++로 이미지 Sobel 경계 검출 및 영상 이진화 (1) | 2018.10.30 |