Linux网络编程的相关信号
来源:互联网 发布:hive 数据倾斜 编辑:程序博客网 时间:2024/05/18 20:34
《Linux高性能服务器编程》阅读笔记:
SIGHUP、SIGPIPE和SIGURG是网络编程中密切相关的信号。
SIGHUP: SIGHUP信号的触发时机是在进程的控制终端被挂起,对于没有控制终端的网络后台程序来说,通常是利用SIGHUP信号来强制服务器程序重读相关的配置文件,一个典型的例子就是xinetd超级服务器程序。
SIGPIPE: 往读端关闭的管道或socket连接中写数据将会触发SIGPIPE信号,在Linux网络编程基础API–TCP的数据读写API中讲道,对端close()通信连接后,本端继续发数据,本端将会收到一个RST复位报文提示本端对端已经关闭连接、需重新建立连接,此时再继续往对端发数据,本端系统将会产生SIFPIPE信号。服务器程序需要在代码中捕获并处理该信号,或者至少忽略它,因为SIGPIPE信号的默认处理行为是结束所在进程。引起SIGPIPE信号的写操作将设置errno为EPIPE。send()系统调用的MSG_NOSIGNAL可选项可禁止写操作触发SPGPIPE信号,所以在这种情况下可以使用send()函数反馈的errno值来判断管道或者socket连接的对端是否关闭。
此外,前面学习IO复用时讲道,IO复用也可以用来检测管道和socket连接的读(对)端是否已经关闭,如poll,当读对端关闭时,本(写)端描述符的POLLHUP事件将被触发,当socket连接被对端关闭时,socket上的POLLRDHUP事件将被触发。
SIGURG:在前面的IO复用技术中,select()等系统调用在接收到带外数据时将能够返回并返回异常事件(select()是exceptfds),另一种方法就是利用SIGURG信号:
typedef void(*handle_func)(int);//SIGURG的信号处理函数,负责读带外数据void sig_urg(int sig){ int errno_bak = errno; char buf[BUFZE] = {0}; int ret = recv(connfd, buf, BUFSE - 1, MSG_OOB); printf("%d byte OOB data: %s\n", ret, buf); errno = errno_bak;}//为SIGURG信号绑定操作函数等行为int add_signal(int sig, handle_func func){ struct sigaction sa; bzero(&sa, sizeof(sa)); sa.sa_handler = func; sa.sa_flags |= SA_RESTART; //重新调用被该信号终止的系统调用,保证服务端程序一直运行 sigfillset(&sa.sa_mask); //屏蔽其它所有所有信号 return sigaction(sig, &sa, NULL);}int main(void){ //... add_signal(SIGURG, sig_urg); //注册信号捕捉函数 fcntl(connfd, F_SETOWN, getpid()); //设置SIGURG信号关联的fd的宿主进程或进程组 char buf[BUFSE] = {0}; while (1) //循环读数据 { bzeor(buf, BUFSZ); ret = recv(connfd, buf, BUFSZ - 1, 0); if (ret <= 0) break; printf("%d byte Normal data: %s\n", ret, buf); } close(fd); close(sock_fd); return 0;}