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