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