消息队列的结构有很多,但在这里讲的队列的结构都是基于链表实现的.
进程间通信的实质是:让不同的进程可以看到相同的资源. |
消息队列的特点:
所以:消息队列提供了一个进程向另一个进程发送了有类型数据块的方法.
实现消息队列的相关函数:
#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版本的进程间通信的方式.