接上一篇文章,先来回顾作业,再来学习守护进程
基于VS2019 C++的跨平台(Linux)开发(1.3.2)——进程管理
一、回顾作业
详解见以下链接
c++ 文件拆分与合并——结合linux进程管理wait/waitpid
二、守护进程
守护进程,也就是通常所说的精灵进程,是Linux中的后台服务进程,生存期较长的进程,通常独立于控制终端并且周期性的执行某种任务或者等待处理某些发生的事情。
守护进程是在后台运行不受终端控制的进程;是能自动转到后台并且脱落与终端的联系;linux系统中一般有很多守护进程在后台运行 ,执行不同的管理任务。
守护进程的特性:
- 后台运行
- 必须与运行钱的环境隔离开来
- 启动方式尤其特殊之处
守护进程运行环境:
包括未关闭的文件描述符、控制终端、会话和进程组,工作目录以及文件创建掩膜等
这些环境通常是守护进程从执行它的父进程中继承下来的(特别是shell)
守护进程的启动方法:
1、在系统启动时很多守护进程都是由系统初始化脚本启动,这些脚本一般在etc目录以及etc/rc开头的目录下,他们的位置和内容依赖于具体的实现
2、许多网络服务器由inetd超级服务器启动的,inetd是由系统初始化脚本启动的
3、corn守护进程按规则定期执行一些程序,由它启动的程序也以守护进程的方式运行,corn是由系统初始化脚本启动
4、不管是在前台还是在后台,守护进程也可以在用户终端上启动
守护进程编程步骤:
1、创建子进程,父进程退出;所有工作在子进程中进行;形式上脱离了控制终端
2、在子进程中创建新会话;setsid函数;使用子进程完全独立出来,脱离控制
3、改变当前目录为根目录;chdir函数;防止占用可卸载的文件系统;也可以换成其他路径
4、重设文件权限掩码;umask函数;防止继承的文件创建屏蔽字拒绝某些权限;增加守护进程灵活性
5、关闭文件描述符;继承的打开文件用不到,浪费系统资源,无法卸载;getdtablesize函数;
返回所在进程的文件描述表的项数,即这个进程打开的文件数目
6、开始执行守护进程核心工作
7、 守护进程退出处理
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
void daemon(void)
{
pid_t pid;
//成为一个新会话的首进程,失去控制终端
if ((pid = fork()) < 0) {
perror("fork");
exit(1);
}
/* parent */
else if (pid != 0)
exit(0);
setsid();
//改变当前工作目录到/根目录下
if (chdir("/") < 0) {
perror("chdir");
exit(1);
}
/* 设置umask为0 */
umask(0);
//重定向0,1,2文件描述符到 /dev/null,因为已经失去控制终端,再操作0,1,2没有意义.
close(0);
open("/dev/null", O_RDWR);
dup2(0, 1);
dup2(0, 2);
}
int main(void)
{
//调用守护进程函数
daemon();
//在此循环中可以实现守护进程的核心工作
while(1);
}
注意:
变成一个守护进程之后不再和当前终端关联。运行带x参数的ps命令可以看到。此外,用户关闭终端窗口或者注销也不影响守护进程的运行。
三、IPC通信
现在linux使用的进程间通信方式:
- 信号(signal)
- 管道(pipe)和命名管道(FIFO)
- 消息队列
- 共享内存
- 信号量
- 套接字(socket)
以上的通信方式会在后续中进行一一学习