第三十六讲 守护进程
一、守护进程
在前面一讲我们知道会话用来管理前后台进程组。会话一般有直接关联着一个终端。此时当我们退出终端之后,现在所使用的会话也会被关闭,会话所管理的前后台进程也随之会被关闭。
守护进程是不受终端影响的,当终端退出后,进程也不会被影响
二、编写一个守护进程
1、步骤
-
创建一个子进程,父进程直接退出
方法:通过 fork 函数创建
如果父进程不退出,将会占有终端的使用权限,子进程不会拥有终端的使用权,所以父进程创建子进程之后就会退出,让出终端使用权。
-
创建一个新的会话
方法:setsid 创建会话
现在的会话是父进程所在的会话,进程在创建时会关联着一个终端。创建子进程后当前进程关联的终端就是父进程创建时所关联的终端。所以当前子进程受这个终端的影响。这样就达不到我们的目的。想要子进程不受当前终端影响,这就需要创建一个新的会话。新的会话不关联任何终端,所以终端关闭不会对新的会话造成任何影响。守护进程也不会被关闭。
-
改变守护进程当前的工作目录
方法:chrdir 函数
一般改为根目录, 即 “/”
在使用
fork
函数创建进程时,它的工作目录为父进程工作目录,这样子进程在操作工作目录的时候是有限制的。例如当前工作目录挂在这一些其他的文件系统,在守护进程中是没有办法卸载掉挂载的文件系统的。 -
重设文件权限的掩码
新建文件的时候主要受到文件权限主要受到掩码的影响。可以通过 umask 查看当前文件掩码值。
新建文件默认执行权限为666,真正的文件权限为666&~unmask
-
关闭不需要的文件描述符
通过clse函数可以关闭
关闭标准输入、标准输出、出错
2、代码
小贴士:守护进程执行了之后会一直打印日志,实验完成一定要记得把守护进程杀掉,不然你的虚拟机或者设备可能储存空间可能因为这个守护进程崩溃!!!!使用kill命令可以杀掉!!!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/stat.h>
int main()
{
pid_t pid;
int i = 0, fd;
// 创建进程
pid = fork();
if(pid < 0)
{
printf("fork error!\r\n");
exit(1);
}
// 销毁父进程
if(pid > 0)
{
exit(0);
}
// 创建会话
setsid();
// 改变当前工作目录
chdir("/");
// 重设文件掩码
umask(0);
// 关闭默认文件描述符 标准输入/输出/出错
for(i = 0; i < 3; i ++)
{
close(i);
}
// 实现守护进程功能
while(1)
{
fd = open("/var/log/daemon.log", O_CREAT | O_WRONLY | O_APPEND, 0666);
if(fd < 0)
{
printf("open file failed!");
return -1;
}
else
{
write(fd, "hello daemon!\r\n", strlen("hello daemon!\r\n"));
close(fd);
sleep(5);
}
}
}
3、将普通代码伪装成守护进程
1、方法
使用函数 nohup
2、语法格式
nohup Command [ Arg … ] [ & ]
3、示例
nohup deamon &