一、守护进程特征
1、生命周期很长。
2、在后台运行且不拥有控制终端。
二、守护进程创建
1、脱离当前进程。
2、释放控制终端。
3、禁止打开控制终端。
4、设置进程 umask。
5、修改进程当前工作目录。
6、关闭打开的文件描述符。
7、重定向文件描述符 0, 1, 2 到 /dev/null。
三、实现
1、becomeDaemon.h
#ifndef BECOME_DAEMON_H
#define BECOME_DAEMON_H
int becomeDaemon(void);
#endif
2、becomeDaemon.c
#include "becomeDaemon.h"
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
/*
* 功能:使当前进程成为守护进程
* 参数:flag
* 返回值:成功返回0、失败返回-1
*/
int
becomeDaemon(void)
{
int maxfd = 0, fd = 0;
// 1、脱离当前进程
switch(fork()){
case -1: return -1;
case 0: break;
default: _exit(0);
}
// 2、释放控制终端
if(setsid() == -1){
return -1;
}
// 3、禁止打开控制终端
switch(fork()){
case -1: return -1;
case 0: break;
default: _exit(0);
}
// 4、设置进程 umask
umask(0);
// 5、修改进程当前工作目录
chdir("/");
// 6、关闭打开的文件描述符
maxfd = sysconf(_SC_OPEN_MAX);
if(maxfd == -1){
return -1;
}
for(fd=0;fd<maxfd;fd++){
close(fd);
}
// 7、重定向文件描述符 0, 1, 2 到 /dev/null
close(STDIN_FILENO);
fd = open("/dev/null",O_RDWR);
if(fd != STDIN_FILENO){
return -1;
}
if(dup2(STDIN_FILENO,STDOUT_FILENO) != STDOUT_FILENO){
return -1;
}
if(dup2(STDIN_FILENO,STDERR_FILENO) != STDERR_FILENO){
return -1;
}
return 0;
}
3、main.c
#include "becomeDaemon.h"
int main(int argc,char* argv[])
{
becomeDaemon();
while(1);
}
四、测试
1、编译
onlylove@ubuntu:~/my/linux/01$ ls -l
total 12
-rw-rw-r-- 1 onlylove onlylove 1269 Jun 5 15:36 becomeDaemon.c
-rw-rw-r-- 1 onlylove onlylove 81 Jun 5 15:36 becomeDaemon.h
-rw-rw-r-- 1 onlylove onlylove 96 Jun 5 15:37 main.c
onlylove@ubuntu:~/my/linux/01$
onlylove@ubuntu:~/my/linux/01$ gcc -o daemonTest becomeDaemon.c main.c
onlylove@ubuntu:~/my/linux/01$ ls -l
total 32
-rw-rw-r-- 1 onlylove onlylove 1269 Jun 5 15:36 becomeDaemon.c
-rw-rw-r-- 1 onlylove onlylove 81 Jun 5 15:36 becomeDaemon.h
-rwxrwxr-x 1 onlylove onlylove 17120 Jun 5 15:42 daemonTest
-rw-rw-r-- 1 onlylove onlylove 96 Jun 5 15:37 main.c
onlylove@ubuntu:~/my/linux/01$
2、daemonTest 进程启动前
onlylove@ubuntu:~$ ps -axj |grep daemonTest
3687 3873 3872 3687 pts/1 3872 S+ 1000 0:00 grep --color=auto daemonTest
onlylove@ubuntu:~$
3、启动 daemonTest 进程
onlylove@ubuntu:~/my/linux/01$ ls -l
total 32
-rw-rw-r-- 1 onlylove onlylove 1269 Jun 5 15:36 becomeDaemon.c
-rw-rw-r-- 1 onlylove onlylove 81 Jun 5 15:36 becomeDaemon.h
-rwxrwxr-x 1 onlylove onlylove 17120 Jun 5 15:42 daemonTest
-rw-rw-r-- 1 onlylove onlylove 96 Jun 5 15:37 main.c
onlylove@ubuntu:~/my/linux/01$ ./daemonTest
onlylove@ubuntu:~/my/linux/01$
4、daemonTest 进程启动后
onlylove@ubuntu:~$ ps -axj |grep daemonTest
1 3879 3878 3878 ? -1 R 1000 0:29 ./daemonTest
3687 3881 3880 3687 pts/1 3880 S+ 1000 0:00 grep --color=auto daemonTest
onlylove@ubuntu:~$
5、查看 daemonTest 进程打开的文件描述符
onlylove@ubuntu:~$ ps -axj |grep daemonTest
1 3930 3929 3929 ? -1 R 1000 4:11 ./daemonTest
3687 3955 3954 3687 pts/1 3954 S+ 1000 0:00 grep --color=auto daemonTest
onlylove@ubuntu:~$
onlylove@ubuntu:~$ ls /proc/3930
arch_status cmdline environ limits mounts oom_score root smaps_rollup task
attr comm exe loginuid mountstats oom_score_adj sched stack timens_offsets
autogroup coredump_filter fd map_files net pagemap schedstat stat timers
auxv cpu_resctrl_groups fdinfo maps ns patch_state sessionid statm timerslack_ns
cgroup cpuset gid_map mem numa_maps personality setgroups status uid_map
clear_refs cwd io mountinfo oom_adj projid_map smaps syscall wchan
onlylove@ubuntu:~$
onlylove@ubuntu:~$ ll /proc/3930/fd
total 0
dr-x------ 2 onlylove onlylove 0 Jun 5 15:53 ./
dr-xr-xr-x 9 onlylove onlylove 0 Jun 5 15:49 ../
lrwx------ 1 onlylove onlylove 64 Jun 5 15:53 0 -> /dev/null
lrwx------ 1 onlylove onlylove 64 Jun 5 15:53 1 -> /dev/null
lrwx------ 1 onlylove onlylove 64 Jun 5 15:53 2 -> /dev/null
onlylove@ubuntu:~$
6、关闭 daemonTest 进程
onlylove@ubuntu:~$ ps -axj |grep daemonTest
1 3879 3878 3878 ? -1 R 1000 1:47 ./daemonTest
3687 3887 3886 3687 pts/1 3886 R+ 1000 0:00 grep --color=auto daemonTest
onlylove@ubuntu:~$ kill -9 3879
onlylove@ubuntu:~$ ps -axj |grep daemonTest
3687 3889 3888 3687 pts/1 3888 S+ 1000 0:00 grep --color=auto daemonTest
onlylove@ubuntu:~$
五、参考
守护进程_lianghe_work的博客-CSDN博客_守护进程
《Linux/UNIX 系统编程手册》 第 37 章。