8 守护进程
约 1839 字大约 6 分钟
2025-06-18
寻常写的程序它的生命周期只在当前控制台, 当控制台关闭后进程也就关闭了 控制终端是与会话关联的终端设备它是用户输入和输出的通道。进程通常通过其控制终端与用户交互,接收输入和向用户显示输出。对于守护进程来说,它必须从任何控制终端中脱离,确保其独立于任何用户会话在后台运行,这样才能保证其稳定性和安全性,不受用户直接控制和会话结束等事件的影响。
步骤
创建子进程并结束父进程 在程序中先调用
fork()
创建子进程, 然后再把父进程关闭使子进程变为孤儿进程. 这样让孤儿进程被更高一级的祖先进程收养, 如: 内核进程,内核进程通常不会关闭,除非计算机关机设置会话ID
setsid()
创建一个新会话,并使调用它的进程成为新会话的领导者,这样做的主要目的是让守护进程摆脱原来的控制终端。这样,守护进程就不会接收到终端发出的任何信号,例如挂断信号(SIGHUP),从而保证其运行不受前台用户操作的影响。
如果调用进程不是进程组的领导者,则创建一个新的会话。创建者是新会话的领导者
- return: 成功则返回调用进程的新会话ID,失败则返回(pid_t)-1,并设置errno以指明错误原因
pid_t setsid(void);
第二次创建子进程 设置会话ID时成为了自己会话的领导但还是有可能被终端控制(避免意外), 再次创建孙子进程并杀死子进程使本会话没有领导者,也就不会被任何东西控制
更改工作目录 将工作目录更改到根目录,主要是为了避免守护进程继续占用其启动时的文件系统。这对于可移动的或网络挂载的文件系统尤其重要,确保这些文件系统不需要时可以被卸载。
更改调用进程的工作目录
- path: 更改后的工作路径
- return: 成功返回0,失败返回-1,并设置errno
int chdir(const char *path);|
- 重设文件权限掩码 每个文件都带有一个umask权限掩码作用类似于子网掩码,对文件进行权限设置时会被umask修正 调用
umask(0)
确保守护进程创建的文件权限不受继承的umask值的影响, 守护进程可以更加精确地控制其创建的文件的权限
设置调用进程的文件模式创建掩码。
- mask: 掩码。是一个八进制数,它指定哪些权限位在文件或目录创建时应被关闭。我们通过umask(0)确保守护进程创建的文件和目录具有最开放的权限设置。
- return: 这个系统调用必然成功,返回之前的掩码值
mode_t umask(mode_t mask);
关闭文件描述符 守护进程通常不需要标准输入、输出和错误文件描述符,因为它们不与终端交互。关闭这些不需要的文件描述符可以避免资源泄露,提高守护进程的安全性和效率。
处理信号
SIGHUP
和SIGTERM
信号。
SIGHUP
:虽然守护进程和终端断开,但仍然有可能收到其它进程或内核发来的SIGHUP
信号,让守护进程不因为它而终止。SIGTERM
:是终止信号,用于请求守护进程终止。通过命令行执行kill<pid>命令可以发送SIGTERM
信号,接收到这个信号之后,守护进程终止子进程,并清理回收资源,最后退出。
执行具体任务
日志信息 守护进程切断了与控制台的关系也就无法报错输出错误信息了 使用
openlog
接入一个日志系统, 把要输出的日志写入到系统上去就可以了\
输出日志(报错) 为程序开启一个面向系统日志的连接
- ident: 每条消息的字符串前缀,按照惯例通常设置为程序名称
- option:指定控制openlog和后续syslog调用的标志。常见标志包括:
LOG_PID
:在每条日志消息中包含进程ID。LOG_CONS
:如果无法将消息发送到日志守护进程,则直接将消息写入控制台。LOG_NDELAY
:立即打开与系统日志守护进程的连接。LOG_ODELAY
:延迟打开与系统日志守护进程的连接,直到实际写入日志时。LOG_PERROR
:将日志消息同时输出到标准错误输出。 - facility:指定日志消息的来源类别,用于区分系统不同部分的日志消息。包括:
LOG_AUTH
:认证系统LOG_SYSLOG
: Syslog自身的消息LOG_USER
:用户进程LOG_UUCP
:UUCP子系统
void openlog(const char *ident, int option, int facility);
生成日志信息 生成一条日志消息
- priority 由一个facility和一个level值或操作得到,如果未指定facility,则使用openlog指定的默认值,如果上文没有调用
openlog()
,则将使用默认值LOG_USER。level取值如下:LOG_EMERG
: (系统无法使用)表示系统已经不可用,通常用于严重的紧急情况。例如:系统崩溃或关键硬件故障LOG_ALERT
: (必须立即采取行动)表示必须立即采取措施解决的问题。例如:磁盘空间用尽或数据库崩溃。LOG_CRIT
: (严重条件)表示严重的错误或问题,但不需要立即采取行动。例如:应用程序的某个重要功能失败。LOG_ERR
: (错误条件)表示一般错误情况,需要注意和修复。例如:无法打开文件或网络连接失败。LOG_WARNING
: (警告条件)表示潜在问题或警告,建议检查,但不会立即影响系统功 能。例如:磁盘空间接近用尽或配置文件缺失。LOG_NOTICE
:(正常但重要的情况)表示正常运行过程中需要特别注意的事件。例如:系统启动或关闭成功。LOG_INFO
: (信息性消息)表示一般信息,用于记录正常操作的事件。例如:用户登录或定时任务完成。LOG_DEBUG
: (调试级别消息)表示详细的调试信息,通常用于开发和调试阶段。例如函数调用跟踪或变量值变化。 - format: 类似于printf()的格式化字符串
...
: 可变参数,可以传递给格式化字符串
void syslog(int priority,const char *format, ...);
系统日志的文件描述符 关闭用于写入系统日志的文件描述符
void closelog(void);
获取运行时的配置信息 获取运行时配置信息
- name配置名称,取值太多,可以通过
man 3 sysconf
自行查阅,我们只用到_SC_OPEN_MAX
,记录了当前进程可以打开的文件描述符的最大数量 - long: 配置的值
long sysconf(int name);
贡献者
版权所有
版权归属:PinkDopeyBug