导航
当前章节:管道
原文链接:进程间通信IPC
上一章节:线程
下一章节:网络通信socket
目录:Linux程序设计
IPC
介绍
IPC代表进程间通信。它指的是不同进程之间可以相互通信的机制。
Linux中一些常见的IPC方法包括:pipe,share memory,message queue, semaphores,signal,socket
管道,信号量我们上文已经了解了,本节主要了解消息队列、共享内存以及支持不同进程间的信号量机制。socket在下一节单独学习。
message queue
消息队列是Linux中进程间通信的一种方法。它们允许进程以数据块的形式交换消息。
消息队列有mquque和sys/msg、sys/ipc两种实现
mquque
关于消息队列的一些关键点:
1. 使用mq_open()创建。这指定了最大消息大小、消息数量等属性。
2. 使用mq_send()将消息写入队列,并使用mq_receive()从队列中读取消息。
3. 消息按写入顺序(FIFO)从队列中读取。
4. 每条消息都有一个优先级,优先级较高的消息在优先级较低的消息之前读取。
5. 消息将保留在队列中直到被读取。队列将在mq_send()块之前容纳最大数量的消息。
6. 打开队列时,消息具有指定的最大大小。较大的邮件将被拒绝。
7. 消息队列由文件系统中的一个名称标识。
8. 进程必须具有对队列的读取和/或写入访问权限才能使用它。在打开队列时指定访问权限。
ipc msg https://blog.csdn.net/guoping16/article/details/6584024
创建msg:int msgget(key_t key, int msgflg);
1.key-用于标识消息队列的密钥。这可以是任意整数,也可以是预定义值之一:
-IPC_PRIVATE-专用队列,不由密钥标识
-IPC_RMID-删除带有此密钥的消息队列
-IPC_CREAT-如果消息队列不存在,则创建该队列
2.msgflg-队列的权限标志。应为0666,以允许所有用户进行读/写访问。
IPC_CREAT也可以与此进行“或”运算,以在队列不存在的情况下创建队列。接收
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long int msgtype, int msgflg);
msgrcv(qid, buf, sizeof(buf), 0, MSG_NOERROR);
出错:-1,错误原因存于error中
成功:实际读取到的消息数据长度
1.msqid-消息队列标识符
2.msgp-指向接收消息缓冲区的指针
3.msgsz-缓冲区的大小(以字节为单位)
4.消息类型-要接收的消息类型(0接收第一条消息)
5.msgflg-消息标志(MSG_NOERROR允许接收截断的消息)
0: 阻塞式接收消息,没有该类型的消息msgrcv函数一直阻塞等待
IPC_NOWAIT:如果没有返回条件的消息调用立即返回,此时错误码为ENOMSG
IPC_EXCEPT:与msgtype配合使用返回队列中第一个类型不为msgtype的消息
IPC_NOERROR:如果队列中满足条件的消息内容大于所请求的size字节,则把该消息截断,截断部分将被丢弃发送
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
msgsnd(qid, msg, sizeof(msg), 0);
成功:0
出错:-1,错误原因存于error中
1.msqid-由msgget()返回的消息队列标识符
2.msgp-指向消息缓冲区的指针
3.msgsz-消息的大小(以字节为单位)
4.msgflg-消息标志(通常为0)
0:当消息队列满时,msgsnd将会阻塞,直到消息能写进消息队列
IPC_NOWAIT:当消息队列已满的时候,msgsnd函数不等待立即返回
IPC_NOERROR:若发送的消息大于size字节,则把该消息截断,截断部分将被丢弃,且不通知发送进程。
4.控制
int msgctl(int msqid, int cmd, struct msqid_ds *buf)
- IPC_STAT-使用队列详细信息填充buf
- IPC_SET-从buf设置队列详细信息
- IPC_RMID-删除消息队列
5.提醒
- qid一般不会为0,如果为0注意qid不会报错且有可能是直接被条件语句赋值了
- 发和收传入参数大小为消息大小,消息结构首个必须为long类型作为类别,且消息类别要求大于0
差异
但总的来说,它们提供了非常相似的消息队列功能,具有相同的基本使用模式。主要的区别是句法上的。
share memory
共享内存允许多个进程访问同一内存区域。这是流程进行通信和共享数据的一种有用方式。
关于共享内存的一些关键点:
- 它由一个进程分配,并且可以由多个其他进程访问。
- 进程连接到共享内存和从共享内存分离,但它会一直存在,直到明确删除为止。
- 共享内存由一个密钥和创建者过程来标识。其他进程使用该密钥连接到同一共享内存。
- 可以设置权限来控制哪些用户/进程可以访问。
- 大小是在创建共享内存时设置的,并且不会更改。进程必须确保它们的写入不会超过分配的大小。
- 进程可以直接读取和写入共享内存,而无需协调或发送消息。
- 不能使用标准文件I/O功能(读、写)。提供了特殊的共享内存功能。
- 比使用文件系统进行IPC更快,因为内核不需要在进程和文件系统之间复制数据。
创建
int shmget(key_t key, size_t size, int shmflg);
int shm_id = shmget(IPC_PRIVATE, 1024, 0666 | IPC_CREAT);
key为唯一序列,shmflg与open参数类似,指定IPC_CREATE和文件权限,创建失败返回-1,否则返回共享内存文件标识符连接
void *shmat(int shmid, const void shmaddr, int shmflg);
void shm_ptr = shmat(shm_id, NULL, 0);
- 链接成功返回一个指向内存的指针shm_ptr,失败返回-1
- 它用于连接到现有的共享内存段,以便您可以访问它。
- shmid指定从shmget()获得的段的ID。
- shaddr通常为NULL,表示系统应该选择一个可用的地址。
- shmflg通常为0。其他标志包括:
SHM_RDONLY-附加只读
SHM_REMAP-替换同一内存区域的任何现有映射 - shmat()返回的指针可以被取消引用,并像普通指针一样用于访问共享内存。
- 在使用shmctl(IPC_RMID)删除共享内存之前,所有进程都必须从共享内存中分离。
解除指针连接
shmdt(shm_ptr);移除共享内存
shmctl(shm_id, IPC_RMID, NULL);