【Linux】如何创建daemon进程&fork一次和fork两次有什么区别

来源:互联网 发布:怎么提高网络延迟 编辑:程序博客网 时间:2024/05/02 04:45

前言


本文适合对Linux进程有了解过的读者。Linux中有一种进程叫做守护进程,又称精灵进程。它运行在后台,很重要,Linux下大多数服务器就是用守护进程实现的。因为它独立于终端运行,也就是说它的运行不受当前登录或者注销的影响,自成会话,周期性的执行某项任务或者等待处理某些事件。其他进程则是在登录或者运行时创建,在运行结束或者注销用户时终止。守护进程命名通常以d结尾,父进程是1号进程,它其实是属于孤儿进程,因为我们知道1号进程会领养所有无父进程的孤儿进程。

创建守护进程


创建守护进程可以分为如下几步:
1. umask设置为0。
2. 调用fork函数,再将父进程退出。
3. 调用setsid函数创建⼀个新的Session,并成为Session Leader。
4. 改变当前目录为根目录
5. 关闭文件描述符
6. 忽略SIGCHLD信号(子进程退出时会发给父进程的信号)

调用setsid函数之前,当前进程不允许是进程组的Leader,否则该函数返回-1。这就是fork后将父进程退出的原因。毕竟刚创建出来的子进程不会是进程组组长。

setsid函数的作用:
1)子进程成为新会话的⾸进程。
2)子进程成为⼀个进程组的组长进程 。
3)子进程没有控制终端。

#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<signal.h>int main(){    umask(0);    if(fork()>0)    {        exit(0);    //父进程退出    }    setsid();     //设置新会话    chdir("/");   //更改当前工作目录为根目录    close(0);    //关闭标准输入流    close(1);     //关闭标准输出流    close(2);    //关闭标准错误流    signal(SIGCHLD,SIG_IGN);   //忽略SIGCHLD信号    while(1)    {        sleep(1);    }    return 0;}

可以看到,上面的代码中fork了一次就完成了对守护进程的创建。那为什么有人创建时需要fork两次呢?一次和两次的作用是不同的,如下:
调用第一次fork的作用
让shell认为这条命令已经终止,不用挂在终端输入上;为后面setsid服务,因为调用setsid函数的进程不能是进程组组长,如果不fork出子进程,则此时的父进程是进程组组长,就无法调用setsid。当子进程调用完setsid函数之后,子进程是会话组长也是进程组组长,并且脱离了控制终端,此时,不管控制终端如何操作,新的进程都不会收到一些信号使得进程退出。
第二次fork的作用
虽然当前关闭了和终端的联系,但是后期可能会误操作打开了终端。
但是只有会话首进程能打开终端设备,所以再fork一次,把父进程退出,再次fork的子进程作为守护进程继续运行,保证了该精灵进程不是对话期的首进程,第二次不是必须的,是可选的。

总结


守护进程是Linux中重要的角色,它无控制终端,自成会话,生存周期与用户登录注销无关,常用于常驻内存的网络服务。Linux提供了一个函数可以直接创建守护进程。

int daemon(int nochdir, int noclose);

使用时两个参数都传0即可,代表当前工作目录变更为根目录;关闭文件描述符。相当于文件描述符重定向到 /dev/null,写入到这里的内容会被操作系统丢弃。

0 0
原创粉丝点击