다음 프로그램, 즉 fork ()는 소수 변경 사항을 찾습니다.
실험 1 부모 프로세스는 잠을 자지 않고 201 자식은 수면을 처리합니다.
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#define LEFT 200
#define RIGHT 250
int main(void)
{
int i,j,mark;
pid_t pid;
for(i = LEFT; i <= RIGHT; i++)
{
pid = fork();
if(pid < 0)
{
fprintf(stderr,"fork() failed!\n");
exit(1);
}
else if(pid == 0)//child
{
mark = 1;
for(j = 2; j < i/2; j++)
{
if(i % j ==0)
{
mark = 0;
break;
}
}
if(mark)
printf("%d is a primer\n",i);
sleep(1000);
exit(0);//!!!
}
}
exit(0);
}
변경 : 각 하위 프로세스가 종료되기 전에 1000 초 동안 휴면합니다.이 경우 상위 프로세스가 먼저 종료되고 201 하위 프로세스가 종료 된 후에 종료해야합니다. 이 경우 부모 프로세스는 201 개의 자식 프로세스를 생성 한 후 바로 exit ()되고 자식 프로세스는 작업을 마친 후 휴면 상태가됩니다.
ps axf 프로세스 상태보기 :
mhr@ubuntu:~/Desktop/xitongbiancheng/test$ ps axf
15800 pts/2 S 0:00 \_ ./a.out
15801 pts/2 S 0:00 \_ ./a.out
15802 pts/2 S 0:00 \_ ./a.out
15803 pts/2 S 0:00 \_ ./a.out
15804 pts/2 S 0:00 \_ ./a.out
15805 pts/2 S 0:00 \_ ./a.out
15806 pts/2 S 0:00 \_ ./a.out
15807 pts/2 S 0:00 \_ ./a.out
15808 pts/2 S 0:00 \_ ./a.out
15809 pts/2 S 0:00 \_ ./a.out
15810 pts/2 S 0:00 \_ ./a.out
15811 pts/2 S 0:00 \_ ./a.out
15812 pts/2 S 0:00 \_ ./a.out
15813 pts/2 S 0:00 \_ ./a.out
15814 pts/2 S 0:00 \_ ./a.out
15815 pts/2 S 0:00 \_ ./a.out
15816 pts/2 S 0:00 \_ ./a.out
15817 pts/2 S 0:00 \_ ./a.out
15818 pts/2 S 0:00 \_ ./a.out
15819 pts/2 S 0:00 \_ ./a.out
15820 pts/2 S 0:00 \_ ./a.out
...
...
...
모든 201 하위 프로세스가 최상위 그리드에 의해 작성되었음을 알 수 있으므로 201 프로세스의 상위 프로세스가 init 프로세스입니다.
부모 프로세스가 종료 된 모든 프로세스에 대해 부모 프로세스가 init 프로세스로 변경되는 경우 이러한 프로세스를 init 프로세스에서 채택한 프로세스라고합니다. 작업 프로세스는 대략 다음과 같습니다. 프로세스 A가 종료되면 커널은 다른 모든 활성 프로세스 BCD 등을 확인하여 이러한 활성 프로세스가 프로세스 A를 종료하는 자식 프로세스인지 여부를 확인합니다. 활성 프로세스 프로세스가 1로 변경됩니다 (초기화 프로세스의 ID는 1 임).이 접근 방식은 모든 프로세스가 상위 프로세스를 갖도록합니다.
실험 2 부모 프로세스는 잠자고, 자식 프로세스는 잠들지 않습니다.
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#define LEFT 200
#define RIGHT 250
int main(void)
{
int i,j,mark;
pid_t pid;
for(i = LEFT; i <= RIGHT; i++)
{
pid = fork();
if(pid < 0)
{
fprintf(stderr,"fork() failed!\n");
exit(1);
}
else if(pid == 0)//child
{
mark = 1;
for(j = 2; j < i/2; j++)
{
if(i % j ==0)
{
mark = 0;
break;
}
}
if(mark)
printf("%d is a primer\n",i);
exit(0);//!!!
}
}
sleep(1000);
exit(0);
}
mhr@ubuntu:~/Desktop/xitongbiancheng/test$ ps axf
\_ zeitgeist-datahub
2824 ? Sl 0:37 \_ /usr/bin/python /usr/bin/terminator
2836 ? S 0:00 | \_ gnome-pty-helper
2837 pts/0 Ss 0:01 | \_ /bin/bash
16001 pts/0 R+ 0:00 | | \_ ps axf
2858 pts/2 Ss 0:00 | \_ /bin/bash
15944 pts/2 S+ 0:00 | \_ ./a.out
15945 pts/2 Z+ 0:00 | \_ [a.out] <defunct>
15946 pts/2 Z+ 0:00 | \_ [a.out] <defunct>
15947 pts/2 Z+ 0:00 | \_ [a.out] <defunct>
15948 pts/2 Z+ 0:00 | \_ [a.out] <defunct>
15949 pts/2 Z+ 0:00 | \_ [a.out] <defunct>
15950 pts/2 Z+ 0:00 | \_ [a.out] <defunct>
15951 pts/2 Z+ 0:00 | \_ [a.out] <defunct>
15952 pts/2 Z+ 0:00 | \_ [a.out] <defunct>
15953 pts/2 Z+ 0:00 | \_ [a.out] <defunct>
15954 pts/2 Z+ 0:00 | \_ [a.out] <defunct>
15955 pts/2 Z+ 0:00 | \_ [a.out] <defunct>
15956 pts/2 Z+ 0:00 | \_ [a.out] <defunct>
15957 pts/2 Z+ 0:00 | \_ [a.out] <defunct>
15958 pts/2 Z+ 0:00 | \_ [a.out] <defunct>
...
....
....
3692 ? Sl 0:02 \_ /usr/lib/x86_64-linux-gnu/notify-osd
이 실험에서는 부모 프로세스가 종료되지 않았으므로 모든 자식 프로세스의 부모 프로세스는 여전히 이전 부모 프로세스이며 init 프로세스로 전송되지 않습니다.
이때 201 개의 자식 프로세스의 프로세스 상태는 좀비 프로세스 인 Z +임을 알 수 있습니다. 그렇다면 좀비 프로세스는 무엇이며 좀비 프로세스는 어떻게 생성됩니까?
UNIX 용어에서 종료되었지만 부모 프로세스가 아직 처리하지 않은 프로세스 (자식 프로세스 종료 및 여전히 차지하고있는 리소스 해제에 대한 정보 획득)는 좀비 프로세스가됩니다.
따라서 위의 예에서 상위 프로세스는 201 개의 하위 프로세스를 포크합니다. 상위 프로세스가 하위 프로세스의 종료 상태를 얻기 위해 대기하지 않는 한 이러한 하위 프로세스는 위와 같이 종료 후 좀비 프로세스가됩니다. 자식 프로세스의 여파에 대해서는 wait () / waitpid ()를 사용하여 처리합니다. 이에 대해서는 다음 섹션에서 자세히 설명합니다.
참고로, 초기화 프로세스에서 채택한 프로세스가 종료되면 어떻게됩니까? 그가 좀비 프로세스가 될까요?
대답은 아니오입니다. init 프로세스는 자식 프로세스가 종료 될 때마다 init가 wait () 함수를 호출하여 처리하고 종료 상태를 얻도록 설계되었습니다. 이것은 시스템이 좀비 프로세스로 채워지는 것을 방지합니다.