📄 00000013.htm
字号:
<HTML><HEAD> <TITLE>BBS水木清华站∶精华区</TITLE></HEAD><BODY><CENTER><H1>BBS水木清华站∶精华区</H1></CENTER>发信人: SuperSB (孤鹰), 信区: Linux <BR>标 题: [转载]unix环境高级编程-13 <BR>发信站: BBS 水木清华站 (Wed Mar 15 14:30:56 2000) <BR> <BR> <BR> <BR> <BR>发信人: taosm (128+64-->cool), 信区: unix <BR>标 题: unix环境高级编程--第13章 精灵进程 <BR>发信站: 西十八BBS (Sat Mar 11 13:53:31 2000), 转信 <BR> <BR>第十三章 精灵进程 <BR>13.1 介绍 <BR>精灵(Daemons)是生存期长的一种进程。它们常常在系统引导装入时启动,在系 <BR>统关闭(shutdown)时终止。因为它们没有控制终端,所以我们说它们是在后台运 <BR>行的。UNIX系统有很多精灵进程,它们执行日常事物活动。 <BR>本章说明精灵的进程结构,以及如何编写精灵进程程序,因为精灵没有控制终端, <BR>我们需要了解在有关事物出问题时,精灵进程如何报告出错情况。 <BR>13.2 精灵进程的特征 <BR>让我们先来察看一些常用的系统精灵进程,以及它们怎样和第九章中所叙述的概念 <BR>:进程组、控制终端和对话期相关联。ps(1)命令打印系统中各个进程的状态。该 <BR>命令有多个选择项,有关细节请参考系统手册。为了察看本节讨论中所需的信息, <BR>在4.3+BSD或SUN OS 系统下执行: <BR> ps -axj <BR>选择项-a显示由其他用户(others)所拥有的进程的状态;-x显示没有控制终端的 <BR>进程的状态。-j显示与作业有关的信息:对话期ID、进程组ID、控制终端以及终端 <BR>进程组ID。在SVR4之下,与此相类似的命令是ps -efjc。(在某些符合"美国国防 <BR>部安全性准则"要求的UNIX系统中,只能使用ps 查看自己所拥有的进程。)ps的输 <BR>出大致是: <BR>PPID PID PGID SID TT TPGID UID COMMAND <BR>0 0 0 0 ? -1 0 <BR>wapper <BR>0 1 0 0 ? -1 0 <BR>sbin/init - <BR>0 2 0 0 ? -1 0 <BR>agedaemon <BR>1 80 80 80 ? -1 0 <BR>yslogd <BR>1 88 88 88 ? -1 0 <BR>usr/lib/sendmail -bd -qlh <BR>1 105 37 37 ? -1 0 <BR>pdate <BR>1 108 108 108 ? -1 0 <BR>ron <BR>1 114 114 114 ? -1 0 <BR>netd <BR>1 117 117 117 ? -1 0 <BR>usr/lib/lpd <BR>其中,已移去了一些我们并无兴趣的列,例如累计CPU时间。按照顺序,各列标题 <BR>的意义是:父进程ID、进程ID、进程组ID、终端名称、终端进程组ID(与该控制终 <BR>端相关的前台进程组)、用户ID以及实际命令字符串。 <BR> 这些ps命令在支持对话期ID的系统(SUN OS)上运行,我们曾在9.5节的sets <BR>id函数中提及对话期ID。它是对话期首进程的进程ID。但是,4.3+BSD系统将打印 <BR>与本进程所属进程组对应的session结构的地址(见9.11) <BR>进程0、1以及2是8.2节中所述的进程。这些进程非常特殊,存在于系统的整个生命 <BR>期中。它们没有父进程ID,没有组进程ID,也没有对话期ID。syslogd精灵进程可 <BR>用于任何为操作人员记录系统消息的程序。可以在一台实际的控制台上打印这些消 <BR>息,也可将它们写到一个文件中(在13.4.2中将对syslog设施进行说明)。sendm <BR>ail是标准邮递精灵进程。update程序定期将核心缓存中的内容写到硬盘上(通常 <BR>是每隔30秒)。为了做到这一点,该程序每隔30秒调用sync(2)函数一次(在4. <BR>24节中已对sync进行了说明)。cron精灵进程在指定的日期和时间执行指定的命令 <BR>。许多系统管理任务是由cron定期地使相关程序执行而得以实现的。我们已在9.3 <BR>节中提到inetd精灵进程。它监听系统的网络界面,以输入对各种网络服务器的请 <BR>求。最后一个精灵进程,lpd,处理对系统提出的各个打印请求。 <BR>注意,所有精灵进程都以超级用户(用户ID为0)的优先权运行。没有一个精灵进 <BR>程具有控制终端-终端名称设置为问号(?)、终端前台进程组ID设置为-1。缺少 <BR>控制终端可能是精灵进程调用了setsid的结果。除update以外的所有精灵进程都是 <BR>进程组的首进程,对话期的首进程,而且是这些进程组和对话期中的唯一进程。u <BR>pdate是它所在进程组(37)和对话期(37)中的唯一进程,但是该进程组的首进 <BR>程(可能也是该对话期的首进程)已经终止。最后,应当引起注意的是所有这些精 <BR>灵进程的父进程都是init进程。 <BR>13.3 编程规则 <BR>在编写精灵进程程序时需遵循一些基本规则,以便防止产生并不希望的交互作用。 <BR>下面先说明这些规则,然后是一个按照规则编写的函数daemon-init。 <BR>1. 首先做的是调用fork,然后使父进程终止。这样做实现了下面几点。第一,如 <BR>果该精灵进程是由一条简单shell命令启动的,那么使父进程终止使得shell认为这 <BR>条命令已经执行完成。第二,子进程继承了父进程的进程组ID,但具有一个新的进 <BR>程ID,这就保证了子进程不是一个进程组的首进程。这对于下面就要做的setsid调 <BR>用是必要的前提条件。 <BR>2. 调用setsid以创建一个新对话期。于是执行9.5节中列举的三个操作。使调用进 <BR>程:(1)成为新对话期的首进程,(2)成为一个新进程组的首进程,(3)没有 <BR>控制终端。 <BR>在SVR之下,有些人建议在此时再调用fork,并使父进程终止。第二个子进程作为 <BR>精灵进程继续运行。这样就保证了该精灵进程不是对话期首进程,于是按照SVR4规 <BR>则(见9.6节)可以防止它取得控制终端。另一方面,为了避免取得控制终端,无 <BR>论何时打开一个中断设备都要指定O-NOCTTY。 <BR>3. 将当前工作目录更改为根目录。从父进程继承过来的当前工作目录可能在一个 <BR>装配的文件系统中。因为精灵进程通常在系统再引导之前是一直存在的,所以如果 <BR>精灵进程的当前工作目录在一个装配文件系统中,那么该文件系统就不能被拆卸。 <BR> <BR>另外,某些精灵进程可能会把当前工作目录更改到某个指定位置,在此位置做它们 <BR>的工作。例如,行式打印机假脱机精灵进程常常将其工作目录更改到它们的spool <BR>目录上。 <BR>4. 将文件方式创建屏蔽字设置为0。由继承得来的文件方式创建屏蔽字可能会拒绝 <BR>设置某些许可权。例如,若精灵进程要创建一个组可读、写的文件,而继承的文件 <BR>方式创建屏蔽字,屏蔽了这两种许可权,则所要求的组可读、写就不能起作用。 <BR>5. 关闭不再需要的文件描述符。这样使精灵进程就不再持有从其父进程继承来的 <BR>某些文件描述符(父进程可能是shell进程,或某个其它进程)。但是,究竟关闭 <BR>那些描述符则与具体的精灵进程有关,所以在下面的例子中不包含此步骤。可以使 <BR>用程序2.3中的open_max函数来决定最高文件描述符值,并关闭直到该值的所有描 <BR>述符。 <BR>实例 <BR> 程序13.1是个函数,可由想初始化成为一个精灵进程的程序调用。 <BR>#include <sys/types.h> <BR>#include <sys/stat.h> <BR>#include <fcntl.h> <BR>#include "ourhdr.h" <BR>int <BR>daemon_init(void) <BR>{ <BR> pid_t pid; <BR> if ( (pid = fork()) < 0) <BR> return(-1); <BR> else if (pid != 0) <BR> exit(0); /* parent goes bye-bye */ <BR> /* child continues */ <BR> setsid(); /* become session leader */ <BR> chdir("/"); /* change working directory */ <BR> umask(0); /* clear our file mode creation mask */ <BR> return(0); <BR>} <BR>程序13.1 初始化一个精灵进程 <BR>若daemon-init函数由main函数调用,然后进入睡眠状态,那么我们可以用ps命令 <BR>检查该精灵进程的状态: <BR>$a.out <BR>$ps_axj <BR>PPID PID PGID SID TT TPGID UID COMMAND <BR> 1 735 735 735 ? -1 224 a.out <BR> 从中可以看到,该精灵进程已被正确地初始化。 <BR>13.4 出错记录 <BR>与精灵进程有关的一个问题是如何处理出错消息。因为它没有控制终端,所以不能 <BR>只是写到标准出错输出上。在很多工作站上,控制台设备运行一个窗口系统,所以 <BR>我们不希望所有精灵进程都写到控制台设备上。我们也不希望每个精灵进程将它自 <BR>己的出错消息写到一个单独的文件中。对系统管理人员而言;如果要关心哪一个精 <BR>灵进程写到哪一个记录文件中,并定期地检查这些文件,那么一定会使他感到头痛 <BR>。所以,需要有一个集中的精灵进程出错记录设施。 <BR>贝克莱开发了BSD syslog 设施,并广泛应用于4.2BSD。从4.×BSD导出的很多系统 <BR>都支持syslog。在13.4.2中说明该设施。 <BR>在系统V中,从来没有一个集中的精灵进程记录设施。SVR4支持BSD风格的syslog设 <BR>施,在SVR4之下的inetd精灵进程使用syslog。在SVR中,syslog的基础是/dev/lo <BR>g流设备驱动程序,在下一节对此进行说明。 <BR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -