进程间通信(IPC)之 信号编程

信号处理函数的注册

  1. 入门版: signal

  1. 高级版:sigaction

信号处理函数

信号发送函数也不止一个,同样分为入门版(无法携带消息)和高级版(可以携带消息)

  1. 入门版:kill

  1. 高级版:sigqueue

一、入门版的收发信号 (signal收信号, kill发信号)

接下来利用signal 实现一下信号处理函数捕获信号 (收信号

#include <signal.h>
#include <stdio.h>

// typedef void (*sighandler_t)(int);

// sighandler_t signal(int signum, sighandler_t handler);

void handler(int signum)
{
        printf("get signum = %d\n",signum);
        switch(signum){
                case 2:
                        printf("SIGINT\n");   // ctrl + c
                        break;
                case 9:
                        printf("SIGKILL");   // 企图捕获其它进程发过来的kill 信号
                        break;
                case 10:
                        printf("SIGUSR1");
                        break;
        }
        printf("never quit\n");
}

int main()
{
        signal(SIGINT, handler);
        signal(SIGKILL, handler);
        signal(SIGUSR1, handler);
        while(1);
        return 0;
}

按下ctrl + c

接下来看能不能捕获到 kill 信号 (发信号)

并不能捕捉到 kill 信号

自己实现一个kill函数,用于发信号

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

// int kill(pid_t pid, int sig);

int main(int argc, char **argv)
{
        int signum;
        int pid;

        signum = atoi(argv[1]);
        pid = atoi(argv[2]);

        kill(pid, signum);
        printf("send signal ok\n");

        printf("signum = %d, pid = %d\n",signum, pid);
        return 0;
}

用法

或者利用system 函数也可以实现这个功能(发信号)

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

// int kill(pid_t pid, int sig);

int main(int argc, char **argv)
{
        int signum;
        int pid;
        char cmd[128] = {0};

        signum = atoi(argv[1]);
        pid = atoi(argv[2]);
        printf("signum = %d, pid = %d\n",signum, pid);

        sprintf(cmd, "kill -%d %d",signum, pid);

//      kill(pid, signum);
        system(cmd);

        printf("send signal ok\n");
        return 0;
}

二、高级版的收发信号

收信号:sigaction

原型:

#include <signal.h>

int sigaction(
    int signum,    // 第一个参数
    const struct sigaction *act, // 第二个参数 
    struct sigaction *oldact    // 第三个参数
);

第一个参数: int signum

第一个参数:signum:信号编号

第二个参数 const struct sigaction *act

第二个参数: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);
};
拆分结构体参数:
第一个参数:
void (*sa_handler)(int):信号处理函数,不接收数据

第二个参数 (编程的时候需要配置)
void (*sa_sigaction)(int, siginfo_t *, void *): 可以接收额外数据
1. int: 信号编号
2. siginfo_t *:结构体
拆分:
siginfo_t {
  pid_t si_pid;  // 谁发的
  int si_int;  // 整型数存放的地方
  sigval_t si_value;  // 信号的值
}
si_value:
union sigval {
    int sival_int;
    void *sival_ptr;
}
3. void *: 空:没有数据; 非空:有数据

第三个参数
sigset_t sa_mask:阻塞作用(默认就是阻塞)

第四个参数  (编程的时候需要配置)
int sa_flags:需要配置一个宏(SA_SIGINFO) 

第三个参数: sigaction

sigaction 用来做备份(备份原操作)

发信号:sigqueue

原型:

#include <signal.h>

int sigqueue(
    pid_t pid,    // 第一个参数
    int sig,      // 第二个参数
    const union sigval value   // 第三个参数(联合体)
);

第一个参数

pid_t pid : 发给谁

第二个参数

int sig: 发的是什么信号

第三个参数

const union sigval value : 需要的消息
union sigval {
    int sival_int;
    void *sival_ptr;
}

携带消息实战代码:

收消息:(sigaction)

#include <signal.h>
#include <stdio.h>

// int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);

void handler(int signum, siginfo_t *info, void *context)
{
        printf("get signum %d\n",signum);
        if(context != NULL){
                printf("get data =%d\n",info->si_int);
                printf("get data =%d\n",info->si_value.sival_int);
                printf("from:%d\n",info->si_pid);
        }
}

int main()
{
        struct sigaction act;
        printf("pid = %d\n",getpid());

        act.sa_sigaction = handler;
        act.sa_flags = SA_SIGINFO; // be able to get message

        sigaction(SIGUSR1, &act, NULL);
        while(1);
        return 0;
}

发消息:(sigqueue)

#include <signal.h>
#include <stdio.h>

//int sigqueue(pid_t pid, int sig, const union sigval value);

int main(int argc, char **argv)
{
        int signum;
        int pid;

        signum = atoi(argv[1]);
        pid = atoi(argv[2]);

        union sigval value;
        value.sival_int = 100;
        sigqueue(pid, signum, value);
        printf("%d, done\n",getpid());
        return 0;
}

结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值