Linux daemon进程的应用、实现和原理

什么情况下用daemon进程

nohup ./XXX &写成daemon程序,可以手动执行,退出终端时程序不退出。

(1)首先,清理过期日志这一类需求,可以写一个死循环一直运行,也可以写在crontab里,,每次执行完就退出(如果每分钟一次可以满足的话);

(2)crontab的需要接受最多1分钟的时延,如果实时性要求更高一些,那么就需要考虑写个死循环了,这个程序可以由crontab来start和restart,只有在挂了重启时才会出现1分钟时延;

* * * * * /usr/bin/flock -nx /home/chenming/lock/test1.lock -c '/home/chenming/test1 >/dev/null 2>&1'(3)服务不能中断的(nginx、redis、apache,所有在线服务),一般都是daemon程序。但理论上用(2)似乎也可以;当然这两者细节上有很多区别。

怎么用daemon进程

linux C/C++可以直接调用int daemon(int, int)函数,不需要自己重新实现。示例代码:

#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <iostream> int main(int argc, char *argv[]) {if (argc < 3) {printf("Usage: $0 no_ch_dir no_close_fd\n");exit(0);}int no_ch_dir = atoi(argv[1]);int no_close_fd = atoi(argv[2]);std::cout << "main pid : " << getpid() << std::endl;std::cout << "main parent pid : " << getppid() << std::endl;std::cout << "main pwd : " << get_current_dir_name() << std::endl;if (daemon(no_ch_dir, no_close_fd) != 0) {// 一般都用daemon(0,0)// 成功返回0,失败返回-1// daemon(0,0):chdir到/,关闭0,1,2描述符。std::cout << "stdout: daemon = -1" << std::endl;std::cerr << "stderr: daemon = -1" << std::endl;return 1;}std::cout << "stdout: daemon = 0" << std::endl;std::cerr << "stderr: daemon = 0" << std::endl;std::cout << "sub pid : " << getpid() << std::endl;std::cout << "sub parent pid : " << getppid() << std::endl;std::cout << "sub pwd : " << get_current_dir_name() << std::endl;while (1);return 0;}编译运行:[chenming@localhost ~]$ g++ test1.cc -o test1[chenming@localhost ~]$ ./test1 0 0main pid : 7978main parent pid : 1382main pwd : /home/chenming[chenming@localhost ~]$ ps -ef | grep test194:chenming 7864 7573 0 16:09 pts/0 00:00:16 vim test1.cc95:chenming 78971 97 16:14 ?00:33:07 ./test1 0 097:chenming 79791 47 16:48 ?00:00:04 ./test1 0 099:chenming 7981 1382 8 16:49 pts/1 00:00:00 grep -inE –color test1[chenming@localhost ~]$ ll /proc/7979/fdtotal 0lrwx——. 1 chenming chenming 64 May 1 16:49 0 -> /dev/nulllrwx——. 1 chenming chenming 64 May 1 16:49 1 -> /dev/nulllrwx——. 1 chenming chenming 64 May 1 16:49 2 -> /dev/null[chenming@localhost ~]$ lsof -p 7979COMMAND PIDUSER FD TYPE DEVICE SIZE/OFF NODE NAMEtest1 7979 chenming cwd DIR 253,040962 /test1 7979 chenming rtd DIR 253,040962 /test1 7979 chenming txt REG 253,08355 142259 /home/chenming/test1test1 7979 chenming mem REG 253,0 122232 52742 /lib/libgcc_s-4.4.7-20120601.so.1test1 7979 chenming mem REG 253,0 142600 38788 /lib/ld-2.12.sotest1 7979 chenming mem REG 253,0 1906308 38865 /lib/libc-2.12.sotest1 7979 chenming mem REG 253,0 202040 47921 /lib/libm-2.12.sotest1 7979 chenming mem REG 253,0 942040 52866 /usr/lib/libstdc++.so.6.0.13test1 7979 chenming 0u CHR 1,30t0 3903 /dev/nulltest1 7979 chenming 1u CHR 1,30t0 3903 /dev/nulltest1 7979 chenming 2u CHR 1,30t0 3903 /dev/null

man 3 daemon可以查看到函数签名:

#include <unistd.h>

int daemon(int nochdir, int noclose);

怎么写daemon进程

1.fork,父进程退出

2.setsid。跟终端脱离关系。

3.umask、关掉0,1,2文件描述符。

4.chdir

5.信号处理

这里只有1和 2是必须的。3一般都会做;5大部分不做。

自己实现一个:

#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <iostream>#include <sys/types.h>#include <sys/stat.h>int daem(int no_ch_dir, int no_close_fd) {int pid = fork();if (pid < 0) {return -1;}else if (pid > 0){exit(0);}if (setsid() < 0) {return -1;}if (no_ch_dir == 0) {chdir("/");}umask(0);if (no_close_fd == 0) {close(0);close(1);close(2);}return 0;}redis的实现:void daemonize(void) {int fd;if (fork() != 0) exit(0); /* parent exits */setsid(); /* create a new session *//* Every output goes to /dev/null. If Redis is daemonized but* the 'logfile' is set to 'stdout' in the configuration file* it will not log at all. */if ((fd = open("/dev/null", O_RDWR, 0)) != -1) {dup2(fd, STDIN_FILENO);dup2(fd, STDOUT_FILENO);dup2(fd, STDERR_FILENO);if (fd > STDERR_FILENO) close(fd);}}带着感恩的心启程,学会爱,爱父母,爱自己,爱朋友,爱他人。

Linux daemon进程的应用、实现和原理

相关文章:

你感兴趣的文章:

标签云: