大家好,欢迎来到IT知识分享网。
一、signal 信号简介
二、signal 产生方式
1. 用户操作终端
- 终端上按
Ctrl+C
组合键通常产生中断信号SIGINT
- 终端上按
Ctrl+\
键通常产生中断信号SIGQUIT
- 终端上按
Ctrl+Z
键通常产生中断信号SIGSTOP
2. 硬件异常
除数为 0,无效的内存访问等。这些情况通常由硬件检测到并通知内核,然后内核产生适当的信号发送给相应的进程
3. 软件异常
当检测到某种软件条件发生,将其通知有关进程时产生信号
4. 调用 kill()
函数或者执行 kill
命令
kill
命令实际上是使用 kill()
函数来发送信号,接收信号进程和发送信号进程的所有者必须相同,或发送信号进程的所有者必须是超级用户
三、signal 基本函数
1. int kill(pid_t pid, int signum);
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <signal.h> int main(int argc, char *argv[]) {
pid_t pid; int i = 0; pid = fork(); if (0 == pid) {
while (1) {
printf("I am son\n"); sleep(1); } } else {
while (1) {
printf("I am father\n"); sleep(1); i++; if (3 == i) {
kill(pid, SIGINT); // 向子进程发送中断信号 SIGINT // kill(pid, 2); // 等价于 kill(pid, SIGINT); } } } return 0; }
2. int pause(void);
#include <stdio.h> #include <unistd.h> int main(int argc, char *argv[]) {
printf("in pause function\n"); pause(); return 0; }
3. signal(int signum, sighandler_t handler);
一个进程收到一个信号的时候,可以用如下方法进行处理:
- 执行系统默认操作,对大多数信号来说系统默认动作是用来终止该进程
- 忽略此信号
- 执行自定义处理函数,
SIGKILL
和SIGSTOP
不能更改信号的处理方式,因为它们向用户提供了一种使进程终止的可靠方法
#include <stdio.h> #include <signal.h> #include <unistd.h> void signal_handler(int signo) {
if (signo == SIGINT) {
printf("recv SIGINT\n"); } if (signo == SIGQUIT) {
printf("recv SIGQUIT\n"); } } int main(int argc, char *argv[]) {
printf("wait for SIGINT OR SIGQUIT\n"); signal(SIGINT, signal_handler); // SIGINT: Ctrl+c signal(SIGQUIT, signal_handler); // SIGQUIT: Ctrl+\ pause(); pause(); return 0; }
4. int sigqueue(pid_t pid, int sig, const union sigval value);
给指定进程发送信号,与kill相比同时可以传递信息
union sigval {
int sival_int; void *sival_ptr; };
5. int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact );
struct sigaction {
void (*sa_handler)(int signum); /*简单的信号处理函数指针*/ void (*sa_sigaction)(int signum, siginfo_t *info, void *context); /*复杂的信号处理函数指针*/ sigset_t sa_mask; /*信号阻塞集*/ int sa_flags; /*信号处理方式*/ };
sa_handler/sa_sigaction:
信号处理函数指针,根据情况给两者之一赋值:
SIG_IGN
:忽略该信号SIG_DFL
:执行系统默认动作- 处理函数名:自定义信号处理函数
sa_flags = SA_SIGINFO:
使用 sa_sigaction 而不是 sa_handler 作为信号处理函数
// 信号发送 #include <stdio.h> #include <stdlib.h> #include <signal.h> #include <sys/types.h> #include <unistd.h> int main(int argc, char *argv[]) {
pid_t pid; union sigval tmp; pid = atoi(argv[1]); // 发往的进程号 tmp.sival_int = atoi(argv[2]); // 信号携带的数据 sigqueue(pid, SIGINT, tmp); // 发送信号 printf("pid_self = %d, pid_destination = %d\n", getpid(), pid); return 0; } // 信号接收 #include <stdio.h> #include <stdlib.h> #include <signal.h> #include <sys/types.h> #include <unistd.h> void signal_action(int signum, siginfo_t *info, void *ptr) {
printf("signum = %d\n", signum); printf("info->si_pid = %d\n", info->si_pid); // 发送方进程号 printf("info->si_sigval = %d\n", info->si_value.sival_int); // 发送方传递的信息 } int main(int argc, char *argv[]) {
struct sigaction act, oact; act.sa_sigaction = signal_action; //指定信号处理回调函数 sigemptyset(&act.sa_mask); // 阻塞集为空 act.sa_flags = SA_SIGINFO; // 指定调用 sa_sigaction sigaction(SIGINT, &act, &oact); while (1) {
printf("pid_self = %d\n", getpid()); pause(); } return 0; }
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/135400.html