Linux系统编程35 进程控制 - init 进程和僵死进程

如下程序,即 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()结束了,而子进程干完活就 sleep了。

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终止时,内核会逐个检查所有其他的活动进程 B C D…等等,来判断这些活动进程 是不是终止进程A 的子进程,如果是的话,则活动进程的父进程更改为1(init 进程的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+ 即 zombie 僵尸进程。那么什么是僵尸进程,僵尸进程是如何产生的?

在UNIX术语中,一个已经终止,但是其父进程尚未对其进行善后处理(获取终止子进程的有关信息,释放它仍然占用的资源)的进程成为 僵尸进程。

所以 对于上述例子,父进程fork了201个子进程,除非父进程等待获取子进程的终止状态,否则这些子进程终止后就会变成僵尸进程,如上。关于如果对子进程进行善后处置,用 wait()/waitpid() 处理,下节详细说明。

还有一个注意事项,一个由 init 进程收养的进程终止的时候会发生什么?他会不会变成一个僵尸进程?

答案是否定的,init进程被设计成 无论何时 只要有一个子进程终止, init就会调用一个 wait() 函数对其进行善后处理,获取其终止状态。这样就防止了系统中塞满僵尸进程。

猜你喜欢

转载自blog.csdn.net/LinuxArmbiggod/article/details/113794652
今日推荐