Linux之进程间通信之消息队列,共享内存,信号量

消息队列

消息队列的结构有很多,但在这里讲的队列的结构都是基于链表实现的.

进程间通信的实质是:让不同的进程可以看到相同的资源.

消息队列的特点:

  • 消息队列的通信是通过发送有类型数据块的方法.
  • 每个数据块都有一个类型,接收方接受的数据块可以有不同的类型值.
  • 消息队列的最大长度有限制.(缺点,因为消息队列必定要占用内存,而如果只发送不接受就会耗内存.)

所以:消息队列提供了一个进程向另一个进程发送了有类型数据块的方法.

实现消息队列的相关函数:
#include 
#include 
key_t ftok(const char *pathname, int proj_id);
函数作用:为创建消息队列的函数提供参数.
注意:对于这个函数,若函数的参数相同,则函数的返回值相同.

①创建消息队列的函数:
int msgget(key_t key,int msgflg);
msgflg:与文件的权限mode是相同的.
常用的参数有:
IPC_CREAT:不存在就创建,若存在就打开.
IPC_EXCL:若存在,就失败.与上面的搭配使用.
函数创建成功就返回非负整数

②消息队列控制函数
int magctl(int msqid,int cmd,struct msqid_ds *buf);
参数:
    msqid_ds:表示消息队列
    cmd:函数执行的作用:IPC_RMID(删除消息队列)
函数返回值:成功返回0失败返-1;

③把消息添加到消息队列中
int msgsnd(int msqid,const void* msgp,size_t msgsz,int msqflg);

④从一个消息队列中接收消息
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
msgp:指向接受的消息的队列.
msgsz:消息队列的长度.
msgtyp:可以实现接收优先级.若为0,就是普通的队列.

查看消息队列的指令:ipcs -q
手动删除某个消息队列:ipcrm -q 进程id

这里是简单的消息队列的实现,若需要,请戳

总结消息队列:
1. 全双工的通信方式.
2. 面向数据块.
3. 内置同步互斥机制.
4. 声明周期随内核.(可以通过手动删除和重启来删除一个消息队列).
5. 可以用于任意进程.

共享内存

每个进程都有自己的虚拟内存空间,而物理空间只有一份,当多个进程映射到相同的物理地址后,那么就可以共同访问这块内存.即共享内存.
蹦蹦蹦:共享内存是最快的进程间通信的方式(省略了两次内存拷贝).但是同时也是不稳定的,由于共同访问同一块内存,会产生不可预知的错误.

实现共享内存调用的相关函数:
int shmget(key_t key,size_t size,int shmget);
key:共享内存段的名字.
size:共享内存的大小.(按页的大小向上取整.一般而言页的大小为4K)
shmflg:与消息队列的那个参数相同.

void* shmat(int shmid,const void* shmaddr,int shmflg);
shmaddr:共享内存连接的地址.
成功返回一个指向共享内存的第一个指针,失败返回-1.

int shmctl(int shmid,int cmd,struct_ds *buf);
cmd:与消息队列中的那个参数相同.
buf:指向一个保存着共享内存的模式状态和访问权限的数据结构.

共享内存的简单实现,若需要请戳

总结共享内存:
1. 双向通信全双工.
2. 用于任意进程间的通信方式.
3. 不存在”面向数据报”和”面向字节流”.
4. 没有同步互斥机制.
5. 生命周期随内核.

信号量

为什么要有信号量的通信方式?
消息队列,共享内存以及管道都是可以同时又多个进程去访问公共资源,可能会引发一系列的问题.而信号量是为了通过控制其他的通信的公共资源来实现进程间通信.信号量则会负责数据操作的同步,互斥等.

信号量的同步指的是所有的进程按照一定的顺序去执行任务,实现对资源的有序访问.
信号量的互斥指的是当有一个进程在临界区时,其余的进程只能等待,等待那个进程出了临界区.

信号量的PV操作
这里的信号量指的是二元信号量,非0即1.
P操作:申请使用临界资源,信号量减一;
V操作:释放临界资源,信号量加一.

简单的实现信号量的代码,若需要请戳

注意:消息队列,共享内存以及信号量都是基于system V版本的进程间通信的方式.

你可能感兴趣的:(C+,进程间通信,消息队列,共享内存,信号量)