Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1409006
  • 博文数量: 430
  • 博客积分: 9995
  • 博客等级: 中将
  • 技术积分: 4388
  • 用 户 组: 普通用户
  • 注册时间: 2006-05-24 18:04
文章存档

2013年(1)

2008年(2)

2007年(14)

2006年(413)

分类:

2006-07-14 09:24:50


第1 3章精灵进程


13.1 引言
精灵进程(d a e m o n)是生存期长的一种进程。它们常常在系统引导装入时起动,在系统
关闭时终止。因为它们没有控制终端,所以说它们是在后台运行的。U N I X系统有很多精灵进
程,它们执行日常事物活动。

本章说明精灵的进程结构,以及如何编写精灵进程程序,因为精灵没有控制终端,我们需
要了解在有关事物出问题时,精灵进程如何报告出错情况。

13.2 精灵进程的特征
先来察看一些常用的系统精灵进程,以及它们怎样和第9章中所叙述的概念:进程组、控
制终端和对话期相关联。p s ( 1 )命令打印系统中各个进程的状态。该命令有多个选择项,有关细
节请参考系统手册。为了察看本节讨论中所需的信息,在4 . 3 + B S D或SunOS 系统下执行:

ps -axj


选择项- a显示由其他用户所拥有的进程的状态。- x显示没有控制终端的进程的状态。- j显示与
作业有关的信息:对话期I D、进程组I D、控制终端以及终端进程组I D。在S V R 4之下,与此相
类似的命令是ps -efjc(在某些符合美国国防部安全性准则要求的U N I X系统中,只能使用ps 查
看自己所拥有的进程)。p s的输出大致是:

P P I D P I D P G I D S I D T T T P G I D U I D C O M M A N D


0 0 0 0? - 1 0 s w a p p e r


0 1 0 0 ? - 1 0 /sbin/init


0 2 0 0 ? - 1 0 p a g e d a e m o n


1 8 0 8 0 8 0 ? - 1 0 s y s l o g d


1 8 8 8 8 8 8 ? - 1 0 /usr/lib/sendmail -bd -qlh


1 1 0 5 3 7 3 7 ? - 1 0 u p d a t e


1 1 0 8 1 0 8 1 0 8 ? - 1 0 c r o n


1 1 1 4 1 1 4 1 1 4 ? - 1 0 i n e t d


1 1 1 7 1 1 7 1 1 7 ? - 1 0 / u s r / l i b / l p d


其中,已移去了一些我们并无兴趣的列,例如累计C P U时间。按照顺序,各列标题的意义是:
父进程I D、进程I D、进程组I D、终端名称、终端进程组I D(与该控制终端相关的前台进程组)、
用户I D以及实际命令字符串。

这些p s命令在支持对话期I D的系统(S u n O S)上运行,9 . 5节的s e t s i d函数中曾
提及对话期I D。它是对话期首进程的进程I D。但是,4 . 3 + B S D系统将打印与本进
程所属进程组对应的s e s s i o n结构的地址(见9 . 11 节)。

进程0、1以及2是8 . 2节中所述的进程。这些进程非常特殊,存在于系统的整个生命期中。
它们没有父进程I D,没有组进程I D,也没有对话期I D。s y s l o g d精灵进程可用于任何为操作人


第1 3章精灵进程3 1 3
下载
员记录系统消息的程序中。可以在一台实际的控制台上打印这些消息,也可将它们写到一个文
件中(1 3 . 4 . 2节将对s y s l o g设施进行说明)。s e n d m a i l是标准邮递精灵进程。u p d a t e程序定期将内
核缓存中的内容写到硬盘上(通常是每隔3 0秒)。为了做到这一点,该程序每隔3 0秒调用s y n c

(2)函数一次(4 . 2 4节已对s y n c进行了说明)。c r o n精灵进程在指定的日期和时间执行指定的命
令。许多系统管理任务是由c r o n定期地使相关程序执行而得以实现的。我们已在9 . 3节中提到
i n e t d精灵进程。它监听系统的网络界面,以输入对各种网络服务器的请求。最后一个精灵进程,
l p d处理对系统提出的各个打印请求。
注意,所有精灵进程都以超级用户(用户I D为0)的优先权运行。没有一个精灵进程具有
控制终端—终端名称设置为问号(?)、终端前台进程组I D设置为-1。缺少控制终端可能是
精灵进程调用了s e t s i d的结果。除u p d a t e以外的所有精灵进程都是进程组的首进程,对话期的首
进程,而且是这些进程组和对话期中的唯一进程。u p d a t e是它所在进程组(3 7)和对话期(3 7)
中的唯一进程,但是该进程组的首进程(可能也是该对话期的首进程)已经终止。最后,应当
引起注意的是所有这些精灵进程的父进程都是i n i t进程。

13.3 编程规则
在编写精灵进程程序时需遵循一些基本规则,以便防止产生并不希望的交互作用。下面先
说明这些规则,然后是一个按照规则编写的函数d a e m o n _ i n i t。

(1) 首先做的是调用f o r k,然后使父进程e x i t。这样做实现了下面几点:第一,如果该精灵
进程是由一条简单s h e l l命令起动的,那么使父进程终止使得s h e l l认为这条命令已经执行完成。
第二,子进程继承了父进程的进程组I D,但具有一个新的进程I D,这就保证了子进程不是一个
进程组的首进程。这对于下面就要做的s e t s i d调用是必要的前提条件。
(2) 调用s e t s i d以创建一个新对话期。于是执行9 . 5节中列举的三个操作,使调用进程:(a)
成为新对话期的首进程,(b)成为一个新进程组的首进程,(c)没有控制终端。
在S V R之下,有些人建议在此时再调用f o r k,并使父进程终止。第二个子进
程作为精灵进程继续运行。这样就保证了该精灵进程不是对话期首进程,于是按
照S V R 4规则(见9 . 6节)可以防止它取得控制终端。另一方面,为了避免取得控
制终端,无论何时打开一个中断设备都要指定O _ N O C T T Y。

(3) 将当前工作目录更改为根目录。从父进程继承过来的当前工作目录可能在一个装配的
文件系统中。因为精灵进程通常在系统再引导之前是一直存在的,所以如果精灵进程的当前工
作目录在一个装配文件系统中,那么该文件系统就不能被拆卸。
另外,某些精灵进程可能会把当前工作目录更改到某个指定位置,在此位置做它们的工作。
例如,行式打印机假脱机精灵进程常常将其工作目录更改到它们的s p o o l目录上。

(4) 将文件方式创建屏蔽字设置为0。由继承得来的文件方式创建屏蔽字可能会拒绝设置某
些许可权。例如,若精灵进程要创建一个组可读、写的文件,而继承的文件方式创建屏蔽字,
屏蔽了这两种许可权,则所要求的组可读、写就不能起作用。
(5) 关闭不再需要的文件描述符。这样使精灵进程就不再持有从其父进程继承来的某些文
件描述符(父进程可能是s h e l l进程,或某个其他进程)。但是,究竟关闭哪些描述符则与具体
的精灵进程有关,所以在下面的例子中不包含此步骤。可以使用程序2 - 3中的o p e n _ m a x函数来
决定最高文件描述符值,并关闭直到该值的所有描述符。

3 1 4 U N I X环境高级编程
下载
实例

程序1 3 - 1是个函数,可由想初始化成为一个精灵进程的程序调用。

程序13-1 初始化一个精灵进程


若d a e m o n _ i n i t函数由m a i n函数调用,然后进入睡眠状态,那么可以用p s命令检查该精灵进程的

状态:
$ a . o u t
$ p s _ a x j
P P I D P I D
1 7 3 5
P G I D
7 3 5
S I D
7 3 5
T T
?
T P G I D
- 1
U I D
2 2 4
C O M M A N D
a . o u t
从中可以看到,该精灵进程已被正确地初始化。
13.4 出错记录

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

伯克利开发了BSD syslog 设施,并广泛应用于4 . 2 B S D。从4 . x B S D导出的很多
系统都支持s y s l o g。1 3 . 4 . 2节将说明该设施。

系统V中从来没有一个集中的精灵进程记录设施。S V R 4支持B S D风格的
s y s l o g设施,S V R 4之下的i n e t d精灵进程使用s y s l o g。在S V R中,s y s l o g的基础是
/ d e v / l o g流设备驱动程序,下一节将对此进行说明。


第1 3章精灵进程3 1 5
下载
13.4.1 SVR4流l o g驱动程序
S V R 4提供了一种流设备驱动程序,其界面具有流出错记录,流事件跟踪以及控制台记录
功能。有关文献包含在〔AT&T 1990d〕的log(7) 中。图1 3 - 1详细给出了这种设施的整个结构。


文件、控制台
s t d o u t 或e - m a i l

出错跟踪控制台用户用户
记录记录记录进程进程

l o g流设备流模块
驱动程序或设备

内核

图13-1 SVR4 log 设施

有三个记录进程(l o g g e r):出错记录进程、跟踪记录进程以及控制台记录进程。每一条记录消
息可以送给其中之一。
下面介绍三种产生记录消息的方法以及三种读记录消息的方法。

. 产生记录消息。
(1) 内核中的例程可以调用s t r l o g以产生记录消息。这种方法通常由流模块和流设备驱动程
序用于出错消息或跟踪消息(跟踪消息常用在新的流模块或驱动程序的排错中)。因为我们无
意编写内核中的例程,所以不详细说明这种消息产生方法。
(2) 一个用户进程(例如一个精灵进程)可以用p u t m s g将消息送到/ d e v / l o g。这种消息可被
送到三个记录进程中的任意一个。
(3) 一个用户进程(例如一个精灵进程)可以用w r i t e将消息写到/ d e v / c o n s l o g。这种消息只
能送向控制台记录进程。
. 读记录消息。
(4) 标准的出错记录进程是s t r e r r(1 M)。它将记录消息增写到在目录/ v a r / a d m / s t r e a m下的一
个文件中。该文件名是e r r o r.m m - d d,其中,m m是月份,d d是天数。s t r e r r本身是个精灵进程,
通常在后台运行,它将记录消息增写到该文件中。
(5) 标准的跟踪记录进程是s t r a c e ( 1 M )。它能有选择地将一套指定的跟踪消息写至其标准输出。
(6) 标准控制台记录进程是s y s l o g d,这是一个B S D导出程序,下一节将对此进行叙述。此
进程是个精灵进程,它读一个配置文件,然后将记录消息写至一个指定的文件(控制台是一个

3 1 6 U N I X环境高级编程
下载
文件)或登录用户,或将该消息发送给在另一台主机上的s y s l o g精灵进程。
虽然上面没有提及,但用户也可以用自己的进程替换任意一个系统提供的标准精灵进程。我们
可以提供自己的出错记录进程、跟踪记录进程或控制台记录进程。

每则l o g消息除消息本身外,还包含有一些其他信息。例如,由l o g驱动程序沿逆流方向发
送的消息,还包含有下列消息:哪个模块产生此消息(如果该消息是由内核中的一个流模块产
生的)、级别、优先级、某些标志以及消息产生的时间。有关细节请参阅手册中的l o g(7)。如
果使用p u t m s g产生一则l o g消息,则可以设置这些字段中的几个。如果调用w r i t e将一则消息发
送至控制台记录进程(通过/ d e v / c o n s l o g),则只能发送消息字符串。

图1 3 - 1中没有显示的另一种可能性是:由一个S V R 4精灵进程调用BSD syslog(3)函数。
用这种方法可将消息发送至控制台记录进程,这与用p u t m s g向/ d e v / l o g发送消息类似。使用
s y s l o g,可以设置消息的优先权字段。下一节将讨论此函数。

当产生了某种类型的记录消息,但是相应类型的记录进程却不在运行时,l o g驱动程序丢
弃该消息。

不幸的是,在S V R 4中,使用这种l o g设施带有随意性。一些精灵进程使用它,
而大多数由系统提供的精灵进程则编写成直接写向控制台。
s y s l o g(3)函数和s y s l o g d ( 1 M )精灵进程的有关文档在B S D兼容库文档部分
〔AT&T 1990c〕,但是它们本身并不在此库中,而是在所有用户进程(精灵进程)
都可使用的标准C库中。

13.4.2 4.3+BSD syslog 设施
自4 . 2 B S D以来,广泛地应用了BSD syslog设施。大多数精灵进程使用这一设施。图1 3 - 2显
示了s y s l o g设施的详细组织结构。

文件、控制台
或e - m a i l

用户进程
因特网域
数据报套接口
U N I X域
数据报套接口
内核
内核例程
T C P / I P网络

图13-2 4.3+BSD syslog设施


第1 3章精灵进程3 1 7
下载
有三种方法产生记录消息:

(1) 内核例程可以调用l o g函数。任何一个用户进程通过打开和读/ d e v / k l o g设备就可以读取
这些消息。因为我们无意编写内核中的例程,所以不再进一步说明此函数。
(2) 大多数用户进程(精灵进程)调用s y s l o g(3)函数以产生记录消息。我们将在下面说
明其调用序列。这使消息发送至U N I X域数据报套接口/ d e v / l o g。
(3) 在此主机上,或通过T C P / I P网络连接到此主机的某一其他主机上的一个用户进程可将
记录消息发向U D P端口5 1 4。注意:s y s l o g函数并不产生这些U D P数据报——它们要求产生此
记录消息的进程具有显式的网络编程。
关于U N I X域套接口以及U D P套接口的细节,请参阅s t e v e n s〔1 9 9 0〕。

通常,s y s l o g d精灵进程读取三种格式的记录消息。此精灵进程在起动时读一个配置文件。
一般,其文件名为/ e t c / s y s l o g . c o n f,该文件决定了不同种类的消息应送向何处。例如,紧急消
息可被送向系统管理员(若已登录),并在控制台上显示,而警告消息则可记录到一个文件中。

该设施的界面是s y s l o g函数。

#include
void openlog(char *


i d e n t, int o p t i o n, int f a c i l i t y) ;
void syslog(intp r i o r i t y, char *f o r m a t, ...);
void closelog(void);

调用o p e n l o g是可选择的。如果不调用o p e n l o g,则在第一次调用s y s l o g时,自动调用

o p e n l o g。调用c l o s e l o g也是可选择的—它只是关闭被用于与s y s l o g d精灵进程通信的描述符。
调用o p e n l o g使我们可以指定一个i d e n t,以后,此i d e n t将被加至每则记录消息中。i d e n t一
般是程序的名称(例如,c r o n、i n e t d等)。表1 3 - 1说明了4种可能的o p t i o n。

表13-1 openlog的o p t i o n参数

o p t i o n 说明
L O G _ C O N S 若日志消息,不能通过U N I X域数据报发送至s y s l o g d,则将该消息写至控制台
L O G _ N D E L A Y 1 立即打开U N I X域数据报套接口至s y s l s g d精灵进程—不要等到记录第一条消息。
通常,在记录第一条消息之前,该套接口不打开
L O G _ P E R R O R 除将日志消息发送给s y s l o g外,还将它写至标准出错。此选项仅由4.3BSD Reno
及以后版本支持
L O G _ P I D 每条消息都包含进程I D此选择项可供对每个请求都f o r k一个子进程的精灵进程使用

o p e n l o g中的参数f a c i l i t y可以选取表1 3 - 2中列举的值。设置f a c i l i t y参数的目的是让配置文件
可以说明,来自不同设施的消息以不同的方式进行处理。如果不调用o p e n l o g,或者以f a c i l i t y为
0来调用它,那么在调用s y s l o g时,可将f a c i l i t y作为p r i o r i t y参数的一个部分进行说明。
调用s y s l o g产生一个记录消息。其p r i o r i t y参数是f a c i l i t y和l e v e l的组合,它们可选取的值分
别列于f a c i l i t y(见表1 3 - 2)和l e v e l(见表1 3 - 3)中。l e v e l值按优先级从最高到最低按序排列。

f o r m a t参数以及其他参数传至v s p r i n t f函数以便进行格式化。在f o r m a t中,每个% m都被代
换成对应于e r r n o值的出错消息字符串(s t r e r r o r)。

S V R 4和4 . 3 + B S D都提供l o g g e r ( 1 )程序,以其作为向s y s l o g设施发送出错消息的方法。送至
该程序的可选择参数可以指定f a c i l i t y、l e v e l以及i d e n t。l o g g e r的意图是用于以非交互方式运行,
又要产生记录消息的s h e l l过程。


3 1 8 U N I X环境高级编程
下载
表13-2 openlog的f a c i l i t y参数
f a c i l i t y 说明
L O G _ A U T H 授权程序: l o g i n . s u , g e t t y ,.
L O G _ C R O N c r o n和a t
L O G _ D A E M O N 系统精灵进程:f t p d , r o u t e d ,.
L O G _ K E R N 内核产生的消息
L O G _ L O C A L 0 保留由本地使用
L O G _ L O C A L 1 保留由本地使用
L O G _ L O C A L 2 保留由本地使用
L O G _ L O C A L 3 保留由本地使用
L O G _ L O C A L 4 保留由本地使用
L O G _ L O C A L 5 保留由本地使用
L O G _ L O C A L 6 保留由本地使用
L O G _ L O C A L 7 保留由本地使用
L O G _ L P R 行打系统:lpd, lpc,.
L O G _ M A I L 邮件系统
L O G _ N E W S U s e n e t网络新闻系统
L O G _ S Y S L O G s y s l o g d精灵进程本身
L O G _ U S E R 来自其他用户进程的消息
L O G _ U U C P U U C P系统
表13-3 syslog中的le v e l s(按序排列)
l e v e l 说明
L O G _ E M E R G 紧急(系统不可使用) (最高优先级)
L O G _ A L E R T 必须立即修复的条件
L O G _ C R I T 临界条件(例如,硬设备出错)
L O G _ E R R 出错条件
L O G _ W A R N I N G 警告条件
L O G _ N O T I C E 正常,但重要的条件
L O G _ I N F O 信息性消息
L O G _ D E B U G 调试排错消息(最低优先级)

l o g g e r命令的格式正由P O S I X . 2标准化。

实例

第1 7章的P o s t S c r i p t打印机精灵进程中,包含有下面的调用序列:

openlog("lprps", LOG_PID, LOG_LPR);
syslog(LOG_ERR, "open error for %s: %m", filename);


第一个调用将i d e n t字符串设置为程序名,指定打印该进程I D,并且将系统默认的f a c i l i t y设定为
行式打印机系统。对s y s l o g的实际调用指定一个出错条件和一个消息字符串。如若不调用

o p e n l o g,则第二个调用的形式可能是:
syslog(LOG_ERR | LOG_LPR, "open error for %s: %m", filename);


其中,将p r i o r i t y参数指定为l e v e l和f a c i l i t y的组合。


第1 3章精灵进程3 1 9
下载
13.5 客户机-服务器模型
精灵进程常常用作为服务器进程。确实,图1 3 - 2中,可以称s y s l o g d进程为服务器,用户进
程(客户机)用U N I X域数据报套接口向其发送消息。

一般而言,服务器是一个进程,它等待客户机与其联系,提出某种类型的服务要求。图1 3 - 2
中,由s y s l o g d服务器提供的服务是记录出错消息。

图1 3 - 2中,客户机和服务器之间的通信是单向的。客户机向服务器发送其服务要求,服务
器则不向客户机回送任何消息。在下面有关进程通信的几章中,有大量实例,其中有客户机和
服务器之间的双向通信。客户机向服务器发送要求,服务器则向客户机回送回答。

13.6 小结
在大多数U N I X系统中,精灵进程是一直运行的。为了初始化我们自己的精灵进程,需要
一些审慎的思索并理解第9章中说明过的进程之间的关系。本章开发了一个可由精灵进程调用,
对其自身正确地进行初始化的函数。

本章还讨论了精灵进程记录出错消息的几种方法,因为精灵进程通常没有控制终端。在
S V R 4下,可以使用流记录驱动程序,在4 . 3 + B S D之下,提供了s y s l o g设施。因为S V R 4也提供
BSD syslog设施,所以在下面的章节中,当精灵进程需要记录出错消息时,将调用s y s l o g函数。
第1 7章中,P o s t S c r i p t打印机精灵进程就包含有这种情况。

习题

1 3 . 1 从图1 3 - 2可以看出,直接调用o p e n l o g或第一次调用s y s l o g都可以初始化s y s l o g,此时
一定要打开用于U N I X域的数据报套接口的特殊设备文件/ d e v / l o g。如果调用o p e n l o g前,用户进
程(精灵进程)先调用了c h r o o t,结果如何?
1 3 . 2 列出你的系统中所有的精灵进程,并说明它们的功能。
1 3 . 3 编写一段调用程序1 3 - 1中d a e m o n _ i n i t函数的程序。调用该函数后调用g e t l o g i n(见
8 . 1 4节)查看该精灵进程是否有登录名。若程序带有3 > /tmp/name1运行时(Bourne shell或
K o r n S h e l l),则将登录名打印到文件描述符3,并重定向到一个临时文件。在调用d a e m o n _ i n i t
和g e t l o g i n之间关闭描述符1、2和3,此时再运行该程序会有什么不同?
1 3 . 4 编写一个S V R 4精灵进程,将其作为一个控制台记录进程。细节可参阅〔AT & T
1 9 9 0 d〕的l o g ( 7 )。每次接收一则消息,并打印相关信息。再编写一个测试程序,将控制台记录
消息发送给/ d e v / l o g以测试该精灵进程。
1 3 . 5 根据1 3 . 3节中提到的规则( 2 ),通过调用两次f o r k修改程序1 3 - 1,以使它在S V R 4下不
能取得控制终端。测试新的函数,并验证它不是一个对话期首进程。

阅读(1228) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~