精华区 [关闭][返回]

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

主题:Unix编程FAQ第一章3-6节
发信人: tengel()
整理人: kevintz(2000-08-24 01:58:07), 站内信件
1。3如何让进程sleep小于一秒的时间?
sleep函数在所有的UNIX中都可用,但仅仅允许指定以秒为单位的间隔。如果你需
要更精确的间隔,那么你需

要寻找其他可能的选择:
。很多系统拥有usleep函数
。你可以使用select或者poll函数,把监测的文件描述符集合置为空;写usleep
函数的通常方法是基于这两个

函数。
。如果你的系统有itimers(大部分都有),你可以使用它来写你自己的usleep(
参考BSD usleep源代码,来

查看BSD是怎么做的)
。如果你有POSIX实时系统,可以使用nanosleep函数。
上面的方法中,select可能是可移植性最好的方法(而且奇怪的是,他一般也比
usleep或者基于itimers的方

法更有效)。然而,如果在sleep的时候,有信号收到,可能行为不同;这对应用
或许是一个问题。
无论你选择那个例程,明白你可能被系统的时间方案所限制是很重要的(一些系
统支持很小的时间间隔被指定

,其他的可能被四舍五入为10ms)。同样,对于sleep,你指定的仅仅是一个最小
的值;在指定的周期过后,

可能在你的进程取得CPU时间仍然有不确定的延时。
1.4我如何得到alarm的更好的版本?
现代UNIX系统往往使用settimer来实现alarms,它比普通的alarm函数有更高的分
辨率和更多的选项。可以假

定alarm和settimer(ITIMER_REAL)可能建立在相同的基础计时器上,同时使用两
种方法来访问可能会造成混乱


Itimers可以被用来实现一次的或者重复的信号;有三种单独的计时器可以使用:

ITIMER_REAL 
实时计数,发送SIFALARM信号
ITIMER_VIRTUAL 
进程使用时间计数,发送SIGVTALRM信号
ITIMER_PROF 
系统和进程时间计数,发送SIGPROF信号;
尽管从4.2BSD就支持Itimers,但并不是所有的标准都支持。实时POSIX扩展定义
了一些类似的,但是不同的函

数。

1。5如何在父子进程见通讯?
父子进程间可以通过任何正常的进程见通讯机制(管道,套接字,消息队列,共
享内存),同时也有一些能够

得到父子进程间关系的优点的其他途径。
最明显的是父进程可以得到子进程的退出状态。
因为子进程继承了父进程的文件标识符,父进程可以打开管道每一端(read or 
write),fork,父进程可以关

闭一端,子进程可以关闭另外一端。这就是当你调用popen例程来运行另外一个应
用程序时所作的工作,也就

是说,你可以向用popen打开的一个文件标识符写数据,子进程把它看作标准输入
,或者你从这个文件标识符

读,而子进程把它看作标准输出。(popen的mode参数定义了这些,如果你希望两
者都作,那么你可以不很困

难的做到它)。

当然,子进程继承了父进程的匿名的内存映射段(或者通过/dev/zero映射),这
些共享内存段不能被不相关

的进程访问。
1。6如何去掉僵尸进程?
1。6。1什么是僵尸进程?
当一个进程fork,而且子进程在父进程之前结束,内核仍然保留一些子进程的信
息,这些信息可以被父进程使

用,例如:父进程需要子进程的退出状态。为了得到这些信息,父进程调用wait
;这时,内核可以丢弃掉这些

信息。
在子进程结束和父进程调用wait之间,子进程被称为“僵尸”。(如果你运行ps
,子进程在它的状态字段拥有

一"Z"状态表示该信息)虽然它已经不运行了,但是它仍然占据进程表的条目。(
它不消耗其他资源,但是一

些工具可以显示象CPU使用的假象;这是因为进程表的一些部分为了节省空间覆盖
了一些统计信息.)
这很不好,因为进程表的条目数量是固定的,它可能使系统的进程数超过进程的
允许数量。即使,系统没有运

行那么多进程,但对每个用户仍然有进程数量的限制,这通常比系统进程数小的
多。这也是你要一直检查fork

运行是否失败的原因之一。
如果父进程没有调用wait就终止,子进程被init收养,init来负责子进程结束的
清理工作。(init是一个系统

的特别的程序,他的进程ID是1----它在系统启动后第一个运行)。
1。6。2如何防止僵尸进程?
你应该确保父进程调用wait(或者是waitid,wait3()等)来等待每个子进程结束
;或者对于一些系统,你可以

指示系统你对子进程的队出状态不感兴趣。
另外的方法是fork两次,而且立即让子进程退出。这使孙子进程成为孤儿,让in
it进程来接管它的清理工作。

在例子中有fork2的代码.
忽略子进程的退出状态,你可以使用下面的代码:(检查你的系统的手册,看它
能否工作)
    struct sigaction sa;
    sa.sa_handler = SIG_IGN;
#ifdef SA_NOCLDWAIT
    sa.sa_flags = SA_NOCLDWAIT;
#else
    sa.sa_flags = 0;
#endif
    sigemptyset(&sa.sa_mask);
    sigaction(SIGCHLD, &sa, NULL);

如果成功,wait函数将被禁止工作;如果他们中的任何一个被调用,他们将等待
所有子进程终止,那么返回失

败,errno==ECHILD。
另外的技术是捕获SIGHLD信号,使信号处理函数调用waitid或者wait3。请参考例
子段的完整程序。

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

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

[关闭][返回]