一、守护进程的概念
- 守护进程是脱离于终端控制,且运行在后端的进程。(孤儿进程)
- 守护进程不会将信息显示在任何终端上影响前端的操作,也不会被终端产生的任何信息打断,例如(ctrl+c).
- 守护进程独立于控制终端,会周期性执行某个任务。(运行在死循环中)
- 守护进程用于:与操作系统启动相关的进程。大多数服务器都是用守护进程实现。
二、创建守护进程的流程
1.创建一个孤儿进程:所有任务运行在孤儿进程中,形式上脱离终端控制
让父进程结束运行,而子进程继续运行
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <errno.h>
#include <pthread.h>
int main(int argc, const char *argv[])
{
int res=fork();
if(res>0){ //父进程
exit(0);
}else if(res==0){ //子进程
while(1);
}else{
exit(0);
}
return 0;
}
2.新建会话:使子进程完全独立
setsid函数:创建新的进程组,创建新的会话组
pid_t setsid(void);
返回值:
成功,创建的会话组id sid
3.将当前进程对应的路径切换到根目录
chdir函数:切换路径
int chdir(const char *path);
返回值:
成功返回0
失败返回-1置位错误码
4.设置umask值
mode_t umask(mode_t mask);
功能:设置掩码
参数:
mask:掩码的值
返回值:总是会成功,返回mask
5.进行文件描述重定向
int dup(int oldfd):
功能:拷贝fd,产生一个新的文件描述符nfd
nfd产生的原则为最小未使用原则,fd和nfd都可以操作同一个文件
文件fd和nfd共用同一个光标
参数:
old:旧的文件描述符
返回值:
成功返回nfd,失败返回-1置位错误
int dup2(int oldfd,int newfd)
功能:dup2函数相当于文件描述符的重定向
把newfd重定向到oldfd中,以后向newfd写内容就是在向oldfd对应的文件中写内容
参数:
oldfd:旧文件描述符
newfd:新文件描述符
返回值:成功返回newfd,失败返回-1置位错误码
(实际使用:其实是吧newfd重新定位为oldfd,需要反过来)
三、代码演示
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <errno.h>
#include <pthread.h>
int main(int argc, const char *argv[])
{
int res = fork();
if(res == 0 )
{//1.创建孤儿进程
//2.创建会话
setsid();
//3.切换到根目录
chdir("/");
//4.重设文件掩码:守护进程一般保留文件原有权限
umask(0);
//5.创建日志文件
//getdtablesize:获取进程的最大的文件描述符
for(int i=3;i<getdtablesize();i++){
close(i);//把之前开了的文件都关了
}
int fd;
fd=open("my.log",O_RDWR|O_APPEND|O_CREAT,0666);
if(fd==-1){
perror("open");
}
//6.文件描述符重定向
dup2(fd,0);
dup2(fd,1);
dup2(fd,2);
//7.开启自己的服务
while(1){
write(1,"hello",6);
putchar(10);
sleep(1);
}
close(fd);
}
else if(res > 0)//父进程
{
exit(0);
}
else
{
perror("fork");
return -1;
}
return 0;
}
运行结果: