信号就是通知某个进程发了某个事件,也称为软件中断。信号提供了一种处理异步事件的方法。信号通常是异步发生的,进程预先不知道信号准确发生的时刻。后端程序(daemon)往往需要提供7*24不间断的服务,因此,编程daemon程序时对信号的正确处理尤为重要。下面和大家分享编写daemon程序时信号处理的注意事项,内容都来自Internet,只是进行了整理和总结。关于信号的基础知识请参考APUE。
常见的信号
SIGHUP1和终端的连接断开,发送该信号给控制进程。通常用此信号来通知daemon重新读取配置文件(因为daemon不会有控制终端,通常不会收到该信号)。
SIGINT2用户中断(Ctrl + C)。
SIGABRT6调用abort函数产生(通常是自杀)。
SIGKILL9可以杀死任意进程,不能被捕获或忽略(俗称酒杀)。
SIGSEGV11无效的内存引用(segmentation fault)。
SIGPIPE13对于socket fd,当一个进程向某个已经收到RST的fd执行写操作时,内核会向该进程发送该信号。
SIGTERM15kill命令发送的默认终止信号。
SIGCHLD17进程终止时向其父进程发送的信号。
SIGPROF27使用gprof工具测试时会收到该信号。
别用signal,用sigaction
可以通过signal或者sigaction函数来设置信号处理函数,但signal函数太过古老,因此推荐使用sigaction。理由如下:
1. sigaction可以提供更多接收到信号的信息。
2. 调用完信号处理函数后重新设置处理函数不会对sigaction有影响,因为sigaction默认是不会去重置处理函数的,同时在执行处理函数会屏蔽掉该信号,也不会有竞争。
3. signal函数在某些系统中会默认重启被中断的系统调用,而sigaction默认不会这样做。
4. signal函数在多线程环境中的行为是未定义的,必须使用sigaction函数。
数据传输和信号
使用了系统调用的函数都有可能被信号中断,立刻返回的函数(不需要等待I/O操作的完成或sleep)不会被中断,而需要等待的函数(等待网络传输,管道的读或者sleep)将会被中断,比如select, read, connect。
在daemon程序中,恰当地处理被中断的系统调用是非常重要的。如果read, write等传输数据的函数被中断,必须处理这种情况并恢复数据的传输。有两种被中断的场景:
1. 当没有数据传输时就被中断,函数返回-1,这时可以通过判断errno的值来识别这种错误,如果errno == EINTR,则表示函数在没有任何数据传输的情况下就被中断,这时可以通过同样的参数来再次调用该数据。
2. 另一种情况是数据传输已经在进行,但在没有完成之前被中断;这种情况下函数不会返回错误,而是返回一个小于期望大小的值,同时errno也不会有错误设置,想识别这种情况只能捕获导致中断的信号。在中断之后恢复数据传输时一定记得部分数据已经被传输,必须从正确的偏移再次发起传输。
不要通过sigaction函数设置SA_RESTART来处理被中断的系统调用。
多线程和信号
多线程程序的信号处理和单线程程序有很大的区别。根据POSIX规范,一个多线程的程序只有一个进程和一个pid,哪个线程会被中断并处理到达的信号呢?有两种情况:
发送给进程的信号 比如用kill向一个pid发送信号,每个线程都有单独的信号掩码,可以通过pthread_sigmask来设置。信号不会分发给已经屏蔽了该信号的线程,而是在没有屏蔽该信号的线程中任选一个来接收,但没有指定哪个线程一定可以接收到。如果所有的线程都屏蔽了该信号,该信号将在预处理队列中排队。
发送给线程的信号 pthread_kill可以用来向指定的线程发送信号,分发和排队都是线程级别的。如果没有指定信号处理函数,而默认是结束进程,发送给线程的信号也会导致整个进程退出。
不要在信号处理函数中使用锁。
同步化信号处理 signalfd
signalfd是一个在linux kernel 2.6.22提供的系统调用,功能是使用一个fd来接收信号。这样就可以同步地处理信号,也不需要设置处理函数。可以man signalfd 查看示例程序。首先必须使用sigprocmask来屏蔽要使用signalfd来处理的信号,然后调用signalfd创建一个fd用来读取到达的信号。当被屏蔽的信号到达时,程序将不会被中断,也不会有处理函数被调用。信号会在fd中排队。signalfd创建的fd可以和其他fd一样:可以放在select, poll, epoll中;可以设置为非阻塞;可以为不同的信号创建不同的fd;在fork之后该fd也不会关闭掉,子进程同样可以读懂发送给父进程的信号。signalfd非常适合在主循环中执行epoll处理大量连接的单进程网络服务程序中使用,信号的处理可以和其他fd一样加到epoll中。由于程序不会被中断,可以选择合适的时机才去处理信号。
相关推荐
运用 Node.js-Koa 来开发小程序项目的后端接口 软件开发设计:应用软件开发、系统软件开发、移动应用开发、网站开发C++、Java、python、web、C#等语言的项目开发与学习资料 硬件与设备:单片机、EDA、proteus、RTOS...
一款活动发布,活动报名的微信小程序,包含前后端源码,后端采用python的一款web框架Django进行开发,且使用了缓存和redis,运行项目后端程序前,请确保您已经安装和启动了redis服务器! 软件开发设计:应用软件开发...
网络与通信:数据传输、信号处理、网络协议、网络与通信硬件、网络安全网络与通信是一个非常广泛的领域,它涉及到计算机科学、电子工程、数学等多个学科的知识。 云计算与大数据:包括云计算平台、大数据分析、人工...
万岳直播商城系统服务web端,后端web+前端ios、android,适用于直播商城、短视频商城、社区商城、知识付费等形式,该开源版包含多商户入驻、直播带货、主播分销、电商商城等功能,后续将继续开源小程序端,欢迎关注...
网络与通信:数据传输、信号处理、网络协议、网络与通信硬件、网络安全网络与通信是一个非常广泛的领域,它涉及到计算机科学、电子工程、数学等多个学科的知识。 云计算与大数据:包括云计算平台、大数据分析、人工...
微信小博客:无博客后端,博客数据来源与 hexo 与github 搭建的博客系统 基于uni-app、colorUi、uView,支持小程序、H5、Android和IOS 软件开发设计:PHP、QT、应用软件开发、系统软件开发、移动应用开发、网站开发...
该项目的主要目标是使用简单的方法来构建类似keepalived的服务器,从而使控制平面和数据路径配置脱钩(keepalived与linux的ipvs紧密耦合)以及添加新功能的简便方法(我认为这样更容易在Go程序中添加一些内容,而...
scanbd是扫描仪按钮守护程序。 当插入/取出纸张时,它会轮询扫描仪按钮以查找按下的按钮或... scanbd可以使用(旧的)scanbuttond项目中的所有合理后端或某些特殊后端。 支持的平台:Linux,FreeBSD,NetBSD,OpenBSD
与该功能相关的Linux命令:ipcrm命令 – 移除一个消息对象、共享内存段或信号集logout命令 – 退出系统nohup命令 – 后端运行程序lua命令 – 独立的Lua解释器bg命令 – 将作业放到后台运行ldconfig命令 – 动态链接...
嵌入式DSP专门用来处理对离散时间信号进行极快的处理计算,提高编译效率和执行速度。在数字滤波、FFT(Fast Fourier Transform)、频谱分析、图像处理的分析等领域,DSP正在大量进入嵌入式市场。 18. MCU在...
scanbd 是一个扫描仪按钮守护进程。 它轮询扫描仪按钮,寻找按下的按钮或功能旋钮的... scanbd 可以使用所有健全的后端或来自(旧) scanbuttond 项目的一些特殊后端。 支持的平台:Linux、FreeBSD、NetBSD、OpenBSD
03 程序的解耦 04 module模块和包的介绍 05 模块的执行以及__name__ 06 关于模块的介绍 07 time时间模块 08 random模块 第22章 01 模块的补充 02 sys修改环境变量 03 BASEDIR的介绍 04 os模块的介绍 05 sys模块的...
服务React前端应用程序和Flask后端。 将实施RTMP实时视频服务器。 关键文件 基本任务 在flight-server / flight-scripts /中-在端口14550上连接到无人机。无人机飞行脚本是使用Dronekit编程的,Dronekit是飞行控制...
正弦信号的matlab代码用友图书馆小组最终项目 预先要求 要运行音频代码,您需要安装以下库 portaudio (跨平台音频后端,用C编写) Mac:使用 Linux:您可以使用任何软件包管理器(apt,snap,yum等)进行安装 在...