守护进程
又叫精灵进程,在linux或者unix操作系统中在系统引导的时候会开启很多服务,这些服务就叫做守护进程。为了增加灵活性,root可以选择系统开启的模式,这些模式叫做运行级别,每一种运行级别以一定的方式配置系统。 守护进程是脱离于终端并且在后台运行的进程。守护进程脱离于终端是为了避免进程在执行过程中的信息在任何终端上显示并且进程也不会被任何终端所产生的终端信息所打断
会话:进程组的更高一级,多个进程对应一个会话
进程组:多个进程在一个组,第一个进程默认是进程组组长
!!!!创建会话的时候,组长不可以创建,必须是组员创建!!!!
会话首进程:在会话中运行的第一个进程,通常用该进程的pid标识这个会话
进程组组长:pid和组pid相同的进程组中的进程
如下图所示
pid 进程号
ppid 父进程号
sid 标识会话的pid
gid 进程组的pid
我们不难看出
sid和父进程号也就是当前终端bash的pid,即会话中,第一个开始运行的进程
每次执行程序,gid和当前进程的pid相同,也就是说,当前的进程就是进程组的组长,用组长的pid来标识这个进程组
守护进程编程流程:
1.先fork(),退出父进程
所有工作在子进程中进行形式上脱离了控制终端
2. setsid(),创建新会话
使子进程独立出来,脱离控制
3. fork(),退出父进程
再次确定为组员创建新会话
4. chdir(“/”)
防止占用可卸载的文件系统,也可换成其他路径
5. umask(0)清除掩码
防止继承的文件创建屏蔽字拒绝某些权限,增加守护进程的灵活性
6. close()关闭描述符
继承的打开文件不会用到,浪费系统资源,无法卸载
注意
调用setsid函数后的进程:
1.成为一个组的组长进程
2.成为一个会话的会话首进程
3.放弃了控制终端
创建并运行的守护进程,在终端用ps无法查看
因为守护进程已经不是这个会话当中的了,我们可以通过ps -ef | grep 【文件名】来查看
如果要结束就用kill指令
如下图
在这里举一个例子
现在要实现一个守护进程,让这个进程每隔5秒就在一个文件中打印当前时间
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
pid_t pid;
pid = fork();
if(pid!=0)
{
exit(0);
}
setsid();
pid = fork();
if(pid!=0)
{
exit(0);
}
chdir("/");
umask(0);
int i = 0;
for(;i<getdtablesize();i++)
{
close(i);
}
while(1)
{
FILE* fp = fopen("/home/clbc/lff/2020hanjia/getsid/log","a");
if(fp == NULL)
{
break;
}
time_t tv;
time(&tv);
fprintf(fp,"NOW time:%s\n",asctime(localtime(&tv)));
printf("ok\n");
fclose(fp);
sleep(5);
}
return 0;
}