1. 守护、孤儿和僵尸进程
(1)守护进程
①守护进程(daemon)是生存期长的一种进程。它们常常在系统引导装入时启动,在系统关闭时终止。
②所有守护进程都以超级用户(用户ID为0)的优先权运行。
③守护进程没有控制终端
④守护进程的父进程都是init进程(1号进程)。
(2)孤儿进程:父进程先结束,子进程就成为孤儿进程,会由1号进程(init进程)领养。
【编程实验】产生孤儿进程
//process_orphen.c
#include <unistd.h> #include <stdio.h> #include <stdlib.h> //孤儿进程。演示时启动另一个终端登录来查看子进程的状态 //由于父进程先结束,子进程会由init进程领养。 int main(void) { pid_t pid = fork(); if(pid < 0){ perror("fork error"); exit(1); }else if(pid > 0){ //parent process printf("%d deaded ", getpid()); exit(0); //父进程终止 }else{ sleep(4); //让父进程先终止,子进程变成孤儿进程,会由1号进程领养 printf("pid: %d, ppid: %d ", getpid(), getppid());//ppid=1 } return 0; }
(3)僵尸进程
①如果子进程先结束,父进程还存在。这时子进程并没有被完全释放内存(在内核中的task_struct没被释放),该进程就成为僵尸进程。
②当僵尸进程的父进程结束后就会被init进程领养,最终被回收。
③避免僵尸进程的方法:
A.让僵尸进程的父进程来回收,父进程每隔一段时间来查询子进程是否结束并回收。调用wait或waitpid,通知内核释放僵尸进程。
B.采用信号SIGCHLD通知处理,并在信号处理程序中调用wait函数来通知释放僵尸进程。
C.让僵尸进程成为孤儿进程,由init进程回收。
【编程实验】僵尸进程的产生
//process_zombie.c
#include <unistd.h> #include <stdio.h> #include <stdlib.h> int main(void) { pid_t pid = fork(); if((pid) < 0){ perror("fork error"); exit(1); }else if(pid == 0){//child process printf("pid: %d, ppid: %d ", getpid(), getppid()); exit(0); } //等待子进程结束并通知释放task_struct //wait(0); //加上这句会通知内核释放子进程的task_struct,不会 //产生僵尸进程,可以取消注释来对比。 //试图产生僵尸进程 while(1){ //父进程继续循环,不退出。此时子进程未被完全 //释放而成为僵尸进程 sleep(1); } return 0; }