创建 SysV 风格的 linux daemon 程序

【自取】最近整理的,有需要可以领取学习:

本文介绍了如何在Linux系统中使用C语言创建SysV风格的守护程序。注:这是一种老式的编写守护程序的方式,进入SYSTEM D时代后,没有必要以这种方式创建守护程序。本文的演示环境是ubuntu 18.04。

[En]

This paper introduces how to use C language to create SysV-style daemon programs in Linux systems. Note: this is an old-fashioned way of writing daemon programs, and it is not necessary to create daemon programs in this way after entering the systemd era. The demo environment for this article is ubuntu 18.04.

通过前文《Linux session(会话)》我们了解到,如果要让程序运行在后台,必须处理好进程的 session。所以在创建 daemon 程序的过程中处理 session 问题是很重要的一步,当然除此之外还需要其它的步骤。下面是在 Linux 系统中创建一个 SysV 风格的 daemon 的基本流程:

接下来,我们通过代码介绍这些操作的含义。

[En]

Next, we introduce the meaning of these operations through the code.

从父进程 fork 出一个子进程
创建子进程,如果成功,让父进程退出,子进程成为init进程的子进程:

[En]

Create a child process, and if successful, let the parent process exit, and the child process has become a child process of the init process:

为子进程创建新的 session ID
后台运行的进程需要摆脱会话终端的束缚,可以通过setsid()函数为进程设置新的会话ID:

[En]

Processes running in the background need to get rid of the shackles of the session terminal, which can be done by setting a new session ID for the process through the setsid () function:


执行到这里时,PID==PGID==SID


在子进程中再 fork 一次
这次 fork 的目的是防止进程再次获得终端。因为只有 session leader 才能获得终端,而这次 fork 使子进程变成了非 session leader:


执行到这里时,PGID==SID 但是已经不等于 PID 了,说明进程已经不是 session leader


修改 umask
为了能够向 daemon 进程创建的任何文件中写入内容(包括日志),必须重置 umask(file mode mask, umask),以确保能够正确地写入或读取这些文件:

修改进程的当前工作目录
您必须确保该进程的当前工作目录存在。由于许多Linux发行版并不完全符合标准的文件目录结构,因此最好将进程的当前工作目录设置为/,以避免设置目录,使其无法卸载:

[En]

You must ensure that the current working directory of the process exists. Because many Linux distributions do not fully comply with the standard file directory structure, it is best to set the current working directory of the process to /, so as to avoid setting a directory so that it cannot be unmount:

关闭进程中的文件描述符
关闭进程中所有打开的文件描述符:

[En]

Close all open file descriptors in the process:

把日志写入 syslog
Daemon 程序的日志非常重要,我们可以通过 openlog、syslog 和 closelog 三个函数把日志内容写入到 syslog 中:

本文 demo 输出的日志如下所示:

完整的代码

这是一个很有意思的话题,有人说需要 fork 两次,有人说第二次是可选的,究竟该如何做呢?当我们理解了第二次 fork 的用途后就可以自行决定是否需要第二次 fork 了。
这还需要从 session 的控制终端说起。控制终端是进程的一个属性,通过 fork 系统调用创建的子进程会从父进程那里继承控制终端。这样,session 中的所有进程都从 session 领头进程那里继承控制终端。前面已经说过了,要把程序变成 daemon,就得让进程摆脱 session 的终端。而这些在第一次 fork 后调用 setsid() 函数就搞定了。那么如果接下来不小心再给进程添加了终端该怎么办?答案是不让你添加!这就是第二次 fork 的作用。只有 session leader 才能获得终端,而第二次 fork 使子进程变成了非 session leader,你想犯错也不给你机会了。

像 nginx 和 gblic 的 daemon 函数的实现都是 fork 一次,所以说第二次 fork 是可选的,你可以根据自己的实际情况来决定。

Original: https://www.cnblogs.com/sparkdev/p/12714790.html
Author: sparkdev
Title: 创建 SysV 风格的 linux daemon 程序

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/7227/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

发表回复

登录后才能评论
免费咨询
免费咨询
扫码关注
扫码关注
联系站长

站长Johngo!

大数据和算法重度研究者!

持续产出大数据、算法、LeetCode干货,以及业界好资源!

2022012703491714

微信来撩,免费咨询:xiaozhu_tec

分享本页
返回顶部