C语言进程通信信号

目录

一、信号的特点

二、信号的处理

        1)忽略信号

        2)捕捉信号

        3)默认操作

三、信号的发送

四、设置信号函数:signal()

五、其他函数:alarm(闹钟)、pause();

六、有名管道与信号结合


一、信号的特点

        1)一个进程收到一个信号与处理器收到一个中断请求可以说是一样的(软中断)。

        2)信号是异步的,一个进程不必通过任何操作来等待信号的到达。

        3)信号是内核定义的,当相应的事件产生时,内核发射相应的信号。

二、信号的处理

        进程可以通过3种方式来响应一个信号

        1)忽略信号

        即对信号不做任何处理,其中,有两个信号不能被忽略:SIGKLL和SIGSTOP。

        接收到了,但是什么都不做。

        2)捕捉信号

        定义信号处理函数,当信号发生时,执行相应的处理函数。

        3)默认操作

        对每种信号都规定了默认操作,如 kill -l 查看到的命令

        

 1) SIGHUP  终端关闭会发送               进程结束
 2) SIGINT   ctrl + c 终止当前进程      进程结束 
 3) SIGQUIT  ctrl + \  停止当前进程     进程结束
 9) SIGKILL    杀死进程                       进程结束        
12) SIGUSR2   用户自定信号        
14) SIGALRM   闹钟信号
19) SIGSTOP     进程暂停
20) SIGTSTP   ctrl+z  挂起进程        转换成后台进程 

        

三、信号的发送

        信号发送函数:kill()、raise();

(1)函数:kill 发送信号

函数原型:int kill(pid_t pid, int sig);

头文件:#include <signal.h>  #include <sys/types.h>

参  数: pid 需要发送哪个进程的id,   sig 是需要发送的信号
                    > 0   发送sig信号给pid的进程(一个进程)
                       0   发送给正在调用的进程组所在进程下的所有id
                      -1   发送sig信号给所有进程(除了1号init进程)
                    <-1    给进程组为绝对值pid的组发送sig信号。
 返回值:如果成功返回0 如果失败返回-1  错误信息存入errno

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

int main(int argc,char *argv[])
{
    if(argc != 3)
    {
        printf("输入的格式错误<命令> <信号> <进程id>");
        exit(-1);
    }
    int res = kill(atoi(argv[2]),-1 * atoi(argv[1]));
    if(res < 0)
    {
        perror("kill");
        exit(-2);
    }
    return 0;
}

(2)函数 raise 给自己发信号

       函数原型: int raise(int sig);

       头文件:#include <signal.h>
        作       用: 给当前进程发送信号,相当于 kill(getpid(),sig)
        参数:    需要放的信号内容
        返回值: 如果成功返回 0,失败返回-1,错误信息errno

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

int main()
{
    printf("hello!!!\n");
    raise(9);
    printf("world\n");
    return 0;
}

四、设置信号函数:signal()

        函数原型:sighandler_t signal(int signum, sighandler_t handler);  
        回调函数:  typedef void (*sighandler_t)(int);
        头文件:      #include <signal.h>
        参数:       signum  信号的值,需要处理什么信号
                        handler 参数:
                       如果想忽略信号(SIG_IGN)    1
                       如果想默认操作(SIG_DEL)0
                       对信号自定义处理的回调函数地址

      返回值:返回先前处理函数的指针,如果没有先前的处理函数则返回自己。如果失败返回SIG_ERR  (-1)

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

/****信号处理函数******/
void add(int n)
{
    printf("***加法****\n");
    printf("add = %d\n", n + n);
}

void sub(int n)
{
    printf("***减法****\n");
    printf("add = %d\n", n - n);
}
void mul(int n)
{
    printf("***乘法****\n");
    printf("add = %d\n", n * n);
}

void div(int n)
{
    printf("***除法****\n");
    printf("add = %d\n", n / n);
}
/**********************/
int main()
{
    signal(10,add);
    signal(11,sub);
    signal(12,mul);
    signal(13,div);
    while(1);
    return 0;
}

五、其他函数:alarm(闹钟)、pause();

(1) alarm 闹钟信号  SIGALRM---14

函数原型:unsigned int alarm(unsigned int seconds);  【重】
头文件: #include <unistd.h>
作用:在参数seconds秒后发送一个闹钟给自己,信号名称:SIGALRM---14
返回值: 如果先前没有设置闹钟,成功返回0,失败返回-1
                    如果之前设置了闹钟,返回之前设置的闹钟剩余秒数,
 注意: 一个进程只能有一个闹钟时间,如果在调用alarm()之前已经设置过闹钟时间,则任何以前的闹钟时间都被新值所替代。

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

int main()
{
    int res = alarm(3);//设置闹钟信号,软中断
    if(res < 0)
    {
        perror("res");
        exit(-1);
    }
    while(1)
    {
        printf("我还活着\n");
        sleep(1);
    }
    return 0;
}

(2)pause 堵塞当前进程
    函数原型: int pause(void);
     头文件:#include <unistd.h>
     作用: 让当前进程处于堵塞状态,等待接受一个信号(终止信号或者引起调用信号处理函数的信号)
                如果是非终止信号或者是不需要捕获的信号,则不会解除堵塞。


   pause和wait的区别:
   前者是等待另外的进程发送sigkill信号,而wait是父进程等待子进程的结束。

六、有名管道与信号结合

A,B两个进程相互通信,A发B收,B发A收,当A给B发消息时同时会发送一个信号,B接收到信号时会中断去读这个信息,同理当B给A发消息时同时会发送一个信号,A接收到信号时会中断去读这个信息。

A ---> 内核--->发信号--->B

B ---> 内核--->发信号--->A

B进程跟A进程相似,A如下图,B省略

 A进程

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>
#include <sys/stat.h>

int fd0, fd1;
void read_r(int n);
char buf0[128] = {0};
char buf1[128] = {0};
int main()
{
    if (access("./aname", F_OK) == -1) //检测是否存在,如果不存在则创建
    {
        int res = mkfifo("./aname", 0666);
        if (res < 0)
        {
            perror("mkfifo");
            exit(-1);
        }
    }
    if (access("./bname", F_OK) == -1) //检测是否存在,如果不存在则创建
    {
        int res = mkfifo("./bname", 0666);
        if (res < 0)
        {
            perror("mkfifo");
            exit(-1);
        }
    }

    fd0 = open("./aname", O_RDWR);
    fd1 = open("./bname", O_RDWR);

    int pid1 = 0;
    int pid = getpid();
    write(fd1, &pid, sizeof(pid));
    read(fd0, &pid1, sizeof(pid1));
    signal(10, read_r); //读
    while (1)
    {
        memset(buf1, 0, sizeof(buf1));
        scanf("%s", buf1);
        write(fd1, buf1, sizeof(buf1));
        kill(pid1, 12);
        if (strcmp(buf1, "quit") == 0)
        {
            kill(pid1, 9);
            break;
        }
    }
}

void read_r(int fd)
{
    read(fd0, buf0, sizeof(buf0));
    printf("B: %s\n", buf0);
}

B进程

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>
#include <sys/stat.h>

int fd0, fd1;
char buf0[128] = {0};
char buf1[128] = {0};
void write_w(int n);
int main()
{
    if (access("./aname", F_OK) == -1) //检测是否存在,如果不存在则创建
    {
        int res = mkfifo("./aname", 0666);
        if (res < 0)
        {
            perror("mkfifo");
            exit(-1);
        }
    }
    if (access("./bname", F_OK) == -1) //检测是否存在,如果不存在则创建
    {
        int res = mkfifo("./bname", 0666);
        if (res < 0)
        {
            perror("mkfifo");
            exit(-1);
        }
    }

    fd0 = open("./aname", O_RDWR);
    fd1 = open("./bname", O_RDWR);

    int pid = 0;
    int pid1 = getpid();
    read(fd1, &pid, sizeof(pid));
    printf("%d\n", pid);
    write(fd0, &pid1, sizeof(pid1));
    signal(12, write_w);
    while (1)
    {
        memset(buf0, 0, sizeof(buf0));
        scanf("%s", buf0);
        write(fd0, buf0, sizeof(buf0));
        kill(pid, 10);

        if (strcmp(buf0, "quit") == 0)
        {
            kill(pid, 9);
            break;
        }
    }
    return 0;
}

void write_w(int n)
{
    read(fd1, buf1, sizeof(buf1));
    printf("A: %s\n", buf1);
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值