文章结构:
wait()的阻塞问题
之前的多进程:父进程监听子进程状态 wait()的使用文章中,父进程为了获取子进程的SIGSTOP、SIGTERM等信号时,由于调用了wait
而导致主进程一直阻塞。在实际的开发中,主进程在等待子进程状态变化时还会有其它的事情要去执行,所以需要一种异步回调机制,让主进程可以在执行其它任务的时候,又可以监听到子进程的进程状态变化时及时处理。
signal()
函数就可以解决以上的问题。
signal()函数讲解
signal()
函数原型如下:
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
typedef
定义了一类函数名叫sighandler_t
,该函数返回类型为void
,且只有一个int
型参数。
signal()
函数第一个参数signum
指所要监听的进程状态的变量信号,所有可监听的信号量的定义可以从sys/signal.h
头文件中去查阅。本文文章的demo中要处理的信号量有:
SIGSTOP: 发送给父进程的,表示子进程被外部命令所暂停。命令可以是
kill
,也可以在top
中操作。SIGCHLD: 发送给父进程的,表示子进程被外部命令所暂停或已经执行完毕退出。这时需要父进程执行
wait
函数让子进程从僵尸进程
状态彻底被系统回收。SIGWINCH: 程序窗口大小发生变化。在终端命令行下运行可执行文件时鼠标拖动一下窗口即可获得此信号。
signal()
函数第二个参数是指定signum
的处理函数。该函数的唯一参数将会被赋值为被监听到的信号量。在此函数中可以调用wait
或其它处理逻辑。也可以赋值为系统的SIG_IGN
或SIG_DFL
函数,分别表示忽略和默认处理方式。但是信号量SIGKILL
及SIGSTOP
的处理方式是不能被忽略处理。
当自定义了信号量处理函数后,所监听的信号被捕获,则该信号会被设置为阻塞blocked
,然后再执行处理函数中的逻辑,处理函数执行完毕后,信号量恢复为未阻塞状态unblocked
。
signal()
函数正常执行,返回值为signum
的原有处理函数;否则出错返回SIG_ERR
,并且可以通过errno
来查看错误原因。
signal()
函数在不同的Unix或Linux版本间存在较大的差异,所以一般推荐用sigaction()
函数来替换。本文不涉及sigaction()
的内容。
示例代码
接下来演示signal()
函数的使用。代码示例中依然用到了对标准输出流的重定向freopen,将子进程的日志输出到child_signal.txt
,父进程日志输出到main_signal.txt
中去。
signal.c
|