본문 바로가기
Linux BSP

[Linux] fork()와 exec()를 이용한 프로세스 생성 과정

by TYB 2024. 2. 19.
반응형
ubuntu@ubuntu8:~/pi_bsp/kernel$ gcc fork.c -o fork

*fork system call 

return 값을 통해 어떤 프로세스인지 확인이 가능함

-1: 에러  /  0:  자식 프로세스   /   다른 값 : 부모 프로세스

 

*fork() exec()를 사용한 프로세스 생성

부모 프로세스가 종료될 때 자식프로세스가 종료되지 않는 걸 좀비 프로세스라고 하는데, 이를 방지하기 위해 아래 단계를 따르는게 좋음.

1.현재 프로세스에서 fork() 호출

 

2.자식 프로세스가 fork()로 부터 0 값이 반환 되면 exec()를 호출하여 새로운 프로그램으로 바꾼다.

 

3.부모 프로세스는 wait()를 호출하여 자식 프로세스의 종료를 기다리고, 자식 프로세스가 종료 되었다는 정보를 받으면 프로세스 종료

 

 

 

*fork() exec()를 이용한 프로세스 생성 과정을 실제로 봐보자

 

ubuntu@ubuntu8:~/pi_bsp/kernel$ vi fork.c

 

#include <unistd.h>
int fatal(char *s);
main()
{
        pid_t pid;        
        switch (pid = fork()){
        case -1:
                fatal("fork failed.");
                break;
        case 0:  /* 자식 프로세스 */
                execl("/bin/ls","ls","-1",(char *)0)); /* 자식이 exec를 호출 */
                fatal("exec failed.");
                break;
        default: /* 부모 프로세스 */
                wait((int *)0);  /* 부모는 자식이 종료 될 때 까지 대기 */
                printf("ls completed\n");
                exit(0);
         }
}
int fatal(char *s)
{
        perror(s);
        exit(1);
}

 

 

execl계열과 cf 계열이 있는데 cl계열은 마지막에 NULL pointer를 넘겨줌. 

ubuntu@ubuntu8:~/pi_bsp/kernel$ gcc fork.c -o fork

 

이 코드를 컴파일 하려고 하면 에러가 발생

ubuntu@ubuntu8:~/pi_bsp/kernel$ man exit

ubuntu@ubuntu8:~/pi_bsp/kernel$ man wait

 

 

 

좌측 상단을 보면 WAIT(2)라고 나와있는데 매뉴얼의 2번 페이지를 나타내는 거임. 우리가 볼 건 2번이나 3번임.

명령어 칠 때도 어떤 페이지를 볼 지 선택 할 수 있는데 man 2 wait 이런식으로 사용하면됨.

 

1번 페이지는 우리가 볼 필요가 없음. 만약 1번 페이지가 나온다면 man 2 wait 명령어를 사용해주면 됨.

 

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

int fatal(char *s);
int main(void)
{
	pid_t pid;
	switch(pid = fork()) {
		case -1:
			fatal("fork failed.");
			break;
		case 0:
			execl("/bin/ls","ls","-l",NULL);
			fatal("exec failed.");
			break;
		default:
			wait((int *)0);
			printf("ls completed\n");
			exit(0);
	}
}
int fatal(char *s)
{
	perror(s);
	exit(1);
}

 

ubuntu@ubuntu8:~/pi_bsp/kernel$ gcc fork.c -o fork

윗 코드 적용하면 컴파일 잘됨.

 

 

 

자식 프로세스를 종료시키지 않은 채 부모 프로세스를 종료시켜 좀비 프로세스 만들어보자

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

int fatal(char *s);
int main(void)
{
	pid_t pid;
	switch(pid = fork()) {
		case -1:
			fatal("fork failed.");
			break;
		case 0:
			execl("/bin/ls","ls","-l",NULL);
			fatal("exec failed.");
			break;
		default:
			wait((int *)0);
			printf("ls completed\n");
			exit(0);
	}
}
int fatal(char *s)
{
	perror(s);
	exit(1);
}

 

return 할 때 좌측으로 8번 shift한 값을 반환하게 되어 있음. 그래서 우리가 프로세스의 return 값에 접근할 때는 우측으로 8번 시프트해서 출력하면 됨. 그래서 코드 수정해주고

 

 

ps -ef | grep fork

 

 

원래는 코드 실행하고 ps auwx | grep fork 명령어를 치면  Z로 보이거나 top에서 zombie 프로세스 카운트가 늘어나야함.

 

 

 

 

 

 

 

 

ps -ef | more 

1page 단위로 보겠다.

대괄호 []로 나오는 건 커널 스레드임.

 

이렇게 나오는게 일반적인 프로세스들

 

 

반응형