Linux 僵尸进程、孤儿进程、守护进程简介

Linux进程简介
  • 每个进程都有一个唯一的正数(非零)进程ID (PID),getpid函数返回调用进程的PIDgetppid函数返回它的父进程的PID(创建调用进程的进程)。
  • 父进程通过调用 fork 函数创建一个新的运行的子进程
  • 子进程得到与父进程用户级虚拟地址空间相同的(但是独立的)一份副。包括代码数据段共享库以及用户栈。子进程还获得与父进程任何打开文件描述符相同的副本,这意味着子进程可以读写父进程中打开的任何文件,父进程新创建的子进程之间最大的区别在于他们有不同的PID
pid_t fork(void); // pid_t 在Linux中被定义为 int
  • fork() 函数调用一次返回两次,一次返回到父进程,一个返回到新创建的子进程。子进程返回0父进程返回子进程的PID如果出错,则为-1。
  • PID:当前进程ID
    PPID:当前进程的父进程ID
    LWP:线程ID
    NLWP:线程组内线程的个数
    在这里插入图片描述
示例:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main() {
    int i = 1;
    pid_t pid;
    pid = fork();
    if (pid == 0) {
        i = 2;
        printf("child process. %d\n", i);
    }
    printf("father process. %d\n", i);  
    // 两次执行这条print,i值不同,因为已经有了不同的地址空间。
    return 0;
}

运行结果:

father process. 1
child process. 2
father process. 2
僵尸进程

当一个进程由于某种原因终止时,内核并不是立即把它从系统中清除。相反,进程被保持在一种已终止的状态中,直到被它的父进程回收。一个终止了但还未被回收的进程称为僵尸进程僵尸进程没有运行,但它仍然消耗系统的内存资源。

僵尸进程测试代码
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <unistd.h>

int main() {
    pid_t pid;
    pid = fork();
    if (pid == 0) { // child process
        printf("child process pid is running\n"); 
        sleep(10);
        return 0;
    }
    sleep(30);
    printf("child process pid : %d\n", pid);
    return 0;
}

这里子进程10s后先结束,因为父进程没有回收子进程,则子进程变成僵尸进程。
在这里插入图片描述
第一次 ps -al 时父进程子进程都在运行,第二次 ps -al 时子进程已经成为僵尸进程,但系统还未正式回收此进程,PID还在。

孤儿进程

如果一个父进程终止了,内核会安排init进程成为它的孤儿进程的养父。init进程的PID为1,是在系统启动时由内核创建的,它不会终止,是所有进程的祖先。如果父进程没有回收它的僵尸子进程终止了,那么内核会安排init进程去回收他们。长时间运行的程序(shell,服务器等)应该回收他们的僵死子进程

init进程 : 在这里插入图片描述

孤儿进程测试代码
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <unistd.h>

int main() {
    pid_t pid;
    pid = fork();
    if (pid == 0) {
        printf("child process pid is running\n");
        sleep(30);
        return 0;
    }
    sleep(10);
    printf("child process pid : %d\n", pid);
    return 0;
}

运行结果:
在这里插入图片描述
可以看到父进程PID为25524,子进程PID为25525,等10s后再次执行ps -al 命令,看到父进程已经消失,子进程的PPID更新为1363。
在这里插入图片描述
本来孤儿进程应该更新PPID为1,但这里Ubuntu 16.04 指定了 /sbin/upstart 收养孤儿进程,属于发行版的特殊功能吧。
在这里插入图片描述

守护进程

守护进程就是在后台运行,不与任何终端关联的进程,通常情况下守护进程在系统启动时就在运行,它们以root用户或者其他特殊用户(apache和postfix)运行,并能处理一些系统级的任务。习惯上守护进程的名字通常以d结尾(sshd),但这些不是必须的。

创建守护进程的大致步骤:

  • fork()创建子进程,父进程退出,子进程成为孤儿进程被init接管,子进程变为后台进程。
  • 调用setsid()让子进程成为新会话的组长,脱离父进程的会话期。
  • 将当前目录改成跟目录(如果把当前目录作为守护进程的目录,当前目录不能被卸载他作为守护进程的工作目录)
  • 关闭进程从创建它的父进程那里继承了打开的文件描述符。
  • 将标准输入,标注输出,标准错误重定向到/dev/null
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值