守护进程

大多数守护进程都是以超级用户特权运行,没有一个守护进程具有控制终端,其终端名为问号(?),终端进程组ID设置为-1,没有一个守护进程具有控制终端,其终端名设置为问号(?),终端前台进程组ID设置为-1,内核守护进程以无控制终端的方式启动。用户层守护进程缺少控制终端可能是守护进程调用了setsid的结果,所有用户守护进程都是进程组的组长进程,以及会话进程的首进程,而且是这些进程组和会话中的唯一进程,最后,应当引起注意的是大多数守护进程的父进程是init进程。

 

 

 

守护进程编写规则:

首先要做的是调用umask将文件模式创建屏蔽字设置为0;

然后调用fork,并使父进程退出;

 

然后调用setsid创建一个新会话;并使调用进程完成以下三件事:称为新会话的首进程,成为一个新进程组的组长进程;没有控制终端

 

然后将当前工作目录更改为根目录,从父进程处继承过来的当前工作目录可能在一个装配文件系统中,因为守护进程通常在系统再引导之前是一直存在,所以如果守护进程的当前工作目录在一个装配文件系统中,那么该文件系统就不能再被拆卸,这与装配文件系统的原意不相符。

另外,某些守护进程可能会把当前工作目录更改到指定位置,在那里做它们的工作,例如,行式打印机假脱机守护进程常常将其工作目录更改到它们的spool目录下。

然后关闭不再需要的文件描述符,这使守护进程不再持有从其父进程继承来的某些文件描述符,可能会用到open_max函数或getrlimit函数,来判定最高文件描述符,并关闭直到该值的所有描述符。

 

 

最后,

某些守护进程打开/dev/null使其具有文件描述符0,1,2.这样,任何一个试图读标准输入,写标准输出或标准出错的库例程都不会产生任何效果,因为守护进程并不与终端设备相关联,所以不能在终端设备上显示其输出,也无处从交互式用户那里接收输入,即使守护进程是从交互式会话启动的,但因为守护进程是在后台运行的,所以登录会话的终止并不影响守护进程。如果其他用户在同一终端设备上登录,我们也不会在该终端上见到守护进程的输出,用户也不可期望他们在终端上的输入会有守护进程读取。

 

出错记录

与守护进程有关的一个问题是如何处理出错消息,因为它没有控制终端,所以不能只是简单地写到标准出错上,在很多工作站上,控制台设备运行一个窗口系统,所以我们不希望所有的守护进程都写到控制台设备上。我们也不希望每个守护进程将它自己的出错消息写到一个单独的文件中,对于系统管理人员而言,如果要关系哪一个守护进程写到哪一个记录文件中,并定期地检查这些文件,那么一定会使他感到头痛。所以,需要有一个集中的守护进程出错记录设施。

 

有三种方法产生日志消息:

内核例程可以调用log函数,任何一个用户进程通过打开(open)然后读(read)/dev/klog设备就可以读取这些消息,因为我们无意编写内核例程,所以不再进一步说明此函数;

(2)大多数用户进程(守护进程)调用syslog(3)函数以产生日志消息,我们将在下面说明其调用序列,这使消息发送只UNIX域数据报套接字/dev/log

该设施的接口是syslog函数

 

#include<syslog.h>

 

void openlog(const char *ident,int option,int facility);

 

void syslog(int priority,const char *format,....)

 

调用syslog产生一个日志消息,其priority参数是facility和level的组合,

format参数以及其他参数传至vsprintf函数以便进行格式化,在format参数中,每个%m都先被代换成对于errno值的出错消息字符串。(strerror)

 

setlogmask函数用于设置进程的记录优先级屏蔽字,它返回调用它之前的屏蔽字,当设置记录优先级屏蔽字时,除非消息的优先级已在记录优先级屏蔽字中设置,否则消息不被记录,

 

 

void closelog(void);

 

int setlogmask(int maskpri);

 

ps:调用openlog是可选择的,如果不调用openlog,则在第一次调用syslog时,自动调用openlog,调用closelog也是可选择的,它只是关闭曾被用于与syslogd守护进程通信的描述符。

调用openlog使我们可以指定一个ident,将它加至每则日志消息中,ident一般是程序的名称,(例如,cron、inetd等)。option参数是指定许多选项的位屏蔽。

 

 

openlog的参数facility可以选取表13-2中所列举的值,设置facility参数的目的是可以让配置文件说明,来自不同设施的消息将一不同的方式进行处理,如果不调用openlog,或者以facility为0来调用它,那么在调用syslog时,可将设施作为priority参数的参数的一部分进行说明。

 

(3)在此主机上的一个用户进程,或通过TCP|IP网络连接到此主机的其他主机上的一个用户进程可以将日志消息发送到UDP端口514,注意,syslog函数并不产生这些UDP数据报,而是要求产生此日志消息的进程进行显示的网络编程。

 

 

 

通常,syslogd守护进程读取这三种格式的日志消息,此守护进程在启动时读一个配置文件,一般其文件名为/etc/syslog.conf,该文件决定了不同种类的消息应送向何处,例如,紧急消息可被送向系统管理员,并在控制台上显示,而警告消息则可记录到一个文件中。

 

 

 

 

 下一节:单实例守护进程

 

 为了正常运行,某些守护进程实现为单实例,也就是在任一时刻只运行该守护进程的一个副本,例如,该守护进程可能需要排他地访问一个设备,在cron守护进程情况下,如果有多个实例运行,那么每个副本都可能试图开始某个预定的操作,于是造成该操作的重复执行,这很可能导致出错。

如果守护进程需要访问一个设备,而该设备驱动程序将阻止多次打开/dev目录下的相应设备节点,那么这就达到了任何时刻只运行一份副本的要求,但是如果没有这种设备可供使用,那么我们就需要自行处理。

 

文件锁和记录锁机制是一种方法的基础。该方法用来保证一个守护进程只有一个副本在运行,如果守护进程创建一个文件,并且在整个文件上加了一把写锁,那就只允许创建一把这样的写锁,所以在此之后如果试图再创建一把这样的写锁就会失败,以此向后续守护进程副本指明已有一个副本在运行。

 

文件和记录锁提供了一种方便的互斥机制,如果守护进程在整个文件上得到一把写锁,那么该守护进程终止时,这把锁将自行删除,这就简化了复原所需的处理,去除了以前的守护进程示例需要进行清理的有关操作。

 

 

 

守护进程的惯例

 

在unix系统中,守护进程遵循下列公共惯例:

若守护进程使用锁文件,那么该文件通常存放在/var/run目录下,注意,守护进程可能需具有超级用户权限才能在此目录下创建文件,锁文件的名字通常是name.pid。其中,name可能是该守护进程或服务的名字,例如cron守护进程锁文件的名字是/var/run/cron.pid

 

若守护进程支持配置选项,那么配置文件通常存放在/etc目录下。配置文件的名字通常是name.conf。其中,name是该守护进程或服务的名字,例如,syslogd守护进程的配置文件是/etc/syslog.conf。

 

守护进程可用命令行启动,但通常他们是由系统初始化脚本之一,(/etc/rc*)或(/etc/init,d/*)启动,如果守护进程终止,应当自动地重新启动它,则我们可以在/etc/initab中为该守护进程包含_respawn记录项,这样,init就将重启动该守护进程。

 

若一守护进程一配置文件,那么当该守护进程启动时,它读该文件,但在此之后一般就不会再查看它,若一管理员更改了配置文件,那么该守护进程可能需要被停止,然后再启动,以使配置文件的更改生效,为避免此种麻烦,某些守护进程将捕捉SIGHUP信号,当他们接受到这种信号时,会重读配置文件。因为守护进程不与终端相结合,他们或者是无控制终端的会话首进程,或者是孤儿进程组的成员,所以守护进程并不期望接收sighup。他们可以安全地重复使用它。

 

 

 

 

ps:补充

进程调用setsid函数建立一个新会话

 

#include<unistd.h>

 

pid_t  setsid(void)

 

调用此函数的进程不是一个进程组的组长,则此函数就会创建一个新会话,结果将发生下列3件事

(1):该进程变成新会话首进程,(会话首进程是创建该会话的进程),此时,该进程是会话的唯一进程;

(2):该进程成为一个新进程组的组长进程,新进程组ID是调用进程的进程ID;

(3):该进程没有控制终端,(下一节将会讨论控制终端):如果调用setsid之前该进程有一个控制终端,那么这种联系也会被终端。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值