用C语言在Linux系统下创建守护进程(Daemon)
2017-12-01 17:15
429 查看
守护进程(daemon)是指在后台运行的,没有控制终端与之相连的进程。它独立于控制终端,周期性地执行某种任务。Linux的大多数服务器就是用守护进程的方式实现的。如web服务器进程http等。守护进程在后台运行,类似于Windows中的系统服务。
编写守护进程程序的要点:
(1)让程序在后台执行。方法是调用fork()产生一个子进程,然后使父进程退出。
(2)调用setsid()创建一个新对话期。控制终端、登录会话和进程组通常是从父进程继承下来的,守护进程要摆脱它们,不受它们的影响,方法是调用setsid()使进程成为一个会话组长。setsid()调用成功后,进程成为新的会话组长和进程组长,并与原来的登录会话、进程组和控制终端脱离。
(3)禁止进程重新打开控制终端。经过以上步骤,进程已经成为一个无终端的会话组长,但是它可以重新申请打开一个终端。为了避免这种情况发生,可以通过使进程不再是会话组长来实现。再一次通过fork()创建新的子进程,使调用fork的进程退出。
(4)关闭不再需要的文件描述符。子进程从父进程继承打开的文件描述符。如不关闭,将会浪费系统资源,造成进程所在的文件系统无法卸下以及引起无法预料的错误。首先获得最高文件描述符值,然后用一个循环程序,关闭0到最高文件描述符值的所有文件描述符。
(5)将当前目录更改为根目录。
(6)子进程从父进程继承的文件创建屏蔽字可能会拒绝某些许可权。为防止这一点,使用unmask(0)将屏蔽字清零。
(7)处理SIGCHLD信号。对于服务器进程,在请求到来时往往生成子进程处理请求。如果父进程不等待子进程结束,子进程将成为僵尸进程(zombie),从而占用系统资源。如果父进程等待子进程结束,将增加父进程的负担,影响服务器进程的并发性能。在Linux下可以简单地将SIGCHLD信号的操作设为SIG_IGN。这样,子进程结束时不会产生僵尸进程。
守护进程的实例:
编译运行上述程序。然后用ps -ef 命令查看进程状态,该进程状态如下:
从结果可以看出该进程具备守护进程的所有特征。
查看/var/log目录下,先前并不存在的test.log文件已经有了。
用vi打开该日志文件,记录如下:
最后需要关闭此守护进程。关闭的方法是通过ps -ef命令查询到该进程的进程号,之后再用kill 命令将其杀死。
注意:使用syslog函数前需要配置。但需要注意的是,在Centos6.x系统中,系统日志的配置文件已经发生了变化。不再是原来的/etc/syslog.conf了,而是/etc/rsyslog.conf。打开上述文件,在文件末尾加入下面一行:
然后重启syslog服务。重启的命令也修改为:/etc/init.d/rsyslog restart
实际上,Linux提供了完成上述同样功能的库函数:
#include <unistd.h>
int daemon(int nochdir,int noclose);
其中,nochdir参数用于指定是否改变工作目录,如果给它传递0,则工作目录将被设置为“/”(根目录),否则继续使用当前工作目录。noclose参数为0时,标准输入、标准输出和标准错误输出都被重定向到/dev/null文件,否则依然使用原来的设备。该函数成功时返回0,失败返回-1,并设置errno。
编写守护进程程序的要点:
(1)让程序在后台执行。方法是调用fork()产生一个子进程,然后使父进程退出。
(2)调用setsid()创建一个新对话期。控制终端、登录会话和进程组通常是从父进程继承下来的,守护进程要摆脱它们,不受它们的影响,方法是调用setsid()使进程成为一个会话组长。setsid()调用成功后,进程成为新的会话组长和进程组长,并与原来的登录会话、进程组和控制终端脱离。
(3)禁止进程重新打开控制终端。经过以上步骤,进程已经成为一个无终端的会话组长,但是它可以重新申请打开一个终端。为了避免这种情况发生,可以通过使进程不再是会话组长来实现。再一次通过fork()创建新的子进程,使调用fork的进程退出。
(4)关闭不再需要的文件描述符。子进程从父进程继承打开的文件描述符。如不关闭,将会浪费系统资源,造成进程所在的文件系统无法卸下以及引起无法预料的错误。首先获得最高文件描述符值,然后用一个循环程序,关闭0到最高文件描述符值的所有文件描述符。
(5)将当前目录更改为根目录。
(6)子进程从父进程继承的文件创建屏蔽字可能会拒绝某些许可权。为防止这一点,使用unmask(0)将屏蔽字清零。
(7)处理SIGCHLD信号。对于服务器进程,在请求到来时往往生成子进程处理请求。如果父进程不等待子进程结束,子进程将成为僵尸进程(zombie),从而占用系统资源。如果父进程等待子进程结束,将增加父进程的负担,影响服务器进程的并发性能。在Linux下可以简单地将SIGCHLD信号的操作设为SIG_IGN。这样,子进程结束时不会产生僵尸进程。
守护进程的实例:
#include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <signal.h> #include <sys/param.h> #include <sys/stat.h> #include <time.h> #include <syslog.h> int init_daemon(void) { int pid; int i; //忽略终端I/O信号,STOP信号 signal(SIGTTOU,SIG_IGN); signal(SIGTTIN,SIG_IGN); signal(SIGTSTP,SIG_IGN); signal(SIGHUP,SIG_IGN); pid = fork(); if(pid > 0) { exit(0); //结束父进程,使得子进程成为后台进程 } else if(pid < 0) { return -1; } //建立一个新的进程组,在这个新的进程组中,子进程成为这个进程组的首进程,以使该进程脱离所有终端 setsid(); //再次新建一个子进程,退出父进程,保证该进程不是进程组长,同时让该进程无法再打开一个新的终端 pid=fork(); if( pid > 0) { exit(0); } else if( pid< 0) { return -1; } //关闭所有从父进程继承的不再需要的文件描述符 for(i=0;i< NOFILE;close(i++)); //改变工作目录,使得进程不与任何文件系统联系 chdir("/"); //将文件当时创建屏蔽字设置为0 umask(0); //忽略SIGCHLD信号 signal(SIGCHLD,SIG_IGN); return 0; } int main() { time_t now; init_daemon(); syslog(LOG_USER|LOG_INFO,"TestDaemonProcess! \n"); while(1) { sleep(8); time(&now); syslog(LOG_USER|LOG_INFO,"SystemTime: \t%s\t\t\n",ctime(&now)); } }
编译运行上述程序。然后用ps -ef 命令查看进程状态,该进程状态如下:
从结果可以看出该进程具备守护进程的所有特征。
查看/var/log目录下,先前并不存在的test.log文件已经有了。
用vi打开该日志文件,记录如下:
最后需要关闭此守护进程。关闭的方法是通过ps -ef命令查询到该进程的进程号,之后再用kill 命令将其杀死。
注意:使用syslog函数前需要配置。但需要注意的是,在Centos6.x系统中,系统日志的配置文件已经发生了变化。不再是原来的/etc/syslog.conf了,而是/etc/rsyslog.conf。打开上述文件,在文件末尾加入下面一行:
user.* /var/log/test.log
然后重启syslog服务。重启的命令也修改为:/etc/init.d/rsyslog restart
实际上,Linux提供了完成上述同样功能的库函数:
#include <unistd.h>
int daemon(int nochdir,int noclose);
其中,nochdir参数用于指定是否改变工作目录,如果给它传递0,则工作目录将被设置为“/”(根目录),否则继续使用当前工作目录。noclose参数为0时,标准输入、标准输出和标准错误输出都被重定向到/dev/null文件,否则依然使用原来的设备。该函数成功时返回0,失败返回-1,并设置errno。
相关文章推荐
- linux系统编程之进程(八):守护进程详解及创建,daemon()使用
- linux系统编程之进程(八):守护进程详解及创建,daemon()使用
- linux系统编程之进程(八):守护进程详解及创建,daemon()使用
- linux系统编程之进程(八):守护进程详解及创建,daemon()使用
- linux系统编程之进程(八):守护进程详解及创建,daemon()使用
- [Linux]C语言Linux系统编程创建进程
- linux下创建守护进程(daemon process)代码-详细注释
- 在创建守护进程时优先选用系统调用daemon()
- Linux C创建守护进程(daemon)及终端相关概念
- [收藏] Linux中系统服务/守护进程 (daemon) 的详细说明
- [收藏] Linux中系统服务/守护进程 (daemon) 的详细说明
- 【Linux编程】守护进程(daemon)详解与创建
- linux 守护进程(daemon)的创建方法
- Linux中系统服务/守护进程 (daemon) 的详细说明
- linux守护进程详解及创建,daemon()使用
- [linux] C语言Linux系统编程-做成守护进程
- 【Linux】守护进程(daemon)创建及详解
- Linux中系统服务/守护进程 (daemon) 的详细说明
- linux下创建守护进程(daemon process)
- linux下创建守护进程(daemon process)