linux进程通信---几个发送信号的函数(kill,raise,alarm,pause)

信号:信号是unix中最古老的进程通信的一种方式,他是软件层次上对中断机制的模拟,是一种异步通信方式,信号可以实现用户空间进程和内核空间进程的交互,内核进程可以利用他通知用户空间进程发生了哪些系统事件,我们可以任何时候给进程发送信号而无需知道进程的状态,如果进程当前并未处于执行态,则信号则会由内核保存起来,如果进程是阻塞状态,那么信号传递会被延迟,直到阻塞结束时才会传递给进程。

看一下kill -l列出的各种命令:

会发现一个规律,前32种信号会有各种不同的名称,后32种会以“SIGRTMIN”或者“SIGRTMAX”开头,前者是从unix继承下来的信号,称为不可靠信号(也称为非实时信号),后者为了解决“不可靠信号”的问题进行了更改和扩充的信号形成了可靠信号(也称为实时信号)

如果想要了解可靠与不可靠信号,需要了解信号的生命周期:

一个完整的信号周期可以分为三个重要阶段,三个重要阶段有四个重要事件刻画的:信号产生,信号在进程中注册,信号在进程中注销,执行信号处理函数

信号处理周期:

相邻的两个事件的时间间隔构成了生命周期的一个阶段,这里的信号处理有多种方式,一般由内核完成,也可以由用户进程完成

可靠信号与不可靠信号的区别:

不可靠信号如果发现信号已经在进程中注册,就会忽略该信号,因此若前一个信号还没有注销又产生了新的信号就是导致信号丢失

可靠信号发送给一个进程时,不管该信号是否已经在进程中注册,都会被再注册一次,因此信号不会丢失,所有可靠信号都支持排队,所有不可靠信号都不支持排队。

ps:这里信号的产生,注册,注销等是指信号的内部的实现机制,而不是调用信号的函数实现,所以信号注册与否,与本节后面讲到的发送信号函数(kill等)以及信号安装函数(signal()等)无关只与信号值有关

用户进程对信号的响应有三种方式:

  1. 忽略信号,对信号不做任何处理,但是又两个信号是不能忽略的,即SIGKILL,SIGSTOP
  2. 捕捉信号,定义信号处理函数,当信号发送时,执行相应的自定义处理函数
  3. 执行缺省操作,linux对每种信号都规定了默认操作

linux中大多数信号是提供给内核的,下面列出了最为常见的信号的含义及其默认操作:

发送信号的函数主要有kill(),raise(),alarm(),pause()

(1)kill()和raise()

kill()函数和熟知的kill系统命令一样,可以发送信号给信号和进程组(实际上kill系统命令只是kill函数的一个用户接口),需要注意的是他不仅可以终止进程(发送SIGKILL信号),也可以向进程发送其他信号。

与kill函数不同的是raise()函数允许进程向自身发送信号。

(2)函数格式:

kill函数的语法格式:

raise()函数语法要点:

下面的例子使子进程不在父进程调用kill之前不退出,然后父进程调用kill使子进程退出:

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()
{
    pid_t pid ;
    int ret ;
    if ((pid = fork()) < 0)
    {
        printf("fork error\n") ;
        exit(1) ;
    }
    else if (pid == 0)
    {
        printf("child(pid:%d)id waiting for any signal\n", getpid()) ;
        raise(SIGSTOP) ;//子进程暂停
        exit(0) ;
    }
    else
    {
    		//获取到pid子进程没有退出,指定WNOHANG不会阻塞,没有退出会返回0
        if ((waitpid(pid, NULL, WNOHANG)) == 0)
        {
            if ((ret = kill(pid, SIGKILL)) == 0)//向子进程发出SIGKILL信号
            {
                 printf("parent kill %d\n", pid) ;
            }
        }
        waitpid(pid, NULL, 0) ;//等待子进程退出,是阻塞函数如同wait()
        exit(0) ;
    }
}
程序运行结果如下:

看出父进程kill掉了子进程

(3)alarm()和pause()

alarm()-----也称为闹钟函数,可以在进程中设置一个定时器,等到时间到达时,就会想进程发送SIGALARM信号,注意的是一个进程只能有一个闹钟时间,如果调用alarm()之前已经设置了闹钟时间,那么任何以前的闹钟时间都会被新值所代替

pause()----此函数用于将进程挂起直到捕捉到信号为止,这个函数很常用,通常用于判断信号是否已到

alarm()函数语法:

pause()函数语法如下:

下面的一个实例实现了sleep()函数的功能

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
    int ret = alarm(5) ;//设置一个定时器
    pause() ;//捕捉定时器信号
    printf("I have been waken up\n", ret) ;
}
~            
执行程序会在5秒之后出现:


这个函数中的printf是不会执行的,因为定时器发送的SIGARAM的默认处理是终止程序,所以程序打印之前程序已经结束了,与sleep不同的是sleep是不会退出的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值