1.处理被中断的系统调用
对于可能永远阻塞的的系统调用,称为慢系统调用(slow system call),永远阻塞的系统调用指调用有可能永远无法返回。例如,没有客户端连接到服务器上,那么服务器的accept就木有返回的保证。对管道和终端设备的读写也是一个慢系统调用的例子,而磁盘I/O是个例外,一般都会返回到调用者。
适用于慢调用的基本原则:当阻塞于某个慢系统调用的进程捕获某个信号且相应信号处理函数返回时,该系统调用可能返回EINTR错误。当编写捕获信号的程序时需要考虑慢系统调用返回EINTR有所准备。有些内核自动重启被中断的系统调用。
2.wait和waitpid函数
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);
int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
2函数均返回2个值:已经终止子进程的进程ID号,以及通过status指针返回的子进程终止符,可以调用3个宏来检查状态,并判别子进程是正常终止、由某一个信号杀死还是仅仅由作业控制停止而已。有些宏用于接着获取子进程的退出状态、杀死子进程的信号值或停止子进程的作业控制信号值。如果调用wait的进程没有已经终止的子进程,但有1+个子进程在执行,则其阻塞到现有第一个终止为止。
waitpid可以设置多个参数来控制,pid是指定想等待的进程ID,值-1表示等待第一个终止的子进程,0表示组进程ID=调用进程ID的子进程,>0表示子进程ID等于PID的子进程。options允许指定附加选项,最常用的WNOHANG,告知内核没有已终止子进程时不要阻塞。
进程网络编程需要考虑三种情况:
1.当fork子进程时,必须捕获SIGCHLD信号;
2.当捕获信号时,必须处理被中断的系统调用;
3.SIGCHLD的信号处理函数必须编写正确,应使用waitpid函数以免留下僵尸进程。