signal 使用介绍

signal 使用介绍本文深入介绍了 Linux 信号机制 包括信号的基本概念 产生方式和常用函数

大家好,欢迎来到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);

一个进程收到一个信号的时候,可以用如下方法进行处理:

  • 执行系统默认操作,对大多数信号来说系统默认动作是用来终止该进程
  • 忽略此信号
  • 执行自定义处理函数,SIGKILLSIGSTOP 不能更改信号的处理方式,因为它们向用户提供了一种使进程终止的可靠方法
#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

(0)
上一篇 2025-07-04 22:20
下一篇 2025-07-04 22:26

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信