signal_pending(3) — The event API

1. signal_pending( current )的作用

仅检查当前进程是否有信号处理(不会在这里处理信号),返回不为0表示有信号需要处理

1.1. 两个信号的概念

signal pending:指在信号被处理之前生成信号的状态,是信号生成和信号消除的中间状态
signal blocking:指阻塞正在处理的信号,这是一种信号处理方法

2. 常规使用场景

 if (signal_pending(current)) {ret = -ERESTARTSYS;return ret;}

signal_pending(current)检查到当前进程有信号需要处理时,退出当前的系统调用,并返回"-ERESTARTSYS";然后便会进入对应的Signal处理函数。
"-ERESTARTSYS"表示信号函数处理完毕后重新执行之前的那个系统调用(如果Signal处理函数之前有系统调用的话)。

3. 情景分析

当一个系统调用处于睡眠状态时(如:等待输入缓冲区不为空),如果此时产生信号,这个信号仅在thread_info结构中标识以下,即所谓"发信号";
"发信号"动作会唤醒系统调用,系调调用便会执行signal_pending(current)检测是否有信号,如果有信号则系统调用返回-ERESTARTSYS,在从系统调用的返回用户空间后,会根据thread_info中信号标识位调用相应的Signal处理函数,这里就是所谓的“接收信号”;
Signal信号函数处理完成后,上层库函数会根据系统调用的ERESTARTSYS返回值重启该系统调用,重启的系统调用会再次检查缓冲区:为空,说明刚才的信号不是缓冲区有数据了的信号,继续等待,重复刚才的过程;不为空,就可以直接处理数据,系统调用正常结束,最后返回用户空间的应用程序。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CKEWdp00-1607526956110)(https://www.programmersought.com/images/355/4c97b4155d2f61758a00b981fec7160b.JPEG)]
Processing process:
When the program is running in user mode -> the process enters the kernel due to a system call or interruption -> turns to the user mode to execute the signal processing function -> enters the kernel after the signal processing function is completed -> returns to the user mode to continue executing the program

First, the program is executed in user mode. On the eve of the process falling into the kernel and returning from the kernel, it will check whether the signal has not been processed, and if it has and is not blocked, it will call the corresponding signal handler to process it. First, the kernel creates a layer on the user stack, in which the return address is set to the address of the signal processing function, so that when the kernel returns to the user mode, the signal processing function will be executed. When the signal processing function is executed, it will enter the kernel again, mainly to detect whether there is a signal that has not been processed, and to restore the original program interrupt execution point, restore the kernel stack, etc., so that when returning from the kernel, it will return to the original program execution place Up

4. 检测进程p是否有待处理的信号的代码

static inline int signal_pending(struct task_struct *p) {return unlikely(test_tsk_thread_flag(p, TIF_SIGPENDING)); // p->thread_info->flags中TIF_SIGPENDING位是否置位
}
#define TIF_SIGPENDING          2   static inline int test_tsk_thread_flag(struct task_struct *tsk, int flag) {return test_ti_thread_flag(task_thread_info(tsk), flag);
}static inline int test_ti_thread_flag(struct thread_info *ti, int flag) {  return test_bit(flag, &ti->flags);
}static inline int test_bit(int nr, const volatile void * addr) {  return (1UL &(((const int *) addr)[nr >> 5] >>(nr & 31) )) != 0UL; // 检测addr的第nr位是否为1(addr右起最低位为第0位)

5. Signal operation 信号操作实验

#include<stdio.h>
#include<signal.h>
#include<unistd.h>/** Add the signal SIGINT to the signal set, set the signal set to a blocked signal set, get the pending signal set, and print it out. When you enter Ctrl+C, you can find that the pending signal set has changed.** in conclusion:** If a signal is blocked by the process, it will not be passed to the process, but it will stay in the pending state.When the signal is blocked, The signal will be processed immediately.*/
// Block a signal, print the pending signal set
void printsigset(sigset_t *set)
{int i = 0;for(;i<32;i++){if(sigismember(set,i)) //Determine whether the specified signal is in the target setputchar('1');elseputchar('0');}puts("");
}int main()
{sigset_t s,p; //Define the signal set object, and clear the initialization, sigset_t 128bytessigemptyset(&s);sigaddset(&s,SIGINT); //Add signal to the signal set, SIGINT是 ctrl+c发出的信号sigprocmask(SIG_BLOCK,&s,NULL); //Set blocking signal set, SIGINT信号被阻挡后ctrl+c是无法停止程序的while(1) {sigpending(&p); //Get pending signal setprintsigset(&p);sleep(1);}return 0;
}
int sigemptyset(sigset_t *set);//Initialize the signal set pointed to by set, and clear the corresponding bits of all signals, indicating that the signal set does not contain any valid signals
int sigfillset(sigset_t *set);//Initialize the signal set pointed to by set and set the corresponding bits of all signals, indicating that the effective signal of the signal machine includes all the signals supported by the system.
int sigaddset(sigset_t *set,int signo);//Add some kind of valid signal to the signal set.
int sigdelset(sigset_t *set,int signo);//Delete a valid signal in the signal set
int sigismemeber(sigset_t* set,int signo);//It is a Boolean function, used to determine whether a signal set contains a certain signal, if it contains a thief, it returns 1, if it does not, it returns 0, and it returns -1 on error
int sigprocmask(int how,const sigset_t*set,sigset_t *oset);//Read or change the signal shielding word (blocking signal set) of the process, if successful, return 0, fail, return -1
int sigpending(sigset_t *set);//Read the pending signal set of the current process and pass it through the set parameter. If the call is successful, it returns 0, and if it fails, it returns -1.

6. linux kernel对ERESTARTSYS等返回值的处理

If a process is blocked on a system call it is put on a waitqueue in the TASK_INTERRUPTIBLE or TASK_UNINTERRUPTIBLE state. In the former case, upon receiving a signal, the kernel puts it back in the TASK_RUNNING state, adds the process to the runqueue and adds the signal to the list of pending signals.

When the process is scheduled, it continues the execution of the system call. Since the syscall was not completed, the possible return codes are:

EINTR
ERESTARTNOHAND
ERESTART_RESTARTBLOCK
ERESTARTSYS
ERESTARTNOINTR
On the exit path from the system call, the pending signals are checked. In this case, your SIG_ALRM handler is called and immediately afterwards the kernel checks the return code of the system call. In general, the following cases may occur:

Return code is EINTR: the user mode process is resumed and the return value of read will be exactly -EINTR
Return code is ERESTARTNOINTR: the system call is reexecuted
Return code is ERESTARTSYS: system call is reexecuted if SA_RESTART flag is set, otherwise -EINTR is returned to userspace.
Return code is ERESTARTNOHAND or ERESTART_RESTARTBLOCK: usermode process is resumed and -EINTR returned.
Reexecuting a system call means that the process EIP is decremented by 2 and it is therefore forced to execute again int 0x80.

参考资料

Flaw in calling read with a timeout
Analysis of Linux signal mechanism
wiki Signal
signal(7)

linux的signal_pending及signal相关推荐

  1. linux c之信号signal处理机制

    最近同事的程序设计过程中用到了Linux的signal机制,从而引发了我对Linux中signal机制的思考.Signal机制在Linux中是一个非常常用的进程间通信机制,很多人在使用的时候不会考虑该 ...

  2. Linux异步之信号(signal)机制分析

    From:http://www.cnblogs.com/hoys/archive/2012/08/19/2646377.html From:http://kenby.iteye.com/blog/11 ...

  3. Linux命令kill和signal

    kill命令用于终止指定的进程(terminate a process),是Unix/Linux下进程管理的常用命令.通常,我们在需要终止某个或某些进程时,先使用ps/pidof/pstree/top ...

  4. 【Linux实验】调用signal()函数来执行信号处理函数

    实验: 相当于检测 CRTL+C 输入了多少次 以下前提都建立在安装了vim和gcc编译器的条件下,如果没有安装可看[Linux写C语言程序]来安装 这是我们要用到的代码,可以自行阅读理解一下 #in ...

  5. linux的一些机制Signal, Fork,

    signal(SIGCHLD, SignalHandler); 注册软中断,对应的api close(socket); ret=fork(): 父进程,返回子进程的pid. 子进程返回0, 出错返回& ...

  6. linux的基础知识——signal信号捕捉,信号集操作函数

    文章目录 1.signal捕捉信号 2.信号集操作函数 3.sigprocmask函数 4.sigpending函数 5.例子1:打印某个进程未决信号集 6.例子2:signal函数的注册捕捉执行函数 ...

  7. signal 11 linux,关于运行时Signal 11 Caught的错误

    我的程序在ubuntu7.10下运行的时候,有时候会出现如下的问题,但不是每次都出现,请问有编程经验的大牛能否指点一二,谢谢了 P2SP-SVCHOST: Signal 11 Caught. P2SP ...

  8. Linux c 中alarm,signal,pause的使用说明

    直接看代码 #include <unistd.h> #include <stdio.h> #include <signal.h> void myfunc() { p ...

  9. linux signal 处理

    linux signal 处理 说明: 本文主要翻译自ULK 3rd chapter 11. 主要受 http://blog.csdn.net/yunsongice 影响,故发表在csdn. 另外,本 ...

最新文章

  1. C++ 莫队算法(转)
  2. Java Review - 并发编程_ThreadLocalRandom实现原理源码分析
  3. pci中断号分配_西门子S7-200 SMART中断及中断指令概述
  4. 【Python】/ 和 // 的区别
  5. sql limit 子句_Java 8流中的常见SQL子句及其等效项
  6. android+使用bmob冲突,bmob开发android遇到的问题
  7. 抓到的一次suse11 xen用libvirt连接的错误
  8. ABP源码分析四十:ZERO的Application和Tenant
  9. authorware学习
  10. tcl语言读取文件一行_TCL语言(九) 路径和文件
  11. Oracle 12C 最新 PSU 补丁下载与安装操作指北
  12. 【云计算】阿里云-pyodps处理指南
  13. 请给孩子多一点点空间
  14. Something about ...
  15. 我在CSDN的2021--一次没有专栏的写在尾声
  16. 前端程序员成长的记录及被某IT外包公司套路的经历
  17. 5G究竟如何改变我们的生活?三大特性和八大应用场景
  18. (八)苏世民:我的经验和教训:决策(567)
  19. Vscode中搜索字符串失败,报错“Spawn ${path}\ressources\app\node_module.asar.unpacked\vs-code-ripgrep\bin\rg.exe“
  20. 联想小新padpro怎么样?测评值得买吗?详细性能点评

热门文章

  1. python跳转下一页_在selenium python中访问下一页上的元素
  2. 编译libevent
  3. 状态估计2(卡尔曼滤波)
  4. vb 修改sql数据库服务器时间格式,博途使用小结:用VB脚本向SQL数据库中写数据的方法...
  5. Python爬虫之豆瓣电影评论数据的爬取(十四)
  6. 数字输入框不能输入小数
  7. Linux终端设置成256色模式
  8. EasyExcel复杂表头导入(一对多)
  9. 小心 SQL 中的空值陷阱!
  10. html类选择器和id选择器,CSS Id 和 Class选择器