Unix进程通信:信号

信号原理

  • 信号机制:事件促使内核向进程发送信号
  • 事件类型:
    • 键盘按键请求内核产生信号:ctrl+c、ctrl+/等
    • 进程执行出错时,如越界访问,0做除数,整形溢出。内核给进程发信号
    • 一个进程调用kill给另一个进程发信号。
  • 信号机制过程
    信号未决(信号处理之前的状态):事件产生->内核发送信号给指定进程->信号注册(信号进PCB)
    信号递送(信号处理动作):信号被屏蔽/若未被屏蔽,信号从PCB注销->信号处理
  • 信号处理方式
    • 按默认方式处理:man 7 signal可以查看每个信号的默认处理方式
    • 忽略信号,SIGKILL和SIGSTOP不能被忽略
    • 捕捉信号,作出反应
  • 可用于进程间使用信号通信
  • 异步通信机制(约定信号处理机制)
  • shell中用 kill -l 查看信号


  • 信号分类
    • 小于32号为不可靠信号,不支持信号队列。后面为可靠信号,支持信号队列
    • 同步信号:本进程操作产生的信号。异步信号:进程之外的事件引发的信号。
  • 信号的意义见官方信号表
    http://man7.org/linux/man-pages/man7/signal.7.html
    也可在终端输入man 7 signal查看信号详细信息和默认处理方式

信号处理函数API

include <signal.h>
__sighandler_t signal(int signum,__sighandler_t handler)

参数表:
signum:要处理的信号
handler:信号处理函数

  • __sighandler_t的定义:typedef void (*__sighandler_t)(int);
    函数指针:返回值为void,有一个类型为int的参数
    此参数对应三种不同的应对
    • SIG_IGN:忽略
    • SIG_DFL:默认
    • 函数名:用户自己定义的反应函数

返回值:
不为-1:成功
SIG_ERR:出错
示例代码:

#include <signal.h>
#include <stdlib.h>//perror,exit()
#include <unistd.h>//fork(),pause()
#include <sys/wait.h>//wait()
#include <iostream>
using namespace std;
 
void fun(int signal)
{
    cout << "process:"<<getpid()<<"have captured the signal " << endl;
}

int  main()
{
    int pid;
    if( ( pid = fork() ) == -1 )
    {
        perror("fork");
        exit(1);    
    }       

    else if(pid == 0)//son process
    {
        signal(SIGINT,fun);
        //SIGINT:signal from keyboard
        //约定信号处理函数
        
        cout << "waiting for signal" << endl;       
        pause();//挂起等待信号
    }
    else//parent process
    {
        sleep(1);
        kill(pid,SIGINT);//发送信号
        wait(NULL);
    }
}

也可发送信号10(用户自定义信号)来进行进程通信

signal函数存在的问题

  • 信号处理不可靠
    处理结束后需要再次设置监听,所以常用此结构
    void handler(int signo)
    {
      signal(SIGINT,handler);
    ...
    }
    
    这种结构在相应处理完信号到重设监听状态有一段危险时间(虽然很短)
  • 不方便获取当前信号处理方式
  • 无法处理多个信号--无法阻塞信号

其他信号相关api(待更新)

  • sigaction:
    int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
    • 当act为空,oldact非空:获取signum当前的处理方式
    • 当act非空,oldact为空:安装信号处理函数
    • sigaction结构体
struct sigaction {
    void (*sa_handler)(int);//信号处理函数句柄,不带参数
    void (*sa_sigaction)(int, siginfo_t *, void *);//信号处理函数句柄,带参数
    sigset_t sa_mask;//响应信号:哪些信号可以阻塞等待执行
    int sa_flags;//设置是否在信号响应后恢复对信号的默认处理
    void (*sa_restorer)(void);
}

一个小例子
通过argv来传送pid和signum
发送端

#include <signal.h>
#include <sys/time.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>

void main(int argc,char**argv)
{
        pid_t pid;
        pid=(pid_t)atoi(argv[1]);
        int signum;
    signum = atoi(argv[2]);
        union sigval mysigval;
        if(kill(pid,signum)==-1)
                printf("send error\n");
        sleep(2);
}

接收端

#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>//atoi
void new_op(int signum)
{
        printf("recieve signumm %d\n",signum);
}

int main(int argc,char**argv)
{
        struct sigaction act;
        sigemptyset(&act.sa_mask);
        act.sa_handler=new_op;
        act.sa_flags=SA_RESETHAND;
        if(sigaction(30,&act,NULL)<0)
        {
                printf("install sigal error\n");
        }
        pid_t pid;         
        pid=getpid();
    printf("pid : %d\n",pid);
    sleep(10);
}
image.png
  • kill:发送信号
  • raise:给自己发信号
  • alarm:计时器
  • pause:挂起(等信号)(pause+alarm = sleep):
  • sigqueue:可以在发信号的时候传参
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,384评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,845评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,148评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,640评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,731评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,712评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,703评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,473评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,915评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,227评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,384评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,063评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,706评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,302评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,531评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,321评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,248评论 2 352

推荐阅读更多精彩内容

  • 进程之间可以通过信号传递信息,信号是一种软中断机制,通过信号用来通知进程发生了异步事件。进程之间可以互相通过系统调...
    lintong阅读 410评论 0 2
  • 概述 Linux 在进程间通信时,有时候需要用到异步通讯方式,而信号机制是Linux系统本身提供的一种异步通讯. ...
    大风qixi阅读 1,899评论 0 4
  • 对于 Linux来说,实际信号是软中断,许多重要的程序都需要处理信号。信号,为 Linux 提供了一种处理异步事件...
    故事狗阅读 84,880评论 2 62
  • 使用场景:1、为了并发,中断处理其它事件,1、进程间通信1、中断中止(注意不是终止)当前正在执行的程序,转而执行其...
    奥斯特洛司机阅读 691评论 0 0
  • 读完梁校的《拥抱梦想,心向光明远方》,印象特别深刻的是,最好的投资是投资一个人的思想,改变一个人的价值取向,思想都...
    prettycool阅读 281评论 0 0