Linux系统编程之进程间通信___2.信号通信

一.信号通信

引入:管道通信的框架

信号通信框架
kill -l显示64种信号

思考:
A让内核发送信号给B
1.A需要告诉内核发给谁
2.A需要告诉内核发送什么信号给B?

$ 信号通信的框架

  1. 信号的发送(发送信号进程,信号的发送相关的函数)kill alarm raise函数;其实就是A发送信号给内核对象
  2. 信号的接收(接收信号进程)pause sleep while();其实就是B接收内核发送的信号
  3. 信号的处理;其实就是B接收到内核的信号之后怎么处理
1.信号的发送
(1)kill

kill函数是系统调用函数。
作用:给指定进程发送指定信号。(不一定会杀死进程,取决于发送的是什么信号)
kill函数
利用kill函数可以实现kill命令。


补充知识:kill命令
Kill命令其实是用来发送信号的,我们常用的Kill -9 pid只是给某个进程发送9号信号而已,而不是说杀死该进程。
kill 9 5741
9(必杀信号)是信号类型 ,5741是test的PID号
将必杀信号发送给5741,会导致杀死5741进程
kill使用过程


(2)raise:发信号给自己 ==kill(getpid() , sig)

raise函数

eg:
#include "stdio.h"
#include "unistd.h"
#include "stdlib.h"
#include "fcntl.h"
int main()
{
    printf("raise before\n");
    raise(9);//此条语句终止本身进程 
    printf("raise after\n");//此条语句不会显示
    return 0;
    
}

例子:
//加深对kill和raise的理解

#include "stdio.h"
#include "unistd.h"
#include "stdlib.h"
#include "fcntl.h"
int main()
{
    pid t pid;
    pid=fork();
    if(pid >0)
    {
        sleep(8);//这个时候父进程处于睡眠S状态
        //8s之后父进程进入运行R状态
//补充:阻塞和非阻塞很简单,将waitpid设置为阻塞后如果子进程没有退出,那么父进程就会一直等待,直到子进程退出。 
//父进程查看子进程状态,子进程没有退出,父进程立即返回去执行其它任务,这一次的过程叫做非阻塞。(而父进程多次来回确认子进程有没有退出的过程称为轮询)
//如果将WNOHANG非阻塞变为0阻塞,那么kill(pid,9)不会执行,父进程变为阻塞状态
        if(waitpid(pid,NULL,WNOHANG) == 0)
        {
            kill(pid,9);//杀死pid子进程
        }
        //wait(NULL);//wait会回收子进程资源
        while(1);//子进程处于死循环状态,没有为子进程回收资源,子进程会变为僵尸Z状态
    }
    if(pid =0)
    {
        printf("raise function before\n");
        raise(SIGTSTP);//子进程会处于暂停T状态
        printf("raise funtion after\n");
        exit(0);
    }
    return 0;
}
(3)alarm函数:只会发送闹钟SIGALRM信号
  1. 调用alarm函数内核不会立马发出信号,而是当定时时间到只会才会发出alarm信号,内核发送的信号也只能给当前进程,收到alarm信号之后进程终止。
  2. alarm函数不需要告诉内核发送什么信号,因为它只能发送闹钟函数,但是需要告诉内核延时多久发送。alarm函数
    eg:
 #include "stdio.h"
#include "sys/types.h"
#include "signal.h"
#include "stdio.h"
#include "stdlib.h"
int main()
{
    int i;
    i=0;
    printf("alarm before\n");
    alarm(9);
    printf("alarm after\n");
    while(i<20)//在收到alarm信号之前进程不能终止
    {
        i++;
        sleep(1);
        printf("process things \n");
        return 0;
    }
}
2.信号的接收

接收信号的进程,要有什么条件:要想使接收的进程能收到信号,这个进程不能结束:
sleep:睡眠一段时间
while(1)
pause:进程状态为S睡眠状态,pause一直处于运行,即让进程一直处于s状态
pause函数

#include "stdio.h"
#include "sys/types.h"
#include "signal.h"
#include "stdio.h"
#include "stdlib.h"
int main()
{
    int i;
    i=0;
    printf("pause before \n");
    pause();//pause在此处s睡眠
    printf("pause after\n");
    while(i<20)
    {
        i++;
        sleep(1);
        printf("process things,i=%d\n",i);
        return 0;
    }
}
3.信号的处理
  1. 前面已经涉及到信号的处理,(默认处理方式)比如收到alarm、SIGSTP信号等,默认终止进程。
  2. 进程通信实际的用的较多的是:A发送信号给B,B进行信号的处理之后,再回来处理自己的进程,此时涉及到一个重要函数SIGNAL()。
  3. signal函数:
    作用:告诉内核处理哪个信号,告诉内核怎么处理信号(采用何种方式处理:忽视;默认处理方式(一般是终止);采用自己的函数去处理)signal函数signal函数自定义的信号处理函数指针:先进入处理函数,处理完之后回到B处理的事情。
 eg:
#include "stdio.h"
#include "sys/types.h"
#include "signal.h"
#include "stdio.h"
#include "stdlib.h"
void myfun(int signum)
{
    int i;
    i=0;
    while(i<10)
    {
        printf("process signal signum=%d\n",signum);
        sleep(1);
        1++;
    }
    return;//return main
}
int main()
{
    int i;
    i=0;
    //signal(14,SIG_IGN);//忽视当前信号
    //signal(14,SIG_DFL);//默认处理方式 终止当前进程
    signal(14,myfun);//接收到14信号之后会处理myfun函数内容,myfun函数处理完之后会继续接着处理while里面的内容
    printf("alarm before\n");
    alarm(9);
    printf("alarm after\n");
    while(i<20)
    {
        i++;
        sleep(1);
        printf("process things,i=d\n",i);
        return 0;
    }
}

函数运行结果:
在这里插入图片描述在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值