1.什么是信号?

信号是 Linux 进程间通信的最古老的方式。信号是软件中断,它是在软件层次上对中断机制的一种模拟,是一种异步通信的方式 。信号可以导致一个正在运行的进程被另一个正在运行的异步进程中断,转而处理某一个突发事件。
信号可以直接进行用户空间进程和内核空间进程的交互,内核进程可以利用它来通知用户空间进程发生了哪些系统事件。
一个完整的信号周期包括三个部分:信号的产生,信号在进程中的注册,信号在进程中的注销,执行信号处理函数。如下图所示:

2. 信号术语

(1)信号相关术语
为了表示清楚,这里总结关于信号的一些术语
递达(Delivery):进程执行信号的处理动作
信号未决(Pending):信号从产生到递达之间的状态
阻塞(Block):进程可以选择对信号进行阻塞,被阻塞的信号产生时将保持在未决状态,知道进程解除对此信号的阻塞,才会执行递达动作
需要注意区分阻塞和忽略,递达有三种可选动作——忽略,执行默认,自定义捕捉,所以忽略是也就是递达了,但是阻塞是保持在了未决
(2)信号在内核中的表示
操作系统对进程发送信号的动作改变标记位置,其实每个信号都有两个标志位分别表示阻塞和未决,还有一个函数指针来表示处理的动作,如下

大家可以看到,从1号信号(SIGHUP)开始,每个信号都对应block位图,pending位图和handler数组(它是一个函数指针数组,每个函数指针指向一个函数,表示处理的动作)的一位或下标。一旦信号产生,进程的task_struct中的pending位图中的第三个位置为1,此时信号处于未决状态还没有递达,一旦信号递达,操作系统就会将该标志位置为0。而block位图中,一旦把第n位设置为了1,表示n号信号被阻塞,需要注意的是无论这个信号是否产生,它都可以被阻塞。

SIGHUP信号产生过,也未被阻塞,所以当此信号递达时将会执行默认动作
SIGINT信号产生过,但是正在被阻塞,所以暂时无法递达,它的处理动作是忽略,但是在没有接触阻塞之前是不能忽略这个信号的,因为进程仍然有机会改变处理动作再接触阻塞
SIGQUIT信号没有产生过,一旦产生就会被阻塞,它的处理动作是用户自定义的一个函数

3.信号集操作函数

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
/*
int sigprocmask(int how,const sigset_t* set,sigset_t* oset);
how set
SIG_BLOCK   set包含了我们希望添加到当前信号屏蔽字的信号
SIG_UNBLOCK set包含了我们希望添加到当前信号屏蔽字中解除阻塞的信号
SIG_SETMASK(常用)   设置当前信号屏蔽字为set所指的值
参数oset如果不设置为NULL,由于此函数会更改当前的信号屏蔽字,所以会在更改之前将此时的信号屏蔽字备份一份到oset所指的变量中*/void print_pending(sigset_t* pending)
{int i=1;for(i=1;i<=31;i++){if(sigismember(pending,i)){printf("1");//只要i信号存在,就打印1}else {printf("0");//不存在这个信号就打印0}}printf("\n");
}int main()
{signal(2,handler);    //信号捕捉函数sigset_t pending;     //定义信号集变量sigset_t block,oblock;//定义阻塞信号集变量sigemptyset(&block);sigemptyset(&oblock);//初始化阻塞信号集sigaddset(&block,2); //将2号信号添加的信号集sigprocmask(SIG_SETMASK,&block,&oblock);//设置屏蔽关键字int cnt = 0; while(1){sigemptyset(&pending);  //初始化信号集sigpending(&pending);   //读取未决信号集,传入pendingprint_pending(&pending);//定义一个函数,打印未决信号集sleep(1);cnt++;if(10 == cnt) //10s后解除阻塞{printf("解除阻塞\n");sigprocmask(SIG_SETMASK,&oblock,NULL);}}
}

4.信号捕捉过程


会进入两个不同的流程,用户态与内核态之间的切换

如果信号的处理动作是用户自定义函数,所以内核决定返回用户态时就会去指定自定义函数,而这个自定义函数和原先的main函数使用的是不同的堆栈空间,所以他们之间不存在调用和被调用的关系,是两个独立的控制流程,而一个进程可以有多个控制流程——线程

5. 信号的产生举例

/***********************************************************************
信号产生
1.coredump产生信号
2.kill
3.raise
4.abort
5.由软件定时器产生 SIGALRM
6. 硬件异常产生
7. 等待信号
************************************************************************/

//1.coredump产生信号
#include<stdio.h>
#include<unistd.h>
int main(){int arr[10]={0};for(int index = 0; index < 20 ; index ++){arr[index] = index;}printf("for test");return 0;
}//2.kill
#include<stdio.h>
#include<unistd.h>
#include<signal.h>
#include<sys/types.h>
#include<sys/wait.h>
int main()
{pid_t pid;int status;if(!(pid = fork())){printf("Hi I am child process!\n");sleep(10);return 0;}else{printf("send signal to child process (%d) \n",pid);sleep(1);kill(pid ,SIGABRT); //给pid所指的进程发送SIGABRT(中止一个程序)信号wait(&status);if(WIFSIGNALED(status))printf("chile process receive signal %d\n",WTERMSIG(status));}return 0;
}//3.raise
#include<stdio.h>
#include<unistd.h>
#include<signal.h>
#include<sys/types.h>
#include<sys/wait.h>
#include <stdlib.h>
int main(int argc,char* argv[])
{if(argc==2)//保证传入参数正确{raise(atoi(argv[1]));//将信号值传入}while(1){printf("I Am runnng now...\n");sleep(1);}return 0;
}
ubuntu@VM-0-17-ubuntu:~/linuxTest/sys_linux/csdn$ kill -l1) SIGHUP  2) SIGINT   3) SIGQUIT  4) SIGILL   5) SIGTRAP6) SIGABRT    7) SIGBUS   8) SIGFPE   9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG  24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF 28) SIGWINCH    29) SIGIO   30) SIGPWR
31) SIGSYS  34) SIGRTMIN    35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10    45) SIGRTMIN+11    46) SIGRTMIN+12    47) SIGRTMIN+13
48) SIGRTMIN+14    49) SIGRTMIN+15    50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX
ubuntu@VM-0-17-ubuntu:~/linuxTest/sys_linux/csdn$ ./signal_appear 1
Hangup
ubuntu@VM-0-17-ubuntu:~/linuxTest/sys_linux/csdn$ ./signal_appear 2ubuntu@VM-0-17-ubuntu:~/linuxTest/sys_linux/csdn$ ./signal_appear 3
Quit (core dumped)
ubuntu@VM-0-17-ubuntu:~/linuxTest/sys_linux/csdn$ ./signal_appear 4
Illegal instruction (core dumped)
ubuntu@VM-0-17-ubuntu:~/linuxTest/sys_linux/csdn$ ./signal_appear 5
Trace/breakpoint trap (core dumped)//4.abort
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
void handler(int sig)
{printf("catch a sin : %d\n",sig);}int main(int argc,char* argv[])
{signal(6,handler);//捕捉6号信号abort();//异常终止while(1){printf("I Am runnng now...\n");sleep(1);}return 0;}//5.由软件定时器产生  SIGALRM
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
int ms = 0;
int main()
{alarm(10);//10s后结束while(1){ms++;printf("ms:%d\n",ms);}return 0;
}//6. 硬件异常产生
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>void handler(int sig)
{printf("catch a sin : %d\n",sig);exit(1);
}int main()
{signal(11,handler);sleep(2);int* p = NULL;*p = 10;//空指针访问return 0;
}
//7. 等待信号
//没有产生信号前,进程一直阻塞在 pause() 不会往下执行,假如,我们按“Ctrl+c”,pause() 会捕获到此信号,中断当前进程
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>int main(int argc, char *argv[])
{    printf("in pause function\n");    pause();    return 0;
}

6. signal - sigaction


#include <signal.h>
#include <stdio.h>
#include <unistd.h>void action(int sig)
{printf("oh, got a signal %d\n", sig);int i = 0;for (i = 0; i < 5; i++){printf("signal func %d\n", i);sleep(1);}
}int main()
{struct sigaction act;act.sa_handler = action;sigemptyset(&act.sa_mask);sigaddset(&act.sa_mask, SIGQUIT);// act.sa_flags = SA_RESETHAND;// act.sa_flags = SA_NODEFER;act.sa_flags = 0;sigaction(SIGINT, &act, 0);struct sigaction act_new;act_new.sa_handler = action;sigemptyset(&act_new.sa_mask);act.sa_flags = 0;sigaction(SIGQUIT, &act_new, 0);while(1){sleep(1);printf("main thread is running \n");}return;}

Linux系统编程 -- 进程 信号相关推荐

  1. linux系统发送信号的系统调用是,linux系统编程之信号:信号发送函数sigqueue和信号安装函数sigaction...

    信号发送函数sigqueue和信号安装函数sigaction sigaction函数用于改变进程接收到特定信号后的行为. sigqueue()是比较新的发送信号系统调用,主要是针对实时信号提出的(当然 ...

  2. Linux 系统编程 -进程概念篇

    Linux系统编程-进程篇 冯诺依曼体系结构 冯诺依曼的两个重要思想 当代计算机的三级缓存 操作系统 操作系统的概念 操作系统的组成 操作系统作用 Linux下的操作系统体系 进程 进程概念 进程特性 ...

  3. Linux系统编程——进程基础知识

    Linux系统编程--进程基础知识 1.程序和进程 程序,是指编译好的二进制文件,在磁盘上,不占用系统资源(cpu.内存.打开的文件.设备.锁-) 进程,是一个抽象的概念,与操作系统原理联系紧密.进程 ...

  4. 【Linux系统编程】信号 (下)

    00. 目录 文章目录 00. 目录 01. 信号集 02. 信号阻塞集 03. sigaction函数 04. 附录 01. 信号集 为了方便对多个信号进行处理,一个用户进程常常需要对多个信号做出处 ...

  5. 【Linux系统编程】信号 (上)

    00. 目录 文章目录 00. 目录 01. 信号概述 02. 信号编号 03. 信号产生方式 04. kill发送信号 05. pause等待信号 06. 信号处理方式 07. 信号处理函数 08. ...

  6. Linux系统编程——进程

    一.进程概念 基础 程序:死的.只占用磁盘空间. --剧本 进程:活的.运行起来的程序.占用内存,cpu等系统资源. --戏 并发 并发的出现基于CPU的发展.然后有了多道程序设计(多进程并发执行). ...

  7. linux系统编程之信号(一):信号基本概述

    一.为了理解信号,先从我们最熟悉的场景说起: 1. 用户输入命令,在Shell下启动一个前台进程. 2. 用户按下Ctrl-C,这个键盘输入产生一个硬件中断. 3. 如果CPU当前正在执行这个进程的代 ...

  8. Linux系统编程 进程控制

    文章目录 01. 学习目标 02. 进程和程序 (理解) 03. 单道.多道程序设计(了解) 3.1 单道程序设计 3.2 多道程序设计 04. 并行和并发(理解) 05. MMU(了解) 06. 进 ...

  9. linux系统编程之信号(四):信号的捕捉与sigaction函数

    一.内核如何实现信号的捕捉 如果信号的处理动作是用户自定义函数,在信号递达时就调用这个函数,这称为捕捉信号.由于信号处理函数的代码是在用户空间的,处理过程比较复杂,举例如下: 1. 用户程序注册了SI ...

  10. Linux系统编程(二)–信号

    文章目录 1 Hello signal 1.1 hello signal 程序 1.2 向 hello signal 发信号 1.3 招待你的"客人" 1.3.1 signal 函 ...

最新文章

  1. 中国储能变流器(PCS)产业投资可行性与发展潜力分析报告2022-2028年版
  2. cocos2d-x 中菜单类
  3. liferay 去掉 portlet:actionUrl 跳转时的message
  4. 技术人必备的学习工具
  5. 航海王燃烧意志如何修改服务器,航海王燃烧意志自动战斗设置攻略 航海王燃烧意志自动战斗设置方法...
  6. springboot毕设项目作业查重系统i667s(java+VUE+Mybatis+Maven+Mysql)
  7. MATLAB学习八(二):标准差std
  8. 支付宝手机网站H5支付
  9. Python学习之路-爬虫(四大名著)
  10. html改变鼠标指针形状代码,改变鼠标指针形状_js改变鼠标形状与样式的方法
  11. 关于VS运行时出现错误cannot decrement string iterator before begin
  12. 级联rc滤波_了解无源RC滤波器,看完这篇你就懂了(二)
  13. HEVC解码器HM源码阅读(一)介绍
  14. nginx完全卸载删除
  15. ​做让用户安心合规的智能家居产品——智能家庭用户个人信息保护方案
  16. STC89C52RC40I-LQFP44简介
  17. 原生HTML+CSS+JS制作自己的导航主页(前端大作业,源码+步骤详解)
  18. SpringMVC重定向与请求转发
  19. matlab火炮射击问题_15个快速射击前端面试问题
  20. 2020届毕业生秋招 算法岗(偏NLP)总结

热门文章

  1. Android GSON解析JSON数据
  2. 7-6 逆序的三位数 (10 分)
  3. Linux下c编程设置串口属性和读写串口操作说明总结
  4. string的一些基本操作和骚操作
  5. 谷歌推出一款72个量子比特的通用量子计算机
  6. modelsim+win环境下systemverilog调用c函数
  7. Kubernetes详解(六)——Pod对象部署和应用
  8. Tomcat详解(五)——jforum论坛部署实战
  9. 解决Ubuntu18.04下VLC打不开的问题
  10. 斯坦福22岁辍学少年的独角兽野心:准备颠覆硅基无人车激光雷达