进程间的通信-信号量(C语言)

7 篇文章 0 订阅
5 篇文章 0 订阅

目录

一、信号量

1、什么是信号

2、在linux下,有哪些信号

3、在linux下,这些信号究竟是由谁来发出

4、用户如何发送信号给进程?

二、信号的函数接口

1、 如何发送信号给另外一个进程

 2、如何捕捉信号

3、发送信号


一、信号量

1、什么是信号

信号是一种异步通信机制,一般情况下,进程什么时候会收到信号、收到什么信号是无法事先预料的(就像你家的门铃,你不知道它什么时候会响,但是门铃响的时候我们可以下楼开门(处理))

2、在linux下,有哪些信号

gec@ubuntu:/mnt/hgfs/GZ2034/09 系统编程/02/code/fifo$ kill -l
 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL10) 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) SIGWINCH29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN
例如:

19) SIGSTOP

信号值)SIG+信号名字

其实信号的名字与信号值是等价的,它们是宏定义来的,被定义在一个头文件:
/usr/include/asm-generic/signal.h

#define SIGHUP 1
#define SIGINT 2
#define SIGQUIT 3
#define SIGILL 4

 

 

3、在linux下,这些信号究竟是由谁来发出

1)由系统来发出。

14) SIGALRM  -> 当在程序中调用alarm()时,如果到点了,就会自动发出这个信号。 注:alarm为闹钟函数
17) SIGCHLD  -> 当子进程退出时,自动发出这个信号给父进程。

2)信号也可以由用户来发送。

如果是由用户来发送,则需要学习 kill / killall 这两个命令。

4、用户如何发送信号给进程?

方法一:

1)首先查看目标进程的PID号。 -> ps -ef

   PID号 
gec        4630   4310  0 00:30 pts/4    00:00:00 ./a.out

2)通过kill命令发送9号信号给该进程,杀死进程。

kill -9 4630
kill -SIGKILL 4630  或者 kill -KILL 4630

方法二:

直接通过killall命令给进程名字发送信号

killall -9 a.out
killall -SIGKILL a.out  或者 killall  -KILL a.out   -> 只要名字为a.out,都会收到这个信号。

二、信号的函数接口

1、 如何发送信号给另外一个进程

#include <sys/types.h>
#include <signal.h>    -> linux信号的专属头文件
int kill(pid_t pid, int sig);

函数作用:

向指定进程或者进程组,发送一个指定的信号

返回值

成功:0        失败:-1

 2、如何捕捉信号

#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);

函数作用:

捕捉一个指定的信号,即预先为某信号的到来做好准备

参数:

signum 需要捕捉的信号

handler

        SIG_IGN 忽略该信号

        SIG_DFL 执行该信号的默认动作

        void (*p)(int) 执行由 p 指向的信号响应函数

返回值:

成功返回 最近一次调用该函数时第二个参数的值

失败返回 SIG_ERR ((__sighandler_t) -1)

注意:

1、所谓的捕捉信号 就是 获取当这个信号来之后,去执行 信号响应函数,原本的信号默认动作就不会执行了。

2、当调用signal 函数之后 ,程序不会阻塞,而是往下面代码执行,但是这个捕捉设置 是 全局有效

3、SIGKILL 、SIGSTOP 不能被捕捉,只能执行默认的动作

例子:

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

typedef void (*sighandler_t)(int);

//回调函数 arg是信号的值
void signalHandler(int arg)
{
    //没有收到信号,所以这个不会执行
    printf("接收到信号!\n");

}

int main(void)
{
    sighandler_t fun; //函数指针
    
    //捕获信号,有对应的信号过来,执行回调函数  ,这个是非阻塞函数
    fun = signal(SIGINT, signalHandler);
    if(fun == SIG_ERR)
    {
        printf("signal failure\n");
    }

    while(1)
    {
        sleep(1);
        printf("hello world\n");
    }

    return 0;
}

结果:

 

3、发送信号

#include <signal.h>
int raise(int sig);

参数:

sig: 发送的信号。

返回值:

成功:0        失败:非0

代码:

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

typedef void (*sighandler_t)(int);

//回调函数 arg是信号的值
void signalHandler(int arg)
{
    //没有收到信号,所以这个不会执行
    printf("接收到信号!\n");

}

int main(void)
{
    sighandler_t fun; //函数指针
    
    //捕获信号,有对应的信号过来,执行回调函数  ,这个是非阻塞函数
    fun = signal(SIGINT, signalHandler);
    if(fun == SIG_ERR)
    {
        printf("signal failure\n");
    }

    while(1)
    {
        sleep(1);
        printf("hello world\n");
        //发送信号
        raise(SIGINT);
    }

    return 0;
}

结果:

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值