Linux进程间通信(信号)

信号发送

信号是 Linux 系统响应某些条件而产生的一个事件,接收到该信号的进程会执行相应的操作。 信号的产生有三种方式:

(1)由硬件产生,如从键盘输入 Ctrl+C 可以终止当前进程

(2)由其他进程发送,如可在 shell 进程下,使用命令 kill -信号标号 PID,向指定进程发送信号。 

(3)异常,进程异常时会发送信号

 在 Ubuntu 终端输入 kill -l,查看所有的信号。

 下面是几个常用的函数:

 

 

 

 使用规则:

实验 1 代码:在程序中实现:自己给自己发送信号。

sig.c

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

int main(int argc, char const *argv[])
{
    //int kill(pid_t pid, int sig);

    printf("raise before\n");
    raise(9);  //自己调用自己
    printf("raise after\n");

    return 0;
}

编译运行,如下图所示:

 

实验 2 代码 sig2.c 发送信号:

sig2.c

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


int main(int argc, char const *argv[])
{
    // int kill(pid_t pid, int sig);
    pid_t pid;
    int sig;

    if (argc < 3)
    {
        printf("请重新输入参数\n");
        return -1;
    }

    // int atoi(const char *nptr);
    sig = atoi(argv[2]);
    pid = atoi(argv[1]);

    kill(pid,sig);

    return 0;
}

test.c

#include <stdio.h>
#include <unistd.h>

int main(int argc, char const *argv[])
{
    while (1)
    {
        sleep(1);
        printf("hello world\n");
    }
    
    
    return 0;
}

编译运行 test,如下图所示,进程会循环打印 hello world

 重新打开另一个窗口,编译 sig2.c,然后查看 test 进程的 pid 号,运行测试如下图所示;

 

实验 3 代码 sig3.c

#include <stdio.h>
#include <unistd.h>

int main(int argc, char const *argv[])
{   
    int i;

    alarm(3);   //相当于定时器

    while (1)
    {
        sleep(1);
        i++;
        printf("i = %d\n",i);
    }
    
    
    return 0;
}

编译 sig3.c,并运行。如下图所示,设定的时间(3 秒)超过后产生 SIGALARM 信号,默认动作是终 止进程。

 

信号接收

接收信号:如果要让我们接收信号的进程可以接收到信号,那么这个进程就不能停止。让进程不停止 有三种方法:

 while

 sleep

 pause

方法一:

sig4.c

#include <stdio.h>
#include <unistd.h>

int main(int argc, char const *argv[])
{
    while (1)
    {
        sleep(1);
        printf("hello world\n");
    }
    
    
    return 0;
}

编译运行结果如下所示,按 ctrl+C 会发送 SIGINT 信号:

 方法三

使用 pause()函数,函数详解如下:

 pause.c

#include <stdio.h>
#include <unistd.h>
void main(void)
{
    printf("pause before\n");
    pause();
    printf("pause after\n");
}

编译程序并运行,如下图所示:

 

信号处理

信号是由操作系统来处理的,说明信号的处理在内核态。信号不一定会立即被处理,此时会储存在信 号的信号表中。

处理过程示意图:

由上图中可看出信号有三种处理方式:

1.默认方式(通常是终止进程),

2.忽略,不进行任何操作。

3.捕捉并处理调用信号处理器(回调函数形式)。

 实验 1代码实现信号忽略:

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
int main(void)
{
    signal(SIGINT,SIG_IGN);
    while(1){
    printf("wait signal\n");
    sleep(1);
}
return 0;
}

编译运行程序,如下图所示,当我们按下 ctrl+C 键的时候,信号被忽略。

 

 实验 2:代码实现采用系统默认方式处理该信号

#include <stdio.h
#include <signal.h>
#include <unistd.h>
int main(void)
{
    signal(SIGINT, SIG_DFL);
    while (1)
    {
        printf("wait signal\n");
        sleep(1);
    }
    return 0;
}

编译运行程序,如下图所示,按 ctrl+c

 实验 3 代码实现捕获到信号后执行此函数内容

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

void myfun(int sig)
{
    if(sig == SIGINT)
    {
       printf("get singnal %d\n",sig);
    }
    
}


int main(int argc, char const *argv[])
{
    //signal(int signum, sighandler_t handler)
    signal(SIGINT,myfun);  // SIG_IGN:忽略信号  SIG_DFL: 系统默认信号
    while (1)
    {
        printf("wait signal\n");
        sleep(1);
    }
    
    return 0;
}

编译运行程序如下图所示,当我们按下 ctrl+c 时,显示 myfun 函数里面的打印信息。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值