孤儿进程: 一个父进程退出,而它的一个或者多个子进程还在运行,那么这些子进程就将成为孤儿进程。孤儿进程将被nit进程(进程号为1)所收养,并有init进程对他们状态收集工作。父进程先结束,释放了资源,然而子进程没人管了,由系统托管来释放资源,这就变成了孤儿进程。
僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或者waitpid获取子进程的状态信息,那么子进程的进程描述符等一系列信息还会保存在系统中。这种进程称之为僵死进程。子进程运行退出后,没有通知父进程回收子进程,子进程的资源没办法被父进程给释放,变成了死而占用资源的僵尸。
措施: 杀死僵尸进程的父进程(僵尸进程的父进程必然存在),僵尸进程成为"孤儿进程",过继给1号进程init,init始终会负责清理僵尸进程。
//子进程变成了孤儿进程
#include <stdio.h>
#include<sys/types.h>
#include<stdlib.h>
#include<unistd.h>
int main()
{
printf("getpid()= %d , getppid()= %d , getuid()= %d , geteuid()= %d\n",getpid(), getppid(),getuid(), geteuid());
int p = fork();
if ( p ==0 )
{
printf("I am child process\n");
printf("getpid()= %d , getppid()= %d , getuid()= %d , geteuid()= %d\n",getpid(), getppid(),getuid(), geteuid());
sleep(20);
}else{
printf("I am parent process \n");
printf("getpid()= %d , getppid()= %d , getuid()= %d , geteuid()= %d\n",getpid(), getppid(),getuid(), geteuid());
// exit(1);
}
printf("Hello world\n");
return 0;
}
gcc fork.c
ps -elf |grep a.out 之后 父进程先退出了,变成了孤儿进程 子进程 被 1号进程接管,
//僵尸进程
#include <stdio.h>
#include<sys/types.h>
#include<stdlib.h>
#include<unistd.h>
int main()
{
printf("getpid()= %d , getppid()= %d , getuid()= %d , geteuid()= %d\n",getpid(), getppid(),getuid(), geteuid());
int p = fork();
if ( p ==0 )
{
printf("I am child process\n");
printf("getpid()= %d , getppid()= %d , getuid()= %d , geteuid()= %d\n",getpid(), getppid(),getuid(), geteuid());
}else{
printf("I am parent process \n");
printf("getpid()= %d , getppid()= %d , getuid()= %d , geteuid()= %d\n",getpid(), getppid(),getuid(), geteuid());
sleep(20);//子进程先结束掉,父进程没有收到信号, 子进程变成僵尸进程,等到父进程回收之后,子进程被init进程回收
// exit(1);
}
printf("Hello world\n");
return 0;
}
用wait() 系统调用来保证先去释放子进程再去释放父进程
int status;
pid_t p =wait(&status); 返回子进程的pid;
WIFEXITED(&status) 判断是否已经运行完毕了
WEXITSTATUS(status) 退出码
#include <stdio.h>
#include<sys/types.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>
int main()
{
printf("getpid()= %d , getppid()= %d , getuid()= %d , geteuid()= %d\n",getpid(), getppid(),getuid(), geteuid());
int p = fork();
if ( p ==0 )
{
printf("I am child process\n");
printf("getpid()= %d , getppid()= %d , getuid()= %d , geteuid()= %d\n",getpid(), getppid(),getuid(), geteuid());
sleep(30);
}else{
int status;
printf("\nI am the parent process \n\n");
pid_t p = wait(&status);
printf("I am parent process pid = %d , child pid = %d \n", getpid() , p);
if( WIFEXITED(status) ) // WIFEXITED() 返回零时 正常退出,非零为,非正常退出
{
printf("EXIT code : %d\n", WEXITSTATUS(status));
}else{
printf("child crash\n");
}
printf("getpid()= %d , getppid()= %d , getuid()= %d , geteuid()= %d\n",getpid(), getppid(),getuid(), geteuid());
// exit(1);
}
printf("Hello world\n");
return 0;
}
wati() 与waitpid() 用法不同,功能一样
进程一旦调用了wait,就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出。如果让它找到了这样一个已经变成僵尸的子进程,wait就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。
include <stdio.h>
#include<sys/types.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>
int main()
{
printf("getpid()= %d , getppid()= %d , getuid()= %d , geteuid()= %d\n",getpid(), getppid(),getuid(), geteuid());
int p = fork();
if ( p ==0 )
{
printf("I am child process\n");
printf("getpid()= %d , getppid()= %d , getuid()= %d , geteuid()= %d\n",getpid(), getppid(),getuid(), geteuid());
sleep(30);
}else{
int status;
printf("\nI am the parent process \n\n");
pid_t p = waitpid(pid , &status, 0);
printf("I am parent process pid = %d , child pid = %d \n", getpid() , p);
if( WIFEXITED(status) ) // WIFEXITED() 返回零时 正常退出,非零为,非正常退出
{
printf("EXIT code : %d\n", WEXITSTATUS(status));
}else{
printf("child crash\n");
}
printf("getpid()= %d , getppid()= %d , getuid()= %d , geteuid()= %d\n",getpid(), getppid(),getuid(), geteuid());
// exit(1);
}
printf("Hello world\n");
return 0;
}