建设免费网站制作,秦皇岛网站制作哪家好,网页设计就业,国内三大oa系统收发信号思想是 Linux 程序设计特性之一#xff0c;一个信号可以认为是一种软中断#xff0c;通过用来向进程通知异步事件。 本文讲述的 信号处理内容源自 Linux man。本文主要对各 API 进行详细介绍#xff0c;从而更好的理解信号编程。 signal 遵循 C11#xff0c;POSIX.… 收发信号思想是 Linux 程序设计特性之一一个信号可以认为是一种软中断通过用来向进程通知异步事件。 本文讲述的 信号处理内容源自 Linux man。本文主要对各 API 进行详细介绍从而更好的理解信号编程。 signal 遵循 C11POSIX.1 - 2008 1.库
标准 c 库libc, -lc
2.头文件
signal.h
3.接口定义 #include signal.htypedef void (*sighandler_t)(int);sighandler_t signal(int signum, sighandler_t handler);
4.接口描述 注意signal() 的行为会根据不同的 UNIX 版本而变化同样它也会根据 Linux 版本的不同而不同。考虑到程序的可移植性尽量避免 signal() 的使用而是使用 sigacton(2) 代替可以参考下面移植性部分。 signal() 设置 signum 信号的处理函数为 handler处理函数可以是SIG_IGN、SIG_DFL也可以是程序设计人员定义的函数地址。 如果 signum 被分发给到一个进程那么会发生以下行为
如果处理函数设置成了 SIG_IGN那么信号会被忽略。如果处理函数设置成了 SIG_DFL那么信号的默认关联行为会发生可以参考 signal(7)。如果处理函数设置成了一个函数那么首先会将默认处理函数复位为 SIG_DFL或者信号被阻塞参考下面可移植性部分然后会调用 handler 函数并传递 signum 参数。如果处理函数调用导致了该信号处理阻塞那么在处理函数返回后该信号会重新被 unblock。 SIGKILL 和 SIGSTOP 两个信号不能被捕捉或者忽略。
5.返回值 signal() 返回信号之前 的处理函数值。发生错误时signal() 会返回 SIG_ERR并设置 errno 来提示具体错误。 错误值定义如下
EINVALsignum 参数不合法
6.版本 sighandler_t 是一个 GNU 扩展它会在 _GNU_SOURCE 定义时暴漏出来。如果定义了_BSD_SOURCEglibc 2.19 或低版本 或者 _DEFAULT_SOURCEglibc 2.19 或高版本glibc 也定义了 sig_t。不使用这些定义的情况下signal() 的声明就会有些晦涩 void ( *signal(int signum, void (*handler)(int)) ) (int);可移植性 signal() 只有在将 handler 设置为 SIG_DFL/SIG_IGN 时才具有移植性。使用 signal() 建立信号处理函数的语义随着系统的不同而不同POSIX.1 明确允许这些不同的行为。所以不要使用它于此目的。 POSIX.1 通过 sigaction(2) 接口解决了这种移植上的混乱sigaction(2) 提供了信号处理调用的明确语义定义。所以使用 sigaction(2) 来代替 signal()。
7.历史 C89POSIX.1-2001 在原来的 UNIX 系统中当使用 signal() 建立的信号处理函数被调用时信号的处理会被设置成 SIG_DFT并且系统不会阻塞该信号通往其他进程的发布。这相当于调用了 sigaction(2)附带以下标记 sa.sa_flags SA_RESETHAND | SA_NODEFER;System V 已提供了 signal() 的语义不过这个定义有点差劲因为在处理函数重新建立连接前可能会连续收到两个信号。更严重的同一个信号的频繁分发会导致处理函数的递归调用。 BSD 对此进行了改善但不幸的是这种改善却改变了现存 signal() 接口的语义。在 BSD 系统上当一个处理函数调用时信号处置并没有被重新设置后面发生的该信号的实例因该处理函数正在执行无法进行分发。更严重的一些阻塞系统调用会在信号处理函数打断后自动重启。BSD 语义相当于使用下面标记调用 sigaction(2) sa.sa_flags SA_RESTART;Linux 上的情景如下
内核的 signal() 系统调用提供了 System V 语义默认情况下glibc 2 及更高版本的 signal() 封装并没有调用内核系统调用而是调用了 sigaction(2)提供 BSD 语义的标记。只要提供合适的宏定义就可以提供以上默认行为glibc 2.19 或低版本的 _BSD_SOURCE 或者 2.19 或更高版本的 _DEFAULT_SOURCE。默认情况下这些宏是定义了的参考 feature_test_macros(7) 。如果这些测试宏没有开启那么 signal) 提供的是 System V 语义。 8.注意 signal() 在进程的多线程场景下的副作用是未定义的。 根据 POSIX 定义进程忽略非 kill(2)/raise(3) 产生的 SIGFPE/SIGILL/SIGSEGV 信号后的行为是未定义的。整数除以 0 是未定义的结果在一些架构上它会产生 SIGFPE 信号同样使用 -1 除最大负整数也可能产生 SIGFPE。忽略这些信号可能会导致无限循环。 参考 sigaction(2) 获取更多关于将 SIGCHLD 信号的处置设置为 SIGIGN 的信息。 参考 signal-safety(7) 来查看一些可以在信号处理函数内部调用的异步信号安全的函数。
9.代码 下面是一个捕捉 CTRL C 信号的程序。
#include stdio.h
#include unistd.h
#include stdlib.h
#include signal.hvoid sighandler(int);int main()
{signal(SIGINT, sighandler);while(1) {printf(开始休眠一秒钟...\n);sleep(1);}return(0);
}void sighandler(int signum)
{printf(捕获信号 %d跳出...\n, signum);exit(1);
}
下一篇 【计算机网络】信号处理接口 Signal API2