Android C++ 系列:Linux 信号(三)
可重入函数
不含全局变量和静态变量是可重入函数的一个要素
可重入函数见 man 7 signal
在信号捕捉函数里应使用可重入函数
在信号捕捉函数里禁止调用不可重入函数
例如:strtok 就是一个不可重入函数,因为 strtok 内部维护了一个内部静态指针,保存上一 次切割到的位置,如果信号的捕捉函数中也去调用 strtok 函数,则会造成切割字符串混乱, 应用 strtok_r 版本,r 表示可重入。
信号引起的竞态和异步 I/O
时序竞态
int pause(void)
使调用进程挂起,直到有信号递达,如果递达信号是忽略,则继续挂起
int sigsuspend(const sigset_t *mask)
以通过指定 mask 来临时解除对某个信号的屏蔽,
然后挂起等待,
当被信号唤醒 sigsuspend 返回时,进程的信号屏蔽字恢复为原来的值
mysleep 实现,这种实现方式是否存在 BUG?
mysleep 改进版
全局变量异步 I/O
可重入函数
不含全局变量和静态变量是可重入函数的一个要素
可重入函数见 man 7 signal
在信号捕捉函数里应使用可重入函数
避免异步 I/O 的类型
sig_atomic_t 平台下的原子类型
volatile 防止编译器开启优化选项时,优化对内存的读写
SIGCHLD 信号处理
SIGCHLD 的产生条件
子进程终止时
子进程接收到 SIGSTOP 信号停止时
子进程处在停止态,接受到 SIGCONT 后唤醒时
代码实现
status 处理方式
pid_t waitpid(pid_t pid, int *status, int options)
options
WNOHANG 没有子进程结束,立即返回
WUNTRACED
如果子进程由于被停止产生的 SIGCHLD, waitpid 则立即返回
WCONTINUED 如果子进程由于被 SIGCONT 唤醒而产生的 SIGCHLD, waitpid 则立即返回
获取 status
WIFEXITED(status) 子进程正常 exit 终止,返回真 WEXITSTATUS(status)返回子进程正常退出值
WIFSIGNALED(status) 子进程被信号终止,返回真
WTERMSIG(status)返回终止子进程的信号值 WIFSTOPPED(status)
子进程被停止,返回真 WSTOPSIG(status)返回停止子进程的信号值
WIFCONTINUED(status) 子进程由停止态转为就绪态,返回真
向信号捕捉函数传参
sigqueue
sigaction
实例
进程自己收发信号,在同一地址空间
不同进程间收发信号,不在同一地址空间,不适合传地址
信号中断系统调用
read 阻塞时,信号中断系统调用:
返回部分读到的数据
read 调用失败,errno 设成 EINTER
总结
本文介绍了可重入函数,信号引起的竞态和异步 I/O,SIGCHLD 信号处理,向想好捕捉函数传参,信号中断系统调用。
版权声明: 本文为 InfoQ 作者【轻口味】的原创文章。
原文链接:【http://xie.infoq.cn/article/558591b82239cbc1d7834bf72】。文章转载请联系作者。
评论