进程间通信


进程间通信:管道 ,信号量,共享内存,消息队列,套接字。(信号量,共享内存,消息队列)
同步机制:管道 消息队列。管道写端写满阻塞,管道为空,读端阻塞。
同步:同一时刻只能一个进程访问资源,若资源被占用程序就会被则色,对程序的控制同步。

管道

基础知识

管道:用来在两个进程之间传递数据,例如:ps -ef | grep “bash”,其中‘|’就是管道,作用是将ps命令的结果写入管道文件,然后grep再从管道文件中读出来该数据进行过滤。
管道:只能以只读只写管道。目的:进程间通讯创建好内存中分配
内存:断点不保存任何数据。
管道通讯特点:
1、半双工
2、管道没有数据,read阻塞
3、管道写端关闭,read返回0
4、管道读端关闭,写端产生异常(发送SIGPIPE,程序收到信号 异常终止)。

有名管道

可以在两个任意两个进程间通信。
管道文件的创建:mkfifo 命令(mkfifo FIFO)
a.c:向管道文件中写入数据
b.c:从管道文件中读取数据
a.c:
在这里插入图片描述
b.c:在这里插入图片描述
我们发现a和b文件不懂再同一个终端运行,需要再两个不同终端进行操作,管道没有数据,read阻塞。
可以在任意两个进程间通信

无名管道

无名管道主要应用于父进程间的通信。
无名管道的创建:pipe(),成功返回0,失败返回-1.
int pipe(int fds[2]);fds[0]是管道读端的描述符,fds[1]是管道写端的描述符。主要在父子进程间通信使用。
举例:在这里插入图片描述

文件描述符复制

dup 重定向,

int fd=open("a.txt",O_WRONLY|O_CREAT.0600);
dup(fd);

将fd复制一份,分配给文件表中未被使用的最小的一项。

0stdin
1stdout
2stderr
3a.txt

信号量

基础知识

多个进程访问相同资源引起的冲突。
同步进程:同一时刻,只能有一个进程访问资源。
有一个特殊的变量值为可用资源的数目,其中有两个操作p操作和v操作,p操作获取资源-1,v操作获取资源+1.信号值为0,可用资源为0,p操作会被阻塞,v操作不会被阻塞。
我们可以举例理解: 有试衣间三个,数字3便是那个特殊的变量,几个人去抢占试衣间,人就相当于进程,当试衣间被占用就会进行p操作-1,当可用试衣间为0就不能进行p操作,用完试衣间让出来就会进行v操作+1.
临界资源:同一时刻只云相册一个进程访问的资源。
临界区:访问临界资源的代码段。

信号量API

semget() :创建或获取已存在信号量。
semget()成功返回信号量的ID,失败返回-1.
库函数:int semget(key_t key,int nsems,int semflag);
key:两个进程使用相同的key值,就可以使用同一个信号量。
nsem:内核维护的是一个信号量集,在新建信号量时,其指定信号量机中信号量的个数。
semflag可选:IPC_CREAT IPC_EXCL

semop() P,V操作,IPC_UNDO
p() 获取资源,程序异常终止,未释放资源,内核释放
IPC_NOWWAIT 打印错误信息。
semop()成功返回0,失败返回-1.
库函数:int semop(int semid,struct sembuf* sops,unsigned nsops);
struct sembuf{
unsigned short sem_num;//指定信号量集中的信号量下标
short sem_op;//其值为-1,代表p操作,其值为-1代表V操作
short sem_flg;//SEM_UNDO
}

semctl() 对信号量初始化 ,删除
控制信号量,semctl()成功返回0,失败返回-1,cmd选项:SETCAL IPC_RMID
union semun{
int val;
strucr semid_ds* buf;
unsigned short* array;
struct seminfo* _buf;
}
库函数:int semctl(int semid,int semnum,int cmd,……);

SETVAL IPC_RMID

ipcs:可以查看消息队列,共享内存,信号量的使用,使用ipcrm可以进行删除操作。
在这里插入图片描述

代码举例

进程a和进程b模拟访问打印机,进程a输出第一个字符‘A’,表示开始使用打印机,输出第二个‘A’表示结束使用,b进程操作同a一样。(肯定不能打印出ABAB之类穿插的字母,因为一个打印机只能同时被一个进程访问)
a.c:在这里插入图片描述
b.c:在这里插入图片描述
sem.h:在这里插入图片描述
sem.c:在这里插入图片描述
运行结果:在这里插入图片描述

共享内存

基础知识

共享内存原理:多个进程在物理内存上有内存空间是共享的,多个进程在各自的逻辑地址空间写入数据,或获取数据,使用同一个空间,不需要数据的拷贝。

在这里插入图片描述

基础函数

int shmget (key_t key,size_t size,int shmflg);用于创建或者获取共享内存
返回共享内存的ID,失败返回1。key:不同的进程使用相同的key值可以获取到同一个共享内存。size:创建共享内存时,指定要申请的共享内存空间大小。shmflg:IPC_CREAT IPC_EXCL

void* shmat(int shmid,const void* shmaddr,int shmflg);//将申请的共享内存的物理内存映射到当前进程的虚拟地址空间上。成功返回共享内存的首地址,失败返回NULL。shmaddr:一般给NULL,由系统自动选择映射的虚拟地址空间。shmflg:一般给0.可以给SHM_RDONLY 为只读模式,其他的为读写模式

int shmdt(const void* shmaddr);断开当前进程的shmaddr指向的共享内存映射。成功返回0,失败返回-1.

int shmctl(int shmid,int cmd,struct shmid_ds *buf);//控制共享内存。成功返回0,失败返回-1。cmd:IPC_RMID。

代码举例

a.c:写入 b.c:读取
a.c:在这里插入图片描述
b.c:在这里插入图片描述
sem.c:在这里插入图片描述
在这里插入图片描述
sem.h:在这里插入图片描述
共享内存本身没有同步控制,共享内存与信号量相结合和以实现同步控制。

消息队列

消息队列

类似于队列,将消息存入队列中,然后从队列中读取元素。
在这里插入图片描述

基础函数

int msgget(key_t key,int msqflg);//创建或者获取一个消息队列。成功返回消息队列ID,失败返回-1。meqflg:IPC_CREAT。

int msgsnd(int msqid,const void* msqp,size_t msqsz,int msqflg);//发送一条消息,消息结构体:

struct msgbuf {
	long mtype;
	char mtext[1];
};

msgsnd()成功返回0,失败返回-1。msqsz:指定mtext中有效数据的长度。msqflg:一般设置为0可以设置IPC_NOWAII

ssize_t msgrcv(int msqid,void* msgp,size_t msqsz,long msqtyp,int msqflg);//接收一条消息。成功返回mtext中接收到的数据长度,失败返回-1。msqtyp:指定接收的消息类型,类型可以为0 。msqflg:一般设置为0可以设置IPC_NOWAIT

int msgctl(int msqid,int cmd,struct msqid_ds* buf);控制消息队列。成功返回0,失败返回-1。cmd:IPC_RMID.

代码举例

a.c:写入数据 b.c:读取数据
a.c:在这里插入图片描述
b.c:在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

*闲鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值