发信人: 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]
|
|