守护进程
守护进程的概念
- Deamon:运行在后台的服务程序,周期性执行系统级任务或等待处理某些发生的事件
- 独立于终端,不与任何控制终端相关联
- 打印信息不会打印在终端上
- 守护进程会创建自己新的会话,避免与其它会话产生关系
守护进程的特点
- 后台运行,不与控制终端相连接
- 不受用户登录或注销的影响,一直在运行,一般为系统服务进程
- 生命周期较长,一般随系统启动和关闭,一直运行系统退出
- 不受SIGINT、SIGQUIT、SIGSTP跟终端相关的信号影响
- 关闭终端不会影响daemon进程的运行
- 守护进程命名:sshd、inetd、httpd(命名不是绝对的、通用的)
查看系统的守护进程
- 查看守护进程
- ps -axj | more
- 参数a:列出所有用户的进程
- 参数x:不仅列出控制终端的进程,还列出所有无控制终端的进程
- 参数j:列出与作业控制相关的信息
守护进程的应用
- Linux的守护进程
- Linux中大多数服务器或服务程序都是使用守护进程实现的
- Httpd :web服务器
- Inetd :Internet服务器
- Crond :作业规划进程
- Syslogd:日志维护 /var/log
- Acpid :电源维护
- Lqd :打印进程
- Dhcpd :DHCP服务进程
- Sshd:SSH服务进程
守护进程的启动
- 通过配置文件和脚本
- 配置文件:/etc
- 启动脚本:/etc/init.d、/etc/rc*.d、/etc/rc.local
- 启动脚本:/usr/lib/systemd/、/etc/systemd、/etc/sysconfig
- 将普通进程“包装”成守护进程:nohup ./a.out &
- nohup:不间断地运行命令
后台进程与守护进程的区别
- 守护进程已经完全脱离终端控制
- 后台程序没有脱离终端控制,一些信息会输出到终端
- 关闭终端时,后台进程会随之终止,而守护进程可以继续运行
- 守护进程有独立的会话、文件描述符、工作目录、而后台进程是继承父进程的
编程作业
编写一个守护进程并运行
- 屏蔽一些控制终端操作的信号
- 调用fork,父进程退出
- setsid创建一个新会话
- 禁止进程重新打开控制终端
- 关闭打开的文件描述符
- 改变当前工作目录
- 重设文件创建掩模
- 处理SIGCHLD信号
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
signal(SIGTTOU, SIG_IGN); // 屏蔽一些控制终端操作的信号
signal(SIGTTIN, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
signal(SIGHUP, SIG_IGN);
umask(0); // umask file mode inheriting from father process
pid_t ret_id = fork(); //调用fork,父进程退出
if (ret_id < 0 )
{
perror("fork");
exit(-1);
}
else if (ret_id > 0)
exit(0);
setsid(); //setsid创建一个新会话
signal(SIGCHLD, SIG_IGN);
ret_id = fork(); //fork again 禁止进程重新打开控制终端
if (ret_id < 0)
{
perror("fork");
exit(-1);
}
else if (ret_id > 0)
exit(0);
if (chdir("/") < 0)
{
perror("chdir");
exit(-1);
}
close(0);
close(1);
close(2);
while(1)
sleep(1);
return 0;
}