POSIX信号处理
- 信号有时候也称为软件中断,信号通常是异步的
- 信号发送:
- 由一个进程发给另一个进程
- 内核发送给某个进程
- 处理信号:
- 通过一个信号处理函数来应对特定信号,这种行为称为捕获信号
- 将信号设置为SIG_IGN忽略,SIGKILL/SIGSTOP不能被捕获也不能被忽略
- 将信号设置为SIG_DFL来启动默认处置
- 建立信号处置的POSIX方法就是调用sigaction
- 有些信号在信号处理函数被调用时阻塞,任何阻塞的信号都是不能递交给进程,将信号掩码设置为空集,则在信号函数运行期间,不阻塞额外的信号
- 如果SA_RESTART设置,相应的信号中断的系统调用将有内核自动重启
- unix信号默认不排队,信号在被阻塞期间产生多次,解阻塞之后通常只递交一次
处理SIGCHLD信号
- 进程终止则该进程的子进程处于僵死状态,处理僵死进程的目的是维护子进程的状态信息将僵死进程的父进程PPID重置为1(被内核领养)
- 信号处理函数捕获SIGCHLD信号,调用wait或者waitpid
Signal(SIGCHLD, sig_chld);
- 当接收到SIGCHLD信号时,父进程阻塞与accept调用,内核会使accept返回一个EINTR错误(被中断的系统调用),父进程不处理这类错误,中止。标准库函中的signal函数不会使内核自动重启被中断的系统调用,SA_RESTRAT没有被设置
- 慢系统调用:当阻塞于某个慢系统调用时,进程捕获某个信号且相应的信号处理函数返回时有可能会返回一个EINTR错误。对accept的for循环添加条件
if(errno==EINTR); continue;
- 当connect被中断时不自动重启,必须调用select等待连接完成
wait和waitpid函数
1 | #include <sys/wait.h> |
- 两个函数均返回两个值:已终止子进程的PID和statloc指针返回的进程终止状态
- 如果调用wait的进程没有子进程终止,并且有一个或多个子进程在执行,则wait一直阻塞直到有子进程终止为止
- 客户终止时调用exit,所有打开的描述符都由内核自动关闭,五个连接在同时时刻终止,Unix信号不排队,很可能会产生四个僵死进程。使用waitpid在循环内调用获得所有已终止自己才能横的状态,指定WNOHANG选项
while((pid=waitpid(-1, &stat, WNOHANG))>0)
SIGPIPE信号
- 当一个进程向某个已收到RST套接字执行写操作时,内核向进程发送一个SIGPIPE信号,该信号的默认行为是终止进程
- 不管是使用信号处理函数并返回还是简单的忽略该信号,写操作都会返回EPIPE错误
- 第一次写操作引发RST,第二次写操作时引发SIGPIPE信号
服务器主机关机
- Unix系统关机,init进程给所有进程发送SIGTERM信号,等待一段时间,然后给所有仍在运行的进程发送SIGKILL信号,服务器子进程终止时,所有打开的描述符都被关闭
数据格式
- 不同的实现以不同的格式存储二进制数
- 不同的实现在存储相同的C数据类型上存在差异,32位和64位系统
- 不同的实现给结构打包的方式存在差异,取决于个数据类型所用的位数和机器的对其限制
- 解决以上数据格式的方法:
- 将所有传输数据作为字符串来传输
- 显示定义所支持的二进制格式