linux socket编程中应全局忽略sigpipe信号,在main开头调用signal(sigpipe, sig_ign),使write()返回-1并置errno为epipe;同时必须检查所有write/send返回值,结合epollin、so_keepalive或应用层心跳及时发现连接异常。

Linux Socket 编程中,SIGPIPE 是一个常见但容易被忽视的“静默杀手”——它不因代码逻辑错误触发,却能在对端关闭连接后的一次 write() 调用中直接终止进程。处理它的核心不是“防住信号”,而是让程序在连接异常时仍能可控、可恢复地运行。
全局忽略 SIGPIPE(最常用且推荐)
在程序启动早期(如 main() 开头、socket 创建前)调用 signal(SIGPIPE, SIG_IGN) 即可全局屏蔽该信号。此后,向已关闭连接写数据时,write() 不再发信号,而是返回 -1 并将 errno 设为 EPIPE,交由应用层统一判断和处理。
- 无需额外信号处理器,代码简洁,线程安全
- 必须在 fork() 或多线程创建前设置,否则子线程/子进程需单独设置
- 注意:忽略后仍需检查 write 返回值,不能仅靠信号是否发生来判断连接状态
使用 send() 的 MSG_NOSIGNAL 标志(按需局部控制)
若无法修改全局信号行为(如嵌入第三方库、模块化服务),可在每次发送时用 send(sockfd, buf, len, MSG_NOSIGNAL) 避免触发 SIGPIPE。这种方式作用范围精确到单次系统调用,不影响其他 socket 或信号全局配置。
Zynq‑7000 / Zynq UltraScale+ 硬件调试技能。适用于 Xilinx Zynq(Cortex‑A9/A53 + FPGA)Linux 环境,调试 I2C、I2S、UART、GPIO 等外设。包括设备树配置、内核驱动、用户空间调试工具、交叉编译和常见问题排查,支持 PetaLinux 开发。
- 适用于非阻塞 socket 场景,尤其配合 epoll 使用时更灵活
- 返回值逻辑与 write() 一致:-1 且 errno == EPIPE 表示对端已关闭
- 不能用于 write()、writev() 等无标志参数的接口,需改用 send() 或 sendmsg()
结合返回值做连接状态判断(不可省略的基础步骤)
无论是否屏蔽 SIGPIPE,write()/send() 的返回值始终是连接状态的唯一可靠依据:
- 返回 0:对端已执行 shutdown(SHUT_WR) 或 close(),本端可安全关闭读端
- 返回 -1 且 errno == EPIPE:对端已关闭,本端仍在尝试写入(典型于 SIGPIPE 被忽略后)
- 返回 -1 且 errno == EAGAIN/EWOULDBLOCK:非阻塞 socket 当前不可写,需等待 EPOLLOUT 事件
- 返回正数:成功写入字节数,但不保证对方已收到或处理
配合连接保活机制提前发现问题
SIGPIPE 只在实际写操作时暴露断连,无法预防“静默掉线”。因此必须叠加主动探测手段:
- 启用内核级心跳:setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)),适合长连接但探测间隔较长(默认 2 小时)
- 实现应用层心跳:定期发送小包(如 ping/pong),超时未响应则主动 close 连接
- 搭配 epoll_wait() 监听 EPOLLIN 事件:若对端优雅关闭(发送 FIN),recv() 会返回 0;若异常断开(RST 或网络中断),后续 recv/write 才暴露问题










