본 블로그에서는 프로세스를 생성하는 방법, 종료하는 방법, exec 함수군 및 동기화 방법에 대해서 알아보고자 합니다.
● 프로세스란 ?
-> 프로세스는 현재 실행중인 프로그램을 의미합니다.
리눅스 시스템에서는 동시에 여러 프로세스가 실행이 되며, 이들은 실행, 수면(sleep), 실행대기 등의 규칙에 따라 여러 상태에 놓여있게 됩니다.
이러한 개별 프로세스들을 식별하기 위해서는 프로세스 ID(PID)값을 이용합니다.
● 프로세스의 구조
- 텍스트 영역 : 프로그램 실행 코드를 저장하는 영역으로 프로세스 실행 중에 크기가 변하지 않는 고정 영역에 속합니다.
- 데이터 영역 : 프로그램에서 정의한 전역 변수를 저장하는 영역으로 데이터 영역 또한 고정 영역에 해당됩니다.
- 힙 영역 : 프로그램 실행 중에 동적으로 메모리를 요청하는 경우에 할당되는 영역으로 할당 및 해제처럼 상태가 변하는 가변 영역에 해당됩니다.
- 스택 영역 : 프로그램에서 정의한 지역 변수를 저장하는 메모리 영역으로 가변 영역에 해당됩니다.
● 프로세스 생성
프로그램 내에서 다른 프로그램을 실행해 새로운 프로세스를 생성하기 위해서 사용되는 함수로는 fork(), system(), vfork() 가 있습니다. 본 글에서는 fork()에 대해서 설명하겠습니다.
Fork()
-파라메터 : 필요 x
-리턴값 : 부모 프로세스에서는 자식의 pid값을 return, 자식 프로세스에서는 0을 return
fork()의 리턴값을 통해 부모 및 자식 프로세스를 구분지어 프로그래밍을 할 수 있습니다.
아래 예제를 통해 이해를 해보도록 합시다.
#include <sys/types.h> #include <stdio.h> #include <unistd.h> int X =100; // X 변수에 초기값 할당 int main() { pid_t pid; int x = 0; // 추가 변수 생성 및 초기값 할당 pid = fork(); // 프로세스 생성 if(pid<0) { //error code // 리턴값이 음수면 프로세스 생성 실패를 의미 printf("fork Fail!\n"); return -1; } else if(pid ==0) { // 자식 프로세스 실행 코드 x++; X++; } else { // 부모 프로세스 실행 코드 sleep(5); x = 2; } printf("X = %d, x = %d\n", X, x); return 0; } |
위의 코드의 결과값은 아래와 같습니다.
결과를 보면 아시겠지만 자식 프로세스에서 출력하는 결과값과 부모 프로세스에서 5초 정도 sleep을 한뒤 출력하는 결과값의 양상이 다르다는걸 볼 수 있습니다.
● 프로세스 종료
프로세스 종료를 위한 함수로는 exit(), atexit(), on_exit(), _exit() 가 있습니다.
대부분 exit()함수를 주로 이용하고 있습니다.
void exit(int status);
● exec 함수군
함수명이 'exec'로 시작하는 exec 함수군은 인자로 받은 다른 프로그램을 자신을 호출한 프로세스의 메모리에 덮어쓰는 역할을 수행합니다. 따라서 프로세스가 수행 중이던 기존 프로그램은 중지되어 없어지고 새로 덮어쓴 프로그램이 실행되게 됩니다.
또한 exec함수군을 사용하여 fork()를 통해 생성된 자식 프로세스를 부모 프로세스와 전혀 연관없는 새로운 프로그램으로 변형해서 실행할 수 있습니다.
아래 예제를 통해 자세히 알아보도록 합시다.
#include<unistd.h> #include<stdlib.h> #include<stdio.h> void mysystem(const char *command) { pid_t pid; int status; if((pid=fork())<0){ printf("parent "); perror("fork"); exit(1); } else if(pid==0){ //자식 프로세스 printf("child"); if(execl("/bin/sh","sh","-c",command,(char *)NULL)==-1){ perror("execl"); exit(1); } } else { wait(&status); } } int main(void){ mysystem("ls -al"); } |
위 예제는 main 함수에서 mysystem함수에 매개변수로 "ls -al"이라는 문자열을 주었고, mysystem 함수에서는 fork()를 통해 자식 프로세스를 생성한 뒤 자식 프로세스안에서 exec 함수군을 통해 매개변수로 받은 커맨드를 실행시키고 exit(1)을 통해 종료하는 코드입니다.
이제 결과를 확인해봅시다.
결과를 보면 매개변수로 준 "ls -al"을 쉘 스크립트에서 실행시킨것과 같은 결과를 보이고 있습니다.
● 프로세스 동기화
fork()함수로 자식 프로세스를 생성하면 부모 프로세스와 자식 프로세스는 순서에 관계없이 실행되고, 먼저 실행을 마친 프로세스는 종료되게 됩니다. 이 때 둘 사이의 동기를 맞추기위해 부모 프로세스에서 wait()함수를 사용하는데, 이는 자식 프로세스의 실행이 완전히 끝나기를 기다렸다가 종료 상태를 확인하는 함수입니다. 이 때 상태 정보를 저장할 주소를 매개변수에 넣어줌으로써 결과를 받을 수 있습니다.
wait()함수의 리턴값은 자식 프로세스의 PID이며, -1이 리턴이 되면 살아있는 자식 프로세스가 하나도 없다는걸 의미합니다.
이번 글에서는 프로세스의 생성 및 동기화까지의 과정에 대해서 알아봤습니다.
다음 글에서는 쓰레드에 대하여 다룰 예정입니다. 감사합니다.
'CS > 시스템 프로그래밍' 카테고리의 다른 글
시스템 V IPC (System V) 2 -Infinite (0) | 2022.06.21 |
---|---|
시스템 V IPC (System V) 1 -Infinite (0) | 2022.06.21 |
파이프(PIPE) -Infinite (0) | 2022.06.20 |
시그널(signal) -Infinite (0) | 2022.06.20 |
쓰레드(Thread) -Infinite (0) | 2022.06.20 |
개발 기술 블로그, Dev
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!