问题:在unix中,什么是守护历程?
答复:
守护历程在Linux/Unix系统中有着普遍的利用。有时,开发人员也想把本身的法式酿成守护历程。在创建一个守护历程的时候,要接触到子历程、历程组、会面期、信号机造、文件、目次和掌握末端等多个概念。
因而守护历程仍是比力复杂的,在那里详尽地讨论Linux/Unix的守护历程的编写,总结出八条体味,并给出利用规范。
编程要点
1。屏障一些有关掌握末端操做的信号。避免在守护历程没有一般运转起来时,掌握末端遭到骚乱退出或挂起。
示例如下:
signal(SIGTTOU,SIG_IGN);
signal(SIGTTIN,SIG_IGN);
signal(SIGTSTP,SIG_IGN);
signal(SIGHUP ,SIG_IGN);
所有的信号都有本身的名字。
那些名字都以“SIG”开头,只是后面有所差别。开发人员能够通过那些名字领会到系统中发作了什么事。当信号呈现时,开发人员能够要求系统停止以下三种操做:
◆ 漠视信号。大大都信号都是摘取那种体例停止处置的,那里就摘用了那种用法。但值得重视的是对SIGKILL和SIGSTOP信号不克不及做漠视处置。
◆ 捕获信号。最常见的情状就是,假设捕获到SIGCHID信号,则表达子历程已经末行。然后可在此信号的捕获函数中挪用waitpid()函数获得该子历程的历程ID和它的末行形态。别的,假设历程创建了暂时文件,那么就要为历程末行信号SIGTERM编写一个信号捕获函数来肃清那些暂时文件。
◆ 施行系统的默认动做。对绝大大都信号而言,系统的默认动做都是末行该历程。
对那些有关末端的信号,一般摘用漠视处置,从而保障了末端免受骚乱。
那类信号别离是,SIGTTOU(表达后台历程写掌握末端)、SIGTTIN(表达后台历程读掌握末端)、SIGTSTP(表达末端挂起)和SIGHUP(历程组长退出时向所有会议成员发出的)。
2。将法式进进后台施行。因为守护历程最末离开掌握末端,到后台往运行。办法是在历程中挪用fork使父历程末行,让Daemon在子历程中后台施行。那就是常说的“脱壳”。子历程陆续函数fork()的定义如下:
#include
#include
pid_t fork(void);
该函数是Linux/Unix编程中十分重要的函数。
它被挪用一次,但返回两次。那两次返回的区别是子历程的返回值为“0”,而父历程的返回值为子历程的ID。假设出错则返回“-1”。
3。离开掌握末端、登录会话和历程组。开发人员假设要脱节它们,不受它们的影响,一般利用 setsid() 设置新会话的领头历程,并与本来的登录会话和历程组离开。
那只是此中的一种办法,也有如下处置的办法:
if ((fd = open("/dev/tty",O_RDWR)) = 0) {
ioctl(fd,TIOCNOTTY,NULL);
close(fd);
此中/dev/tty是一个流设备,也是末端映射,挪用close()函数将末端封闭。
4。制止历程从头翻开掌握末端。历程已经成为无末端的会话组长,但它能够从头申请翻开一个掌握末端。开发人员能够通过不再让历程成为会话组长的体例来制止历程从头翻开掌握末端,需要再次挪用fork函数。
上面的法式代码表达完毕第一子历程,第二子历程陆续(第二子历程不再是会话组长)。
5。 封闭翻开的文件描述符,并重定向原则输进、原则输出和原则错误输出的文件描述符。历程从创建它的父历程那里继续了翻开的文件描述符。假设不封闭,将会浪费系统资本,引起无法意料的错误。封闭三者的代码如下:
for (fd = 0, fdtablesize = getdtablesize();
fd 0)
8。
在Linux/Unix下有个syslogd的守护历程,向用户供给了syslog()系统挪用。任何法式都能够通过syslog笔录事务。
因为syslog十分好用和易设置装备摆设,所以良多法式都利用syslog来发送它们的笔录信息。一般守护历程也利用syslog向系统输出信息。
syslog有三个函数,一般只需要用syslog(。。。)函数,openlog()/closelog()无关紧要。syslog()在shslog。h定义如下:
#include
void syslog(int priority,char *format,。
此中参数priority指了然历程要写进信息的品级和用处。第二个参数是一个格局串,指定了笔录输出的格局。在那个串的最初需要指定一个%m,对应errno错误码。
利用规范
下面给出Linux下编程的守护历程的利用规范,在UNIX中,差别版本实现的细节可能纷歧致,但其实现的原则是与Linux一致的。
#include
#include
#include
main(int argc,char **argv)
time_t now;
int childpid,fd,fdtablesize;
int error,in,out;
/* 漠视末端 I/O信号,STOP信号 */
signal(SIGTTOU,SIG_IGN);
signal(SIGTTIN,SIG_IGN);
signal(SIGTSTP,SIG_IGN);
signal(SIGHUP ,SIG_IGN);
/* 父历程退出,法式进进后台运行 */
if(fork()!=0) exit(1);
if(setsid() 0下编译通过。那个法式比力简单,但根本表现了守护历程的编程要点。读者针对现实利用中差别的需要,还能够做响应的调整。