守护进程(daemon)是在后台运行且不与任何控制终端关联的进程。
启动守护进程的方法
1)在系统启动阶段,许多守护进程由系统初始化脚本启动,这些脚本通常位于/etc/目录或者以/etc/rc开头的某个
目录汇总。有若干个网络服务器通常从这些脚本启动:inetd超级服务器
2)许多网络服务器由inetd超级服务器启动。inetd自身由一个脚本启动。inetd监听网络请求(FTP,telnet等)每当
有一个请求达到时,启动相应的实际服务器(FTP服务器,telnet服务器)
3)cron守护进程按照规则定期执行一些程序,而由它启动执行的程序同样作为守护进程运行。cron自身由
第一条启动方法中的某个脚本启动
4)at命令一欧诺个鱼指定将来某个时刻的程序执行。这些程序的执行时刻到来时,通常由cron守护进程启动
执行他们,因此这些程序同样作为守护进程运行。
5)守护进程还可以从用户终端或者再前台或在后台启动。这么做往往是为了测试守护程序或重启因某种原因
而终止了的某个守护进程
syslogd守护进程
unix系统中的syslogd守护进程通常由某个系统初始化脚本启动,而且在系统工作期间一直运行。执行步骤如下
1)读取配置文件,通常是/etc/syslog.conf
2)创建一个unix域数据报套接字,给他捆绑的路径是/var/run/log,有些系统是/dev/log
3)创建一个UDP套接字,捆绑到514端口,syslog服务使用的端口
4)打开路径名/dev/klog,来自内核中的任何出错消息都输入到这里
//syslog函数 #include <syslog.h> void syslog(int priority, const char *message, ...);
本函数中的priority参数是级别(level)和设施(facility)两者的组合
openlog的facility参数
facility | 说明 |
LOG_AUDIT | 审计设施 |
LOG_AUTH | 授权程序login,su,getty等 |
LOG_AUTHPRIV | 与LOG_AUTH相同,但写日志文件时 具有权限限制 |
LOG_CONCOLE | 将消息写入/dev/console |
LOG_CRON | cron和at |
LOG_DAEMON | 系统守护进程inetd,routed等 |
LOG_FTP | FTP守护进程ftpd |
LOG_KERN | 内核产生消息 |
LOG_LOCAL0 | 保留由本地使用 |
LOG_LOCAL1 | 保留由本地使用 |
LOG_LOCAL2 | 保留由本地使用 |
LOG_LOCAL3 | 保留由本地使用 |
LOG_LOCAL4 | 保留由本地使用 |
LOG_LOCAL5 | 保留由本地使用 |
LOG_LOCAL6 | 保留由本地使用 |
LOG_LOCAL7 | 保留由本地使用 |
LOG_LPR | 行式打印机系统lpd,lpc等 |
LOG_MAIL | 邮件系统 |
LOG_NEWS | Usenet网络新闻系统 |
LOG_NTP | 网络时间协议系统 |
LOG_SECURITY | 安全子系统 |
LOG_SYSLOG | syslogd收紧进程本身 |
LOG_USER | 来自掐用户进程的消息(默认) |
LOG_UUCP | UUCP系统 |
syslog中的level(按序排列)
level | 说明 |
LOG_EMERG | 紧急(系统不可使用)(最高优先级) |
LOG_ALERT | 必须立即修复的情况 |
LOG_CRIT | 严重情况(如硬件设备处错) |
LOG_ERR | 出错情况 |
LOG_WARNING | 警告情况 |
LOG_NOTICE | 正常但重要的情况 |
LOG_INFO | 信息性消息 |
LOG_DEBUG | 调试消息(最低优先级) |
//当程序执行失败时,执行下列程序 syslog(LOG_INFO|LOG_LOCAL2, "execute failure");
/etc/syslog.conf配置类似如下
kern.* /dev/console local7.debug /var/log/cisco.log 所有内核的消息都输出到控制台 所有local7的debug几倍消息都输出到 cisco.log文件中
//进程也可以调用下面两个函数 //openlog可以在首次调用syslog前调用 //closelog可以再应用进程不再需要发送日志消息时调用 #include <syslog.h> void openlog(const char *ident, int options, int facility); void closelog(void);
syslog的 openlog函数的option参数
option | 说明 |
LOG_CONS | 若日志消息不能通过UNXI域数据报发送至syslogd,则将消息写至控制台 |
LOG_NEDLAY | 立即打开至syslogd守护进程的UNIX域数据报套接字,不要等到第一条消息已经被记录时 再打开。通常在记录第一条消息之前,不打开该套接字 |
LOG_NOWAIT | 不要等待在将消息记入日志过程中可能已创建的子进程。因为再syslog调用wait时,应用 程序可能已获得了子进程的状态,这种处理阻止了与捕捉SIGCHLD信号的应用程序之间 产生的冲突 |
LOG_ODELAY | 在第一条消息被记录之前延迟打开至syslogd守护进程的连接 |
LOG_PERROR | 除将日志消息发送给syslogd外,还将它写至标准出错(在Solaris上不可用) |
LOG_PID | 记录每条消息都要包含进程ID,此选项可供对每个不同的请求都fork一个子进程的守护 进程使用(与从不调用fork的守护进程相比较,如syslogd) |
inetd守护进程
典型的unix系统可能存在许多服务器,他们只是等待客户请求的达到,如FTP,telnet等。所有这些服务都有一个进程与之关联。这些进程都是从/etc/rc文件中启动。而且每个进程执行几乎相同的启动任务:创建一个套接字,把本服务器的众所周知端口捆绑到该套接字,等待一个连接。
这个模型存在两个问题
1)所有这些守护进程含有几乎相同的启动代码,既表现在创建套接字上,也表现在演变成守护进程上
2)每个守护进程再进程表中占据一个表项,然后他们大部分时间处于睡眠状态
使用一个特殊的inetd超级服务器解决上述问题
1)通过由inetd处理普通守护进程的大部分启动细节以简化守护进程的编写。
2)单个进程(inetd)就能为多个服务等待外来的客户请求,以此取代每个服务一个进程的做法,这么做减少了
系统中的进程总数
/etc/xinetd.d 目录下配置文件各字段解释
字段 | 说明 |
service-name | 必须在/etc/services文件中定义 |
socket-type | stream(对于TCP)或者dgram(对于UDP) |
protocol | 必须在/etc/protocols文件中定义 |
wait-flag | 对于TCP一般为nowait,对于UDP是wait |
login-name | 来自/etc/passwd的用户名,一般为root |
server-program | 调用exec指定的完整路径名 |
server-program-arguments | 调用exec指定的命令行参数 |
inetd的工作流程
1)在启动阶段,读取/etc/xinetd.d 目录下的文件并为每个服务创建一个适当类型的套接字
2)为每个端口调用bind,指定捆绑相应服务器的总所周知端口和统配地址,这个TCP或者UDP端口号通告
getserverbyname获得
3)对于每个TCP套接字,调用listen以接受外来的连接请求
4)创建完所有套接字后,调用select等待其中任何一个套接字变为可读。inetd大部分时间都阻塞在select调用上
5)当select返回指出魔木格套接字可读之后,如果该套接字是一个TCP套接字,而且其服务器的wait-flag值为
nowait那就调用accept接受这个新连接
6)inetd守护进程调用fork派生进程,并由子进程处理服务请求,这一点类似标志的并发服务器
7)如果第五部中select返回的是是一个字节流套接字,那么父进程必须关闭已连套接字。父进程再次调用select
等待下一个变为可读的套接字
参考
UNP Chapter 12 - 守护进程和inetd超级服务器