Linux网络编程第八单元守护进程和inetd超级服务器2第八单元守护进程和inetd超级服务器•8.1守护进程•8.2inetd的工作原理守护进程概述•守护进程是在后台运行不受终端控制的进程(如输入、输出等),一般的网络服务都是以守护进程的方式运行。守护进程查看•ps–axj命令•以超级用户启动的(UID为0);•没有控制终端(TTY为?);•终端进程组ID为-1(TPGID表示终端进程组ID,该值表示与控制终端相关的前台进程组,如果未和任何终端相关,其值为-1;•父进程都为init进程(PID为1的进程)。守护进程与后台进程的区别•后台运行程序:即加&启动的程序•后台运行的程序拥有控制终端,守护进程没有。•守护进程没有控制终端的原因–在某终端启动守护进程后,该终端可能要执行其他任务,或者其他用户登录该终端,这样守护进程的信息就不应该出现在终端。–终端上按键产生的一些信号如ctrl+c产生SIGINT信号,不应该对以前终端上启动的守护进程造成影响。启动守护进程的方法•1引导系统时从启动脚本/etc/rc.d中启动。–如inet超级服务器,web服务器等•2由inet超级服务器启动的–如Telnetd、FTP等•3由crond守护进程(周期性)启动。•4at命令(一次性)启动。•5手工从用户终端启动。–这是测试守护进程或重新启动守护进程常用的方法78.1守护进程•8.1.1syslogd守护进程•8.1.2创建守护进程syslogd守护进程•由于守护进程没有控制终端,在发生问题时它要用一些其它方式以输出消息。–可以通过向文件里写数据来输出消息,但这样不好管理,因为每一个守护进程要对应一个文件。•syslogd守护进程作用–接收系统或用户守护进程的输出消息,并根据配置信息作出相应处理。syslogd守护进程启动过程•1、读入配置文件–通常是/etc/syslogd.conf,设定syslogd对接收的各种登记消息如何处理。•2、创建一个Unix域套接字–捆绑路径名/var/run/log•3、创建一个udp套接字–捆绑端口514•4、打开设备/dev/klog–内核中的所有出错消息作为这个设备的输入出现;•5、运行一个无限循环–循环中调用select,等待234三步创建的三个描述符中的某一个变为可读,并按配置文件对消息进行处理。浅析/etc/syslogd.conf——1*.info;mail.none;news.none;authpriv.none;cron.none/var/log/messagesmail.*/var/log/maillogcron.*/var/log/cron*.emerg*10浅析/etc/syslogd.conf——2•syslogd.conf文件保存syslogd对消息的处理方式,每行由消息类型和处理方案组成。–消息类型•由消息来源和紧急程度构成,中间用点号连接。–处理方案:•存硬盘,或转发到另一机器,或显示在终端上。•处理方案一览:–文件名:写入某个文件,要注意绝对路径。–@主机名或IP:转发给另外一台主机的syslogd程序。–/dev/console:发送到本地机器屏幕上。–*:发送到所有用户的终端上。11如何利用syslogd守护进程•其他守护进程如何向syslogd发送消息呢?•方法一:–创建一个Unix域数据报套接口,并向syslogd守护进程绑定的路径名发送消息。•方法二:–创建一个UDP套接口,将日志消息发到127.0.0.1及端口号514;•方法三(最简单):–利用syslog函数,它将消息发往syslogd守护进程。12syslog函数#includesyslog.hvoidsyslog(intpriority,constchar*message,…);•参数–由于/etc/syslog.conf文件要根据消息的来源和紧急程度来判断该将消息发往何处,所以syslog函数需要指明这三方面信息。•消息:message与printf所用的格式化字符串类似,同时增加了%m,它将由对应的当前errno值的出错消息所取代;•来源和紧急程度:priority是“紧急程度|来源”的组合,这样对相同来源的消息就会得到同样的处理,或相同级别的消息得到同样的处理。如LOG_INFO|LOG_LOCAL2。•紧急程度和消息来源见后syslog-priority-level——紧急程度•级别自高至低排列–LOG_EMERG系统不可用–LOG_ALERT必须立即进行处理–LOG_CRIT危险情况–LOG_ERR错误情况–LOG_WARNING警告情况–LOG_NOTICE常见但值得注意的情况(默认)–LOG_INFO通告消息–LOG_DEBUG调试信息14syslog-priority-facility——消息来源–LOG_AUTH安全/授权消息–LOG_CRON时间守护进程(cronandat)–LOG_FTPftp守护进程–LOG_KERN内核消息–LOG_LOCAL0到LOG_LOCAL7本地使用–LOG_LPR行式打印机–LOG_MAIL邮件系统–LOG_NEWS网络新闻系统–LOG_SYSLOGsyslogd内部消息–LOG_USER任意的用户消息(默认)–LOG_UUCPUUCP消息15syslog函数举例•syslog0.c•若/etc/syslogd.conf配置文件中有以下行:local2.info/var/log/info.log则所有来源为local2的通知消息将添加到/var/log/info.log文件的末尾;•如果还有其他关于local2或info的规则,则都会执行。#includesyslog.h#includeunistd.hintmain(){syslog(LOG_INFO|LOG_LOCAL2,OK);}openlog和closelog——1•调用openlog是可选择的。–如果不调用openlog,则在第一次调用syslog时,自动调用openlog。•调用closelog也是可选择的–它只是关闭被用于与syslog守护进程通信的描述符。–进程退出前会自动关闭所有没有关闭的描述符。•调用openlog可以通过第一个参数指定一个ident,以后此ident将被加至每则记录消息中。ident一般是程序的名称,如cron等。17openlog和closelog——2voidopenlog(constchar*ident,intoption,intfacility);voidcloselog(void);•参数:–ident:一个字符串,它将被加到每条登记消息前面;–option:由以下值组合而成。•LOG_CONS若不能发往syslogd,则登记到控制台上•LOG_NDELAY不延迟打开,立即创建套接口•LOG_PERROR既发往syslogd,又登记到标准错误输出•LOG_PID登记每条消息的进程ID–facility:如果以后的syslog函数没有设置消息来源,则使用这个参数作为缺省值。一个简单例子•/home/linuxnet/8/syslog.c,教材P117•执行后OK字符串输出到哪里了呢?•根据/etc/syslog.conf文件L7说明*.info/var/log/messages•OK进入了/var/log/messages文件。•如果想指定OK进入自定义的文件呢?–在/etc/syslog.conf中增加一行,如–local2.info[中间是tab]/var/log/test.log–然后运行/etc/init.d/syslogrestart–重新执行程序,也可以在/var/log/test.log中看到OKtest.log文件中的数据218.1守护进程•8.1.1syslogd守护进程•8.1.2创建守护进程setsid()函数#includesys/types.h#includeunistd.hpid_tsetsid(void);返回值:若成功则为进程组ID,出错则为-1•如果调用进程不是一个进程组的组长,则此函数创建一个新的会话:–此进程变成该会话的首进程,同时是该会话的唯一进程;–此进程成为一个新进程组的组长进程。新进程组ID是此调用进程的进程ID;–此进程没有控制终端,如果在调用setsid之前此进程有一个控制终端,那么这种联系也被解除。•如果调用进程已经是一个进程组长,则函数出错。23创建守护进程的过程1•1.调用fork创建子进程。–父进程终止,让子进程在后台继续执行。•2.子进程调用setsid产生新会话期并失去控制终端–调用setsid()使子进程进程成为新会话组长和新的进程组长,同时失去控制终端。•3.忽略SIGHUP信号。–会话组长进程终止会向其他进程发该信号,造成其他进程终止。•4.调用fork再创建子进程。–子进程终止,子子进程继续执行,由于子子进程不再是会话组长,从而禁止进程重新打开控制终端。24创建守护进程的过程2•5.改变当前工作目录为根目录–一般将工作目录改变到根目录,这样进程的启动目录也可以被卸掉。•6.关闭打开的文件描述符,打开一个空设备,并复制到标准输出和标准错误上。–避免调用的一些库函数依然向屏幕输出信息。•7.重设文件创建掩码–清除从父进程那里继承来的文件创建掩码,设为0。•8.用openlog函数建立与syslogd的连接。daemon典型代码.c守护进程时间服务器与客户端•/etc/home/linuxnet/8–守护进程时间服务器daemons.cP119-120–客户端daemonc.cP121–makefile•编译–make•运行:–先运行服务器,再在另一个终端运行客户端•结果:–服务器运行后自动成为守护进程,返回shell–客户端运行后收到服务器发来的当前时间25all:daemonsdaemoncdaemons:daemons.cgcc$^-o$@daemonc:daemonc.cgcc$^-o$@clean:rm–fdaemonsdaemonc编写守护进程的注意事项•当程序开始时,尽快调用daemon_init,使之变成守护进程,否则容易受控制终端影响;•守护进程必须避免调用printf和fprintf函数,而调用syslog函数。27第八单元守护进程和inetd超级服务器•8.1守护进程•8.2inetd的工作原理inetd的引入•UNIX/Linux系统中一般都有很多网络服务器的守护进程在运行。–每个网络服务器的守护进程运行过程几乎相同•创建套接字,绑定地址,监听端口等–正常情况下这些进程全都运行起来将占用进程表中的很多项,但是大多数时间这些进程会处于睡眠状态。•为了节约系统资源(进程表,内存等),相同的工作可以通过一个特殊的守护进程来完成,即inetd——超级服务器。28inetd基本工作过程•inetd进程自己先变成一个守护进程。•读入配置文件/etc/inetd.conf,指明inetd支持哪些服务,以及客户请求到来时该怎么做。•inetd对配置文件中的每个服务都完成socket-bind过程,如果是TCP套接字还要进行listen•然后调用select阻塞等待,如果有客户端请求,通过select函数可以判断是哪个服务器应答•然后(TCP套接字accept)fork,在子进程中进行处理并启动相应的服务器程序。29inetd工作流程图(TCP)socket()bind()listen()如果是tcp套接字select()等待可读条件accept()如果是tcp套接字fork()close已连接套接字(如果是tcp)close已连接套接字之外的所有描述字将套接字描述字dup到描述字0、1、2,然后close原来的套接字setgid()setuid()(如果不是root)exec()服务程序父进程子进程对每个在/etc/inetd.conf文件中列出的每个服务inetd作用•简化大多数服务器进程的启动过程,通过一个进程可以启动多个服务器。•避免多个进程都