一、守护进程是什么?
定义:脱离于终后台服务程序端,在后台独立运行的程序;
特点:
- 独立控制终端,用户不需要和终端交互;
- 周期性的执行某任务;
- 不受用户登录注销的影响;
- 一般采用d结尾的名字(服务)
了解了守护进程的基本概念之后,还需要了解两个知识点:
进程组
和会话
- 进程组
一个或多个进程的集合;
进程组ID作为唯一标识;
组长进程是进程组的第一个进程;
进程组的ID == 进程组的组长的ID; - 会话
会话是由多个进程组组成; - 创建一个会话注意的事项
*不能是组长进程;
创建会话的进程成为新进程组的组长;
创建的新会话会丢弃原有的控制终端;
一般步骤:先fork(),父进程死,子进程创建会话(setsid());
获取进程所属的会话ID
pid_t setsid(pid_t pid);
创建一个会话:
pid_t setsid(void);
二、创建守护进程的过程
1.枯燥的概念
- 创建子进程,父进程退出;
- 子进程创建新的会话,调用setsid();
setsid()函数的作用
- 在上一步,调用fork()创建子进程,再将父进程退出;
- 而在调用fork()时,子进程全盘拷贝了父进程的会话、进程组和控制终端,虽然父进程退出了,但是这些没有改变,因此还不是真正意义的独立开来;
- 而setsid()可以使进程完全独立,从而摆脱其它进程的控制。
-
改变当前目录为根目录
-
重设文件权限掩码
文件权限掩码是指屏蔽文件权限的对应位;
比如,有一个文件的权限掩码是050,它就屏蔽了文件组的可读和可执行权限。
使用fork()新建的子进程继承了父进程的文件权限掩码,这会给子进程使用文件带来很多麻烦,因此把文件权限掩码设置为0 ,可以增强守护进程的灵活性,一般用umask(0);
- 关闭文件描述符
与文件权限码一样,使用fork()创建的子进程会继承父进程的一些已经打开的文件,这些文件可能用于不会被守护进程读写,但是它们一直消耗系统资源。
在第2步之后,子进程即守护进程已经与所属终端断了联系;
因此,从终端输入的字符不可能到达守护进程,守护进程中用常规方法输出的字符也不可能在终端打印出来;
所以,文件描述符0(输入),1(输出),2(报错)已经失去了存在的价值,应该被关闭。
2.直观的代码
代码如下:
/*
守护进程实例:每隔2s获取一次系统时间,写入到文本文件中;
*/
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/types.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/stat.h>
#include <time.h>
void func(int no); // callback function
int main(int argc, char **argv)
{
pid_t pid = fork();
if(pid >0)
{
printf("parent process exit\n");
_exit(1);
}
else if(pid == 0)
{
setsid(); //child create session
umask(0);
close(STDIN_FILENO); //close file descriptor
close(STDOUT_FILENO);
close(STDERR_FILENO);
struct sigaction act;
act.sa_flags = 0;
act.sa_handler = func;
sigaddset(&act.sa_mask, SIGQUIT);
itimerval time; //set timer
time.it_value.tv_sec = 2;
time.it_value.tv_usec = 0;
time.it_interval.tv_sec = 1;
time.it_interval.tv_usec = 0;
sigaction(SIGVTALRM, &act, NULL);
setitimer(ITIMER_VIRTUAL, &time, NULL);
while(true);
}
return 0;
}
void func(int no)
{
time_t currtime;
time(&currtime);
char* ptr = ctime(&currtime);
int fd = open("/home/fork/setsid.txt", O_CREAT | O_WRONLY | O_APPEND, 0777);
write(fd, ptr, sizeof(ptr)+1);
close(fd);
}
总结
这部分知识点有点枯燥啊,守护进程,孤儿进程,僵尸进程,继续努力,稍后再更新!