Linux C: 信号及异常和捕捉函数原理
#define SIGHUP 1 | 终端挂起或控制进程终止 |
#define SIGINT 2 | 终端中断(Ctrl+C 组合键) |
#define SIGQUIT 3 | 终端退出(Ctrl+\组合键) |
#define SIGILL 4 | 非法指令 |
#define SIGTRAP 5 | debug 使用,有断点指令产生 |
#define SIGABRT 6 | 由 abort(3)发出的退出指令 |
#define SIGIOT 6 | IOT 指令 |
#define SIGBUS 7 | 总线错误 |
#define SIGFPE 8 | 浮点运算错误 |
#define SIGKILL 9 | 杀死、终止进程 |
#define SIGUSR1 10 | 用户自定义信号 1 |
#define SIGSEGV 11 | 段错误(无效的内存段) |
#define SIGUSR2 12 | 用户自定义信号 2 |
#define SIGPIPE 13 | 向非读管道写入数据 |
#define SIGALRM 14 | 闹钟 |
#define SIGTERM 15 | 软件终止 |
#define SIGSTKFLT 16 | 栈异常 |
#define SIGCHLD 17 | 子进程结束 |
#define SIGCONT 18 | 进程继续 |
#define SIGSTOP 19 | 停止进程的执行,只是暂停 |
#define SIGTSTP 20 | 停止进程的运行(Ctrl+Z 组合键) |
#define SIGTTIN 21 | 后台进程需要从终端读取数据 |
#define SIGTTOU 22 | 后台进程需要向终端写数据 |
#define SIGURG 23 | 有"紧急"数据 |
#define SIGXCPU 24 | 超过 CPU 资源限制 |
#define SIGXFSZ 25 | 文件大小超额 |
#define SIGVTALRM 26 | 虚拟时钟信号 |
#define SIGPROF 27 | 时钟信号描述 |
#define SIGWINCH 28 | 窗口大小改变 |
#define SIGIO 29 | 可以进行输入/输出操作 |
#define SIGPOLL | SIGIO |
#define SIGPWR 30 | 断点重启 |
#define SIGSYS 31 | 非法的系统调用 |
#define SIGUNUSED 32 | 未使用信号 |
转载:「一只青木呀」的原创文章,原文链接:https://blog.csdn.net/weixin_45309916/article/details/111939072
一、信号和中断
信号是进程间通信的重要内容之一。它可以来源于硬件,例如键盘的 Ctrl+C 组合键,间隔定时器,IO错误等硬件错误;也可以是来源于自己,例如自己的代码除0,指针越界等执行报错;其中最需要了解的是来自于其他进程例如 kill命令。信号可以被捕捉从而触发信号处理函数。信号处理函数可以被重写,信号也可以被屏蔽。
在进程结构体PROC 中,都有一个信号处理数组 int sig[32] ; 其中值为0 代表默认处理,1代表忽略,其他非零值表示用户模式下预先设定好的信号处理函数地址。除了信号处理数组每个PROC都有一个32位向量(信号位向量) 和Mask(屏蔽)位向量 。 bits向量用来指明哪些信号被signal , masks 用来指明哪些信号被Block 。当信号位为1时,且屏蔽位为0时,信号才会生效并传递给进程。如果进程发现了个未被阻塞的信号,则会将信号位清0。
二、信号的捕捉和捕捉函数的设置
信号处理内容可以被修改,除了 SIGKILL(9) 和 SIGSTOP(19) 。 为了处理信号捕捉可能造成的死循环,这两个信号9和19作为终止进程的最后手段,规定了不能被修改。
进程可以使用系统调用来修改捕捉到信号时的信号处理函数:
int r = signal (int signal_number , void *handler) ;
但是signal 函数有几个个缺点:
1。如果信号触发频率过快,可能导致下一个信号和信号处理函数重新设置会出现竞态条件。相同的,signal是线程不安全的,可能不适用于多线程。
2. signal不能阻塞其他信号,只能通过sigprocmask()来显示屏蔽或者接触屏蔽信号
3.signal 只能传输一个信号编号,不能够传输关于信号的其他信息
因此,现在大多数都用sigaction() 来代替 signal:
sigaction() 的系统调用和 sigaction 结构体如下:
int sigaction(int sigid ,const struct sigaction *act , struct sigaction *oldact );struct sigaction{
void (*sa_handler)(int);
void (*sa_sigaction)(int , siginfo_t *,void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(int);
}
sa_handler : 指向处理函数的指针
sa_sigaction :另一种方法,指向处理函数的指针 , 外加上了两个额外的参数。其中siginfo_t 接收信号的更多信息。
sa_mask : 在处理函数执行时,设置要阻塞的信号
sa_flags ; 设置信号处理过程的行为,如果用sa_sigaction处理函数,sa_flags 需设置为 SA_SIGINFO.
sigaction:的示例:
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
void handler (int sig ,siginfo_t *siginfo , void * context){printf("handler:sig = %d from PID=%d UID=%d \n",sig,siginfo->si_pid,siginfo->si_uid);
}int main(int argc, char * argv[]){struct sigaction act ;memset(&act ,0 ,sizeof(act));act.sa_sigaction = &handler ;act.sa_flags =SA_SIGINFO ;sigaction(SIGTERM,&act ,NULL);printf("looping\n");printf("enter kill PID=%d to send SIGTERM signal to it \n" , getpid());while(1){sleep(10);}
}
上面的代码利用sigaction 重新设置SIGTERM (15) 信号,当收到 15信号时就会执行 handler内容。开启另一个会话对进程发出kill命令,则会有上面的输出结果。最后发出的8信号对应是浮点异常信号,虽然上述程序并不会出现浮点异常,但是由于程序收到了该信号,就执行默认的信号8处理函数了.
三、利用sigaction和管道实现消息IPC
Linux 管道和和文件描述符的相关内容:可看
https://blog.csdn.net/superSmart_Dong/article/details/118641774
/****sigaction*****/
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>#define LEN 64
int ppipe[2]; //管道-文件描述符
int pid ;
char line[LEN];
int parent(){printf("parent %d running \n",getpid());close(ppipe[0]); // 关闭标准输入文件描述符while(1){printf("parent %d : input a line : \n" ,getpid());fgets(line ,LEN,stdin); // line[LEN]得到标准输入line[strlen(line) -1 ] = 0 ;printf("parent %d write to pipe",getpid());write(ppipe[1],line,LEN); //向管道写入内容printf("parent %d send signal 10 to %d",getpid(),pid);kill(pid,SIGUSR1);}
}
void chandler(int sig){printf ("\n child %d got an interrupt sig=%d \n ",getpid(),sig);read(ppipe[0] ,line ,LEN); //向管道读出内容 printf("child %d get a message = %s \n" ,getpid(),line);
}
int child(){char msg[LEN];int parent =getppid();printf("child %d running \n",getpid());close(ppipe[1]);signal(SIGUSR1,chandler);while(1);
}
int main(int argc, char * argv[]){pipe(ppipe);pid = fork();if (pid){parent();}else{child();}
}
Linux C: 信号及异常和捕捉函数原理相关推荐
- linux 与信号集操作相关的函数
与信号集操作相关的函数 #include <signal.h> 清空信号集 全都为0 int sigemptyset(sigset_t *set);填充信号集 全都为1 int sigfi ...
- linux SIGCHLD信号
SIGCHLD的产生条件 子进程终止时 子进程接收到SIGSTOP信号停止时 子进程处在停止态,接受到SIGCONT后唤醒时 借助SIGCHLD信号回收子进程 子进程结束运行,其父进程会收到SIGCH ...
- linux操作系统信号捕捉函数之回调函数小结
(1)signal 信号捕捉函数:注册一个信号捕捉函数(不参与捕捉,那是内核的事情) 函数实现: typedef void(*sighandler_t)(int); //声明了一个函数指针(代 ...
- linux操作系统信号捕捉函数之sigaction用法小结
(1)sigaction函数:注册一个信号捕捉函数(不参与捕捉信号,信号由内核捕捉),并修改原来的信号处理动作 (2)函数原型及头文件 头文件:#include<signal.h> 函数原 ...
- Linux进程信号(产生、保存、处理)/可重入函数概念/volatile理解/SIGCHLD信号
首先区分一下Linux信号跟进程间通信中的信号量,它们的关系就犹如老婆跟老婆饼一样,没有一毛钱的关系. 信号的概念 信号的概念:信号是进程之间事件异步通知的一种方式,属于软中断.比如:红绿灯是一种信号 ...
- Linux 进程信号:信号的概念、生命周期、产生流程、阻塞
信号的概念 信号的生命周期 信号的阻塞 信号的概念 信号 信号是一个软中断.操作系统通过信号通知某个进程发生了某件事件,然后中断这个进程当前操作,让它优先去处理这个事件. 我们在linux下常用的ki ...
- Linux Signal信号详解
信号是Linux编程中非常重要的部分,本文将详细介绍信号机制的基本概念.Linux对信号机制的大致实现方法.如何使用信号,以及有关信号的几个系统调用. 信号机制是进程之间相互传递消息的一种方法,信号全 ...
- Linux C 信号使用
文章目录 1.信号的基本概念 2.两个信号捕获函数 2.1.signal信号函数 2.2.sigaction函数 2.3.信号相关函数 3.两个时钟函数 3.1.alarm函数 3.2.setitim ...
- 【Linux】第八讲:Linux进程信号详解(一)_ 认识信号 | 产生信号
「前言」文章是关于Linux进程信号方面的知识,本文的内容是Linux进程信号第一讲,讲解会比较细,下面开始! 「归属专栏」Linux系统编程 「笔者」枫叶先生(fy) 「座右铭」前行路上修真我 「枫 ...
最新文章
- 动态获得资源的路径大小写问题
- ggplot01:R语言坐标轴离散、连续与图例离散连续的区分
- [YTU]_2626( B 统计程序设计基础课程学生的平均成绩)
- fileinput 图片上传
- Error:java: 无效的标记 -version 编译错误的解决办法
- object 构造器java_“java”中为什么“Object”类要有一个空的构造函数?
- flask模型中【外键】relationship的使用笔记
- 也许现在的前端,应该了解更多的算法
- docker ubuntu16安装
- [转载] 【数据处理】 python 极速极简画图——频数(率)分布直方图
- [FAQ03776] [Power]关于RTC唤醒系统问题
- Python-人脸识别并判断表情 笑脸或非笑脸 使用笑脸数据集genki4k
- 管理小故事100例3
- storm 阿姆歌曲_Eminem经典歌词
- 解决layui form组件使用botton按钮提交页面自动刷新问题
- 最全Pycharm教程(3)——代码的调试、运行
- 模型优化与tensorflow
- Java篇第七回——内部类与异常类
- 练习题记录:求解距离矩阵,首先生成一百个二维坐标点,计算任意两个坐标点的距离
- 浪潮服务器自研芯片,5G、AI高度融合发展,浪潮服务器满足各种AI场景应用需求...