精华区 [关闭][返回]

当前位置:网易精华区>>讨论区精华>>编程开发>>C/C++>>资料汇编----------藏经阁>>Unix编程FAQ>>Unix编程FAQ第一章7-13节

主题:Unix编程FAQ第一章7-13节
发信人: tengel()
整理人: kevintz(2000-08-24 02:05:19), 站内信件
1。7如何使我的程序作为守护进程工作?
守护进程是经常被定义像后台进程一样运行但不属于任何终端会话。许多系统服
务,像网络,打印都是通过

守护进程执行。
简单的在后台运行程序不是这些长运行程序真正的适合的方法;因为这样没有真
正的把进程从终端会话中分

离出来。而且,常规的运行守护进程的方法是简单的在rc脚本中手工输入命令,
守护进程被期望自动进入后

台执行。
下面是建立守护进程的步骤:
1。fork(),所以父进程可以退出,这可以返回控制给命令行或者调用你的应用程
序的shell;这一步被要求

以使新进程保证不作为进程组的首进程。下一步,setsid(),如果你的进程是首
进程将失败。
2。setsid()将一个进程转变为进程组或者会话组的首(进程)。因为控制终端与
一个会话关联,而且新的

会话没有获得一个新的控制终端,我们的进程就没有了控制终端,这对守护进程
来说是一件好事。
3。再fork()一次,以使父进程(会话组的首进程)可以退出。这意味着,作为非
会话组首进程,将永远也

不能重新得到控制终端。
4。chdir("/")来确认我们的进程不再使用任何目录。如果失败将使系统管理员不
能卸载文件系统,因为那

是我们的当前目录(我们不能改变任何包含守护进程操作的文件的目录)
5。umask(0)以使我们完全控制我们写的任何权限。我们不知道我们继承的umask
。[这一步时可选的]
6。close()文件描述符0,1,和2。这就释放了我们继承子我们父进程的标准输入
输出,和错误。我们没有

办法知道这些描述符在那里被重定向。很多守护进程使用sysconf()来检测_SC_O
PEN_MAX的限制。

_SC_OPEN_MAX告诉我们每个进程可以打开文件的最大数目。那么在一个循环,收
据进程可以关闭所有可能的

文件描述符。你不得不决定是否需要做这一步。如果你想你将关闭可能打开的文
件描述符,这里有一个并发

的文件描述符的数量上的限制。
7。为标准输入,输出,错误建立新的文件描述符。甚至如果你不打算使用他们,
这仍然是一个好主意。浙

将精确的处理事件;如果你有一个日志文件,例如,你可能希望像标准输出或者
标准错误一样打开它,作为

标准输入打开"/dev/null",可选的,你能作为标准错误或者标准输出打开"/dev/
console",或者为你的守护

进程使用其他组合。
如果你的守护进程通过inetd启动,那么上面的步骤几乎没有多少是必须的。在这
种情况下,标准输入,输

出,错误都被设置为网络连接,fork和会话管理将不需要。仅仅chdir和umask两
个步骤是有用的。
1。8我如何像系统中的ps一样察看进程?
你实际上不需要这样做。
到目前为止最可移植的方法是popen(pscmd,"r"),然后分析他的输出。(pscmd在
SysV上可能是象"ps -ef"

一样的命令,在BSD上,有很选项)
在例子一节,有两个完整版本的程序;一个是SunOS4的,他要求root权限来运行
和使用kvm_*例程来读核心

数据结构;另外一个是SVR4系统的(包含SunOS5),使用Proc文件系统。
在更早的系统有一个SVR4.2风格的"/proc",从"/proc/PID/psinfo"中可一读取每
个感兴趣的进程的信息,

该信息以psinfo_t结构表示。然而这种方法或许是被支持的最差的。(在FreeBS
D系统的"/proc",你从

"/proc/PID/status"中读一个半公开的可打印字符串;Linux也基本上是这样)。

1。9给出一个pid,如何获取它是否是一个正在运行的程序?
使用kill()和一个0的信号值。
下面是四种可能的返回值:
。返回0 意味着给出pid的进程存在,而且系统允许你个他发送信号。他是否是一
个僵尸进程与特定的系统

有关。
。返回-1,errno==ESRCH 或者该进程不存在,或者安全机制使系统禁止它存在(
在一些系统,该进程可能是

一个僵尸进程)
。返回-1.errno==ESERM 系统不允许你kill指定的进程。这意味着或者该进程存
在(在一次说明,它可能是

一个僵尸进程)或者严格的安全机制被表现(例如:你的进程不允许发送信号给
其他进程)
。返回-1,和其他的errno,那么你有麻烦了。
最常用的技术是假定成功或者失败返回errno=ESERM意味着进程存在,其他错误意
味着进程不存在。
一个可选的方案,如果你工作在特定的系统,你可以提供一个"/proc"文件系统来
监测"/proc/PID"是否存在


1。10 system/pclose/waitpid的返回是什么?
system(),pclose(),waitpid()的返回值不像是进程的退出值,或者退出值被左移
了8位,到底是怎么回事?
手册是对的,你也是对的。如果你阅读了手册waitpid项,你将发现进程的退出值
被编码了。进程的退出值

在高十六位,其他部分被另外一些东西使用。你不能依赖他们,除非你不想移植
他们,所以建议你使用宏,

一般在wait或者wstat下的有文档。
为此目的宏定义(在<sys/wait>中)包含(stat是一个waitpid的返回值):
WIFEXITED(stat) 
如果子进程正常退出为非0值
WEXITSTATUS(stat) 
子进程的返回值
WIFSIGNALED(stat) 
子进程被信号锁终止为非0值
WTERMSIG(stat) 
终止子进程的信号
WIFSTOPPED(stat) 
如果子进程停止为非0值
WSTOPSIG(stat) 
终止子进程的信号数量
WIFCONTINUED(stat) 
子进程继续为非0值
WCOREDUMP(stat) 
如果WIFSIGNALED(stat) 为非0,如果进程在core dump之后退出,这个值也为非
0
1。11如何得到进程的内存使用量
如果可用,看getrusage。
1。12为何进程从不减少大小?
当你使用free归还内存到堆,在大多数系统上并不减少你的程序的内存的使用。
被释放的内存仍然是进程的

地址空间的一部分,将被以后malloc()请求所使用。
如果你确实需要释放内存给系统,察看使用mmap()来申请私有的匿名映射。当他
们被ummapped,内存将真正

的释放给系统。某些malloc的实现(像GNU C库)自动的使用mmap(),来使之可以
执行大的内存申请;这些

块将在free()被返还给系统。
当然,如果你的程序在你认为不应该的时候增加大小,你可能有内存漏洞----程
序的一个bug,也就是内存

没有被释放。
1。13我如何改变我的程序的名字(在ps中看)?
在BSDish系统,ps程序实际上是察看进程的地址空间来找到当前的argv[],然后
显示他,这允许应用程序改

变他的名字,通过简单的修改argv[].
在SysVish系统,命令名和通常前80个字节的参数被存贮在进程的u-area(不再进
程地址空间?),所以不

能直接修改他。可能有一个系统调用来修改他,另外的唯一的方法是执行exec,
或者些核心内存(很危险,

而且仅仅能作为root来执行)
其它系统(特别是solaris)可能有两个不同的ps,一个在 /usr/bin 作为SYSV的
行为,另外的一个在 

/usr/ucb/ps 来作为BSD的行为。在这些系统上,如果你更改了argv[],将只影响
到BSD。
检查你的系统是否有setproctitle函数。

--
                                           _
   O           @___       G               : \  
  /|__       /|/         /\|\             :  \
 /|/_       / /\         \ X_             :   \
  /  |     __/  \          | \      0     :    \
 /    0        0|          /              :     \

※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.103.136.195]

[关闭][返回]