进程间通信(IPC)之信号、管道、信号量

1.信号

信号是进程间通信方式之一,是系统用来通知进程发生了某件事的一种手段,仅是一种通知,没有数据传递。

信号的本质是一个整数,不同的信号代表了不同的含义,可以在linux中使用指令kill -l查看系统中的所有信号。

当进程收到信号时,会中止当前的任务,转而去处理信号,处理完成后,再从中止点继续执行原来的任务,所以,信号也可以软中断。

常用的信号:

2) SIGINT       由按键ctrl+c产生,默认中止进程
9) SIGKILL      由用户主动发出,用于结束指定的进程
11) SIGSEGV     由于程序非法使用内存,系统发出该信号,默认终止当前进程
13) SIGPIPE     管道破裂,指在往管道中写数据时,读端不存在了,进程就会收到该信号,默认终止当前进程
14) SIGALRM     闹钟信号
17) SIGCHLD     子进程结束时,会给它的父进程发该信号。linux为了防止僵死进程的产生,默认是忽略这个信号的,但不是所有版本的linux都是这样的,所以,最有效的方式是捕获该信号,然后调用wait/waitpid函数。

常用的信号相关接口:

#include <signal.h>
int kill(pid_t pid, int sig);
功能:给指定的进程发送指定的信号
返回:
    成功返回0,
    失败返回-1,同时设置errno
#include <signal.h>
typedef void (*sighandler_t)(int);//定义一个名为sighandler_t的新类型,它是一个函数指针类型,指向一个接收一个整型参数并且返回空类型的函数
sighandler_t signal(int signum, sighandler_t handler);
功能:用于处理指定的信号
参数: 
    signum  需要处理的信号(可以是信号值,也可以是信号名称)
    handler 信号处理器(本质是一个函数指针,当指定的信号到达,系统自动调用你指定的这个函数)
说明:
    信号处理器可以是忽略信号,用SIG_IGN表示
    信号处理器可以使用信号的默认处理方式,用SIG_DFL来表示
    信号处理器可以是自定义的函数,
        该函数要求返回类型为void, 
        有一个int类型的参数,这个int就是signal的第一个参数,即要处理的信号
​
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
功能:设置一个指定时间的闹钟,时间超时则发出SIGALRM信号
参数: seconds 时间秒数
        该参数可以为0,表示取消之前设置的闹钟
返回:
    闹钟正常超时,返回0
    被取消则返回闹钟的剩余时间

2.无名管道

无名管道在内核中开辟了一块缓冲区,这块内核空间由所有进程共享。

无名管道类似于文件,可以用文件描述符read/write/close操作,但无名管道没有名字,所以不用open获取文件描述符,而是系统专门提供了一个接口pipe。

#include <unistd.h>
int pipe(int pipefd[2]);
功能:在内核中创建一个无名单向管道,用于进程间通信
参数: 
    pipefd 是两个元素的整型数组的首地址,由用户提供,内核创建好管道之后,会自动把管道两端的描述符写入该数组
    pipefd[0] 是读端描述符, pipefd[1]是写端描述符。
返回:
    成功返回0,失败返回-1,同时设置errno
​

一些说明:

无名管道是单向的;

如果无名管道为空,读数据时会阻塞,直到有数据写入;

如果无名管道满了,写数据时会阻塞,直到数据被读走;

无名管道只能用于具有亲缘关系的进程之间(即有共同祖先)。

3.有名管道

有名管道需要有一个名字存在于文件系统中,任意进程都可以使用该名字来打开这个管道进行读写操作。

 #include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
参数:
    pathname 待创建的命名管道的名字,建议带路径
    mode 创建文件时的权限,一般用八进制表示
返回:
    成功返回0,
    失败返回-1,同时设置errno

一些说明:

与无名管道相同,创建成功后用文件接口进行读写操作;

只读打开fifo时会阻塞,直到有进程以写的方式打开该fifo,反之亦然;

但是可读可写的方式打开则不会有这个问题。

无名管道和有名管道的区别

无名管道:

1)只能用于共同祖先的进程,一般用于父子进程和兄弟进程之间;

2)是一种半双工的通信方式,数据只能单向流动;

3)创建一块内核资源用于通信,不会在文件系统中留下对应的文件;

有名管道:

1)可以用于任意的进程;

2)是一种全双工的通信方式;

3)使用mkfifo系统调用创建,会在文件系统中留下一个FIFO文件用于通信;

总的来说,无名管道通常用于临时的、简单的通信需求,而有名管道多用于长期的、稳定的跨进程通信需求。

4.信号量

信号量是用于协调(同步)进程或线程间工作的,标识某种共享资源的数量,当多个进程或线程争夺共享资源时,信号量用来保证它们合理、有序的使用这些资源。

可以把信号量理解为一个整数,这个整数就表示资源的数量: 如信号量的值为0,表示没有资源可用,进程不能访问该资源; 如信号量的值为1,表示有1份资源可用,即同一时刻只允许有一个进程去访问共享资源; 如信号量的值为n, 表示同一时刻允许有n个进程去访问共享资源。

当资源可用的情况下, 进程访问共享资源前,需要把信号量的值减1,表示消耗了一份资源,这种操作称为P操作; 进程访问共享资源完成后,需要把信号量的值加1,表示增加了一份资源,这种操作称为V操作。 简称P-V+

信号的PV操作 是原子性的,也就是说对信号量值的增加或减少,系统保证在CPU级别上是不可分割的,这与普通整数的加减是有本质的区别的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值