进程组与会话
进程组
进程组,也称之为作业,顾名思义,代表一个或多个进程的集合,设计进程组的概念是为了简化对多个进程的管理。
父进程创建子进程的时候,默认父子进程位于同一个进程组,进程组的ID就是第一个进程的ID,第一个进程成为进程组的组长。
只要进程组有一个进程存在,进程组就存在,与组长进程是否终止无关。
进程组生存期:进程组的最后一个进程终止。
一个进程可以为自己或者子进程设置进程组ID
进程组操作函数
- getpgrp 获取当前进程的进程组ID
- getpgid 获取指定进程的进程组ID
- setpgid 改变进程默认所属的进程组,通常可用来加入一个现有的进程组或创建一个新进程组
会话###
会话是一个进程组或者多个进程组的集合,通常一个会话开始于用户登录,终止与用户退出,在此期间,该用户运行的所有程序都属于这个会话
创建一个会话需要注意以下几个事项:
- 创建会话的进程不能是某个进程组的组长
- 创建会话的进程成为这个会话的会长和会话里第一个进程组的组长
- 新会话丢弃原有的控制终端,该会话没有控制终端
- 建立新会话步骤,先fork一个子进程,然后父进程退出,子进程调用setsid
会话相关的两个函数:
- getsid 查看当前进程的会话ID
- setsid 创建一个会话,并以自己的ID为会话ID
守护进程
daemon进程,即守护进程是指linux后台服务程序,通常独立于控制终端并且周期性的执行某种任务,名字一般以d结尾
linux的系统服务进程,没有控制终端,不能直接和用户交互等都是守护进程,如nfs服务器,ftp服务器
创建守护进程模型
创建守护进程的过程实际上是创建一个新的会话,跳出控制终端建立的会话,达到脱离于终端运行的目的。创建守护进程模型有以下几个步骤:
- 创建子进程,退出父进程
- 子进程调用setsid创建会话,成为会话第一个进程组的组长
- 改变当前目录为根目录,不是必须,为了防止当前目录被删除
- 重设文件权限掩码umask为0
- 重定向标准输入,标准输出和标准错误到/dev/null
- 开始守护进程的逻辑
示例代码
/*
* 创建一个守护进程
*
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
int main()
{
pid_t pid;
int i;
pid = fork();
/* 干掉父进程 */
if (pid > 0)
{
exit(0);
}
/* 创建会话期 */
pid = setsid();
printf("pid = %d \n", getpid());
if (pid == -1)
{
perror("setsid error :");
exit(0);
}
/* 改变文件掩码 */
umask(0);
/* 切换目录到根目录 */
chdir("/");
/* 重定位标准输入、输出、错误到/dev/null */
for (i=0; i<3; i++)
{
close(i);
}
open("/dev/null",O_RDWR);
dup(0);
dup(0);
int fd;
time_t t;
char *t_buffer;
fd = open("timelog", O_CREAT | O_RDWR, 0644);
if (fd == -1)
{
perror("fd error:");
exit(-1);
}
while (1)
{
t = time(0);
t_buffer = asctime(localtime(&t));
write(fd, t_buffer, strlen(t_buffer));
sleep(5);
}
}
这个程序首先创建了一个守护进程,在守护进程里每隔5秒打印当前系统的时间到timelog日志文件里。
由于切换工作目录为根目录,因此执行的时候需要加上sudo权限,运行结果:
可以看到,这个守护进程的所属用户已经变成了root用户,父进程为1号进程,tty为?,表示不属于任何终端
使用sudo killall + 守护进程的名字可以杀掉守护进程
daemon函数
除了上述方法可以创建一个守护进程外,也可以使用daemon函数创建一个守护进程。
int daemon(int nochdir, int noclose);
参数:
- nochdir:=0 将当前目录更改至“/”
- noclose:=0 将标准输入、标准输出、标准错误重定向至“/dev/null”
返回值
- 成功返回0
- 失败返回-1
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!