进程间通信与信号基础

管道通信:分为无名和有名管道

无名管道:

 为了进程间能够通信,调用系统创建管道作为存储空间,以队列模式先进先出,管道头部文件描述符hfd,尾部文件描述符tfd,需要两个进程PCB相同,则PB为PA的子进程,fork创建PB进程继承了PA进程的PCB,也就继承了文件描述符

此管道只能应用于具有亲缘关系的通信,父子或兄弟关系(无名管道不记录在系统当中)

管道里没有内容,读不出来会读阻塞

管道满了,写不进去会写阻塞

创建单向管道

#include<unistd.h>

int pipe(int pipefd[2]);

功能:创建一个单向管道

参数:pipefd[0]指向读端,pipefd[1]指向写端

返回值:成功返回0,失败返回-1,errno被设置

代码测试:

有名管道是一种文件类型的管道,该类型文件的特点是内容始终为0,只起到进程间通讯的作用

有名管道对于进程之间的关系没有要求

使用mkfifo(3)创建,依然是队列思想,先进先出

#include<sys/types.h>

#include<sys/stat.h>

int mkfifo(const char*pathname,mode_t mode);

功能:创建一个管道类型的文件,文件必须读写两端同时打开

参数:

pathname: 指定文件名自

mode:指定文件权限,最终权限mode&~umask

返回值:成功返回0,失败返回-1.errno被设置

 测试结果如下:

信号的基础知识

什么是信号:软中断,软件实现的中断机制,使用中断处理程序

进程再执行过程中,如果有信号到来,进程调用信号处理程序,处理完毕进程继续执行

每个进程都有信号的处理程序,继承父进程

系统为用户提供了多少信号?(kill -l可以查看)

 常用

2号信号,终止进程(ctrl+c)

3号信号,ctrl+\

9号信号,杀死进程

10、12自定义

11、段错误信号

14、闹钟信号

17、子进程终止发给父进程的回收资源信号

信号一般经过三个过程,产生、递达、处理

信号的产生

①硬件产生信号 ctrl+c等等

②使用命令产生信号  kill -信号编号

③使用系统调用或库函数发送 kill(2)、raise(3)、alarm(2)

从产生到处理之前信号都处于一个未决状态,称这种信号叫做未决信号,可以设置进程为信号进行阻塞

信号的处理有三种方式

①缺省处理

②忽略处理

③用户自定义处理

信号处理函数的注册signal(2)

#include<signal.h>

typedef void(*sighandler_t)(int);

sighandler_t signal(int signum,sighandler_t handler);

功能:改变进程的信号处理函数

参数:

signum:指定信号编号

handler:指定处理函数

返回值:

错误:返回SIG_ERR,errno被设置

成功:返回原来信号处理函数的入口地址

handler:

①SIG_IGN 信号忽略,SIGKILL和SIGSTOP不可忽略

②SIG_DFL 缺省处理

③自定义函数

其中SIGKILL和SIGSTOP不可忽略

信号的发送

#include<sys/types.h>

#include<signal.h>

int kill(pid_t pid,int sig);

功能:发送信号给进程和进程组

参数:

pid:指定了目标进程的pid

sig:指定了信号编号

返回值

成功返回0

失败返回-1,errno被设置

#include<unistd.h>

unsigned int alarm(unsigned int seconds);

功能:设置一个闹钟,到seconds指定秒时,产生SIGALRM信号,将信号发送给当前进程,默认是终止进程

参数:

seconds 指定的秒数,如果是0,将取消原来设置的所有闹钟,所有未决闹钟都被取消

返回值:

原来无设置闹钟返回0

原来设置闹钟返回闹钟的未决时间

 

#include<unistd.h>

int pause(void);

功能:等待信号

返回值:当信号到达调用完信号处理函数后再返回-1,errno被设置

注:忽略信号不能唤醒pause,自定义信号可以,pause使用时CPU会被让出,等待信号处理才会唤醒

 信号阻塞的设置

信号集类型分为信号掩码集和未决信号集

信号掩码集:用来指示线程阻塞的信号的集合。通俗地讲,信号掩码用来表示哪些信号会被线程阻塞

未决信号集信号已经产生了,但是还没有成功送达给线程处理的集合

 信号集相关操作:

定义一个信号集是sigset_t

#include<signal.h>

int sigemptyset(sigset_t *set);

功能:将信号集初始化为空

参数:set是要指定初始化的信号集地址

返回值:成功返回0,失败返回-1,errno被设置

int sigfillset(sigset_t *set);

功能:将信号集初始化为满,也就是包含所有信号

参数返回值同上

int sigaddset(sigset_t*set,int signum);

功能:将信号添加到信号到信号集中

参数

set 指定信号集

signum 指定信号编号

返回值同上

int sigdelset(sigset_t *set,int signum);

功能:将信号从信号集中移除

参数返回值同上

 int sigismember(const sigset_t*set,int signum);

功能:测试信号是否是信号集的一员

参数同上

返回值:

成功:返回1代表是,0代表不是

失败:返回-1,errno被设置

int sigpromask(int how,const sigset_t*set,sigset_t *oldset);

功能:检查和改变阻塞信号集

参数:

set:指定信号掩码集

oldset:如果不为空,将进程原来的信号掩码集保存到这里

how:

SIG_BLOCK:将set和当前进程信号掩码集合并

SIG_UNBLOCK:将set集合中信号从当前进程信号掩码集中移除

SIG_SETMASK:将set设置为进程的信号掩码集

返回值:

成功:返回0

失败:返回-1,errno被设置

int sigpending(sigset_t*set);

功能:审查当前进程的未决信号

参数:

set:将当前进程的未决信号集返回到set指定的地址空间里

返回值:

成功 返回0

失败 返回-1 errno被设置

代码测试:

 注:信号的丢失

有些信号在阻塞时输入多次的时候,只会被执行一次,叫做不可靠信号(1-31号信号)

没有信号丢失的称为可靠信号,也叫实时信号(34-64号信号)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值