Linux系统编程——特殊进程

写在前面

本文主要介绍Linux下的三个特殊进程,才学了俩,守护进程学了在更新

僵尸进程

进程已运行结束,但进程的占用的资源未被回收,这样的进程称为僵尸进程

在每个进程退出的时候,内核释放该进程所有的资源、包括打开的文件、占用的内存等。 但是仍然为其保留一定的信息,这些信息主要主要指进程控制块的信息(包括进程号、退出状态、运行时间等)。直到父进程通过 wait()waitpid() 来获取其状态并释放(具体用法,请看《等待进程结束》)。 这样就会导致一个问题,如果进程不调用wait()waitpid() 的话, 那么保留的那段信息就不会释放,其进程号就会一直被占用,但是系统所能使用的进程号是有限的,如果大量的产生僵死进程,将因为没有可用的进程号而导致系统不能产生新的进程.此即为僵尸进程的危害,应当避免 。

如果是64位系统,孤儿进程的父进程号并不是 1 号。

案例

僵尸程序的测试代码如下

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

int main(){
    pid_t pid; 
    pid = fork();
    
    if(pid < 0){ 
        perror("fork");
        exit(0);
    } else if(pid == 0) {
        printf("I am child my pid is %d\n", getpid());
    } else {
        sleep(1); //保证子进程先运行
        printf("I am parent\n");
        while(1);//防止父进程退出,子进程被init回收
    }   
    return 0;
}

image.png

程序后面带有 <defunct> 的均为僵尸进程。僵尸进程无法使用 kill 命令来清除,因为 kill是用来终止进程的,而僵尸进程是已经终止的进程。

孤儿进程

父进程运行结束,但子进程还在运行(未运行结束)的子进程就称为孤儿进程(Orphan Process)。孤儿进程最终会被 init 进程(进程号为 1 )所收养,并由 init 进程对它们完成状态收集工作,类似于一个孤儿院?

孤儿进程是没有父进程的进程,为避免孤儿进程退出时无法释放所占用的资源而变为僵尸进程(什么是僵尸进程,请看《特殊进程之僵尸进程》),进程号为 1 的 init 进程将会接受这些孤儿进程,这一过程也被称为“收养”。init 进程就好像是一个孤儿院,专门负责处理孤儿进程的善后工作。每当出现一个孤儿进程的时候,内核就把孤 儿进程的父进程设置为 init ,而 init 进程会循环地 wait() 它的已经退出的子进程。这样,当一个孤儿进程凄凉地结束了其生命周期的时候,init 进程就会代表党和政府出面处理它的一切善后工作。因此孤儿进程并不会有什么危害。

案例

孤儿进程测试案例

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

int main(){
    pid_t pid; 
    pid = fork();
    
    if(pid < 0){ 
        perror("fork");
        exit(0);
    } else if(pid == 0) {
        while(1){
            printf("I am child my pid is %d, father is %d\n", getpid(), getppid());
            sleep(1);
        }
    } else {
        sleep(2);
        printf("I am parent my pid is %d\n", getpid());
    }   
    return 0;
}

image.png

最开始父进程还在的时候,子进程的父进程pid = 40490,当父进程死后,子进程的父亲的pid = 1728

守护进程

更新中......