信号(进程间的通信方式)

目录

一,信号的概念

二,信号的响应方式(用户处理信号的方式)

三,信号种类

四,信号函数接口


一,信号的概念

1.信号是一种在软件层次上对中断机制的模拟,是一种异步通信方式;

2.信号可以直接进行用户空间进程和内核进程之间的交互,内核进程也可以利用信号来通知用户,关于空间进程发生了哪些系统事件;

3.如果一个进程当前并未执行,则该信号就由内核保存起来,直到进程执行或者恢复执行后再传递;如果一个信号被进程设置为阻塞,则信号的传递将会被延迟,直到阻塞被取消才能传递给进程;

二,信号的响应方式(用户处理信号的方式)

1.忽略该信号:不对信号做任何处理,但是有两个信号不能忽略,SIGKILL和SIGSTOP;

2.捕捉该信号:定义信号函数,当信号发生时,执行相应的信号处理函数;

3.执行缺省操作:也就是默认操作,Linux对每种信号都规定了默认操作。

三,信号种类

信号性质默认处理方式
SIGKILL9当产生这个信号后,当前进程就会退出,不能被缺省或捕捉退出进程
SIGSTOP19当产生这个信号后,当前进程会停止,不能被缺省或捕捉停止进程
SIGINT2键盘键入Ctrl+c时产生的信号退出进程
SIGQUIT3键盘键入Ctrl+\时产生的信号退出进程
SIGTSTP20键盘键入Ctrl+z时产生的信号停止进程
SIGCONT18当产生当前信号后,当前停止的进程会恢复运行停止的进程恢复运行
SIGALRM14当alarm函数设置的时间到达时,会产生当前信号退出进程
SIGPIPE13当管道破裂时,会产生当前信号退出进程
SIGABRT6当调用abort函数时会产生当前信号退出进程
SIGCHLD17当使用fork创建一个子进程时,如果子进程状态改变或退出,则会产生当前信号缺省
SIGUSR110用户自定义的信号,不会自动产生,只能使用kill函数或者命令给指定的进程发送当前信号缺省
SIGUSR212用户自定义信号,不会自动产生,只能使用kill函数或者命令给指定的进程发送当前信号缺省

四,信号函数接口

1.int kill(pid_t pid,int sig);

功能:给指定进程发送信号;

参数:pid->指定进程的进程号;sig->要发送的信号;

返回值:成功为0,失败为-1;

2.int raise(int sig);

功能:进程向自己发送信号;

参数:sig->信号;

返回值:成功为0,失败为-1;

3.unsigned int alarm(unsigned int seconds)

功能:在进程中设置一个定时器;

参数:seconds->定时时间,单位为秒;

返回值:如果该alarm函数是进程中第一次调用,则返回0,如果不是第一次调用,则返回上一次调用alarm函数剩余的时间;

注意:一个进程中,如果多次调用alarm函数,进程中的闹钟时间将会被最后一次调用的alarm函数所设定的时间确定。

4.int pause(void);

功能:用于将调用该函数的进程挂起,直到接收到信号为止;

5.typedef void (*sighandler_t)(int);

   sighandler_t signal(int signum,sighandler_t handler);

功能:接收信号,并进行相应操作;

参数:signum->要处理的信号;

        handler->信号的处理方式:SIG_IGN忽略信号;SIG_DFL默认操作和handler用户自定义的信号处理函数;

参数:成功则执行设置的信号处理方式,失败则返回-1;

代码演示:实现司机和售票员问题;

1)售票员捕捉SIGINT(代表开车)信号,向司机发送SIGUSR1信号,司机打印(let's gogogo)
2)售票员捕捉SIGQUIT(代表停车)信号,向司机发送SIGUSR2信号,司机打印(stop the bus)
3)司机捕捉SIGTSTP(代表到达终点站)信号,向售票员发送SIGUSR1信号,售票员打印(please get off the bus)
4)司机等待售票员下车,之后司机再下车。

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

pid_t pid; //两个信号处理函数和main函数都要使用pid,所以定义为全局变量;
//司机信号处理函数
void hand_bus(int sig)
{
    if (sig == SIGUSR1)
    {
        printf(" let's gogogo!\n");
    }

    if (sig == SIGUSR2)
    {
        printf(" stop the bus\n");
    }

    if (sig == SIGTSTP)
    {
        //给指定进程(子进程乘务员)发送信号
        kill(pid, SIGUSR1);
        wait(NULL);
        exit(0);
    }      
}
//乘务员信号处理函数
void hand_staff(int sig)
{
    if (sig == SIGUSR1)
    {
        printf(" please get off the bus\n");
        exit(0);
    }
    if (sig == SIGINT)
    {
        kill(getppid(), SIGUSR1);
    }
    if (sig == SIGQUIT)
    {
        //给指定进程(父进程司机)发送信号
        kill(getppid(), SIGUSR2);
    }
}

int main(int argc, char const *argv[])
{
    if ((pid = fork()) < 0)
    {
        perror("fork err");
        return -1;
    }
    else if (pid == 0) //staff
    {
        //接收乘务员要处理的信息,执行乘务员信号处理函数
        signal(SIGINT, hand_staff);
        signal(SIGQUIT, hand_staff);
        signal(SIGUSR1, hand_staff);
        //忽略其他信号
        signal(SIGUSR2,SIG_IGN);
        signal(SIGTSTP,SIG_IGN);
    }
    else //bus
    {
        //接收司机要处理的信息,执行乘务员信号处理函数
        signal(SIGTSTP, hand_bus);
        signal(SIGUSR1, hand_bus);
        signal(SIGUSR2, hand_bus);
        //忽略其他信号
        signal(SIGINT,SIG_IGN);
        signal(SIGQUIT,SIG_IGN);
    }
    pause();
    return 0;
}

执行结果为:

 如果本文中存在概念错误或代码错误的情况,请批评指正。 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值