1.进程组
定义:进程的集合,进程组ID等于组长进程ID。类似于QQ群号等于群主QQ号。
生命周期:进程组里的最后一个进程离开的时候,进程组生命周期结束,也就是说只要有进程,该进程组就存在。
作用:简化对多个进程的管理。
函数:getpgrp()、getpgid()、setpgid()
进程组组长:创建这个进程组的进程,简称为该进程组组长(组长进程)。该进程组ID等于该进程ID。子进程进程组ID默认等于父进程进程组ID。 2.会话
定义:进程组的集合。非组长进程调用setsid函数创建一个会话,这个会话ID等于该进程ID,该进程的进程组也变为该进程ID,也就是该进程的会话ID==该进程的进程组ID==该进程ID。
注意:组长进程不能创建会话。因为一个进程创建会话后,该进程的进程组也变了,所以和"进程组ID等于组长进程ID"这句话就矛盾了。
特点:新会话会脱离原有的控制终端,所以会话没有控制终端。所以创建新会话是守护进程的关键一步。创建会话需要root权限(ubuntu除外不需要)。
函数:getsid()、setsid()、命令行输入ps -ajx 可查看与会话相关的进行信息 3.守护进程
定义:也称为精灵进程(daemond)。是一些后台服务进程,没有控制终端,不与用户直接交互,不受用户登陆注销的影响,一直运行着。比如sshd服务、ftpd服务等都是守护进程。
注意:创建守护进程,最关键的是调用setsid创建新的会话,成为该会话首进程。
创建守护进程步骤:
1)调用fork()创建子进程,非组长进程
2)调用setsid()创建新会话,脱离终端
3)调用chdir()改变工作目录,防止占用可卸载的文件系统
4)调用umask()重置文件权限掩码,防止继承父进程的文件屏蔽字拒绝某些权限
5)调用close()关闭打开的继承父进程的无用文件描述符
示例代码:
void test_daemond()
{
//1.fork()子进程
//2.sid()新建新会话,脱离终端
//3.chdir()切换工作目录,防止占用可卸载的文件系统
//4.umask(0)重置文件权限掩码,防止继承父进程的文件屏蔽字拒绝某些权限
//5.close(fd)关闭打开的继承父进程的无用文件描述符
pid_t pid = fork();//1.创建子进程,父进程退出
if (pid < 0)
{
perror("fork error");
exit(EXIT_FAILURE);
}
if (pid > 0)
{//parent
exit(EXIT_SUCCESS);
}
if (setsid() == -1)
{//2.创建新会话,脱离终端
perror("setsid error");
}
if (chdir("/") == -1)
{//3.切换工作目录,不一定是根目录哈
perror("chdir error");
}
printf("old umask:%d\n", umask(0));//4.重置文件掩码
//5.关闭标准输入输出错误流
close(STDIN_FILENO);//fd=0,先关闭fd=0
open("/dev/null", O_RDWR);//再打开该文件,根据最小fd可用原则,所以/dev/null对应的fd为0
dup2(STDIN_FILENO, STDOUT_FILENO);//将fd=1重定向到fd=0,并关闭fd=1
dup2(STDIN_FILENO, STDERR_FILENO);//将fd=2重定向到fd=0,并关闭fd=2
while (1)
{
sleep(1);
printf("daemond working...\n");
}
}
原文:https://www.cnblogs.com/yongfengnice/p/11961052.html