一、守护进程的概念
- 守护进程是脱离于终端控制,且运行在后端的进程。(孤儿进程)
- 守护进程不会将信息显示在任何终端上影响前端的操作,也不会被终端产生的任何信息打断,例如(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;
}
运行结果: