10.共享内存 信号量集 消息队列
- **1. IPC对象操作通用框架**
- **2. 共享内存(Shared Memory)**
- **3. 信号量集(Semaphore)**
- **4. 消息队列(Message Queue)**
- **5. 练习与作业**
- **6. 总结**
1. IPC对象操作通用框架
- 操作流程:
- 生成唯一键值(
ftok):key_t ftok(const char *pathname, int proj_id);- 功能:通过路径和项目ID生成唯一键值。
- 参数:
pathname:文件路径。proj_id:项目ID(通常为ASCII字符)。
- 返回值:成功返回键值,失败返回
-1。
- 申请IPC对象:
- 共享内存:
shmget。 - 信号量集:
semget。 - 消息队列:
msgget。
- 共享内存:
- 操作IPC对象:
- 共享内存:
shmat、shmdt。 - 信号量集:
semop。 - 消息队列:
msgsnd、msgrcv。
- 共享内存:
- 删除IPC对象:
- 共享内存:
shmctl。 - 信号量集:
semctl。 - 消息队列:
msgctl。
- 共享内存:
- 生成唯一键值(
2. 共享内存(Shared Memory)
- 特性:
- 效率最高的进程间通信方式。
- 多个进程可以共享同一块内存区域。
- 操作流程:
- 申请共享内存:
int shmget(key_t key, size_t size, int shmflg);- 功能:申请共享内存。
- 参数:
key:唯一键值。size:共享内存大小。shmflg:权限标志(如IPC_CREAT|0666)。
- 返回值:成功返回共享内存ID,失败返回
-1。
- 映射共享内存:
void *shmat(int shmid, const void *shmaddr, int shmflg);- 功能:将共享内存映射到进程地址空间。
- 参数:
shmid:共享内存ID。shmaddr:映射地址(通常为NULL,由系统分配)。shmflg:映射标志(如0表示读写,SHM_RDONLY表示只读)。
- 返回值:成功返回映射地址,失败返回
(void*)-1。
- 读写共享内存:
- 使用
memcpy、strcpy等函数直接操作映射地址。
- 使用
- 撤销映射:
int shmdt(const void *shmaddr);- 功能:断开共享内存映射。
- 参数:
shmaddr:映射地址。 - 返回值:成功返回
0,失败返回-1。
- 删除共享内存:
int shmctl(int shmid, int cmd, struct shmid_ds *buf);- 功能:删除共享内存。
- 参数:
shmid:共享内存ID。cmd:命令(如IPC_RMID表示删除)。buf:共享内存信息结构体(通常为NULL)。
- 返回值:成功返回
0,失败返回-1。
- 申请共享内存:
3. 信号量集(Semaphore)
- 特性:
- 用于解决共享内存的临界资源访问问题。
- 通过P(
sem_wait)和V(sem_post)操作实现同步。
- 操作流程:
- 申请信号量集:
int semget(key_t key, int nsems, int semflg);- 功能:申请信号量集。
- 参数:
key:唯一键值。nsems:信号量数量。semflg:权限标志(如IPC_CREAT|0666)。
- 返回值:成功返回信号量集ID,失败返回
-1。
- 初始化信号量:
- 使用
semctl初始化信号量值。
- 使用
- P/V操作:
int semop(int semid, struct sembuf *sops, unsigned nsops);- 功能:执行P/V操作。
- 参数:
semid:信号量集ID。sops:操作结构体数组。nsops:操作数量。
- 返回值:成功返回
0,失败返回-1。
- 删除信号量集:
int semctl(int semid, int semnum, int cmd, ...);- 功能:删除信号量集。
- 参数:
semid:信号量集ID。semnum:信号量编号。cmd:命令(如IPC_RMID表示删除)。
- 返回值:成功返回
0,失败返回-1。
- 申请信号量集:
4. 消息队列(Message Queue)
- 特性:
- 用于进程间传递消息。
- 消息以队列形式存储,先进先出(FIFO)。
- 操作流程:
- 申请消息队列:
int msgget(key_t key, int msgflg);- 功能:申请消息队列。
- 参数:
key:唯一键值。msgflg:权限标志(如IPC_CREAT|0666)。
- 返回值:成功返回消息队列ID,失败返回
-1。
- 发送消息:
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);- 功能:发送消息。
- 参数:
msqid:消息队列ID。msgp:消息结构体指针。msgsz:消息大小。msgflg:发送标志(如0表示阻塞)。
- 返回值:成功返回
0,失败返回-1。
- 接收消息:
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);- 功能:接收消息。
- 参数:
msqid:消息队列ID。msgp:消息结构体指针。msgsz:消息大小。msgtyp:消息类型。msgflg:接收标志(如0表示阻塞)。
- 返回值:成功返回消息大小,失败返回
-1。
- 删除消息队列:
int msgctl(int msqid, int cmd, struct msqid_ds *buf);- 功能:删除消息队列。
- 参数:
msqid:消息队列ID。cmd:命令(如IPC_RMID表示删除)。buf:消息队列信息结构体(通常为NULL)。
- 返回值:成功返回
0,失败返回-1。
- 申请消息队列:
5. 练习与作业
- 练习1:使用共享内存完成两个进程间的通信,共享一个数字。
- 练习2:设计两个进程,进程1获取用户输入并写入共享内存,进程2读取共享内存并打印输出,遇到
exit时退出。 - 作业1:封装信号量的P/V操作函数:
int my_sem_wait(int id, int sem); int my_sem_post(int id, int sem); - 作业2:使用信号量集解决共享内存的临界资源访问问题。
6. 总结
- 共享内存:效率最高的IPC方式,适合大数据量传输。
- 信号量集:用于解决共享内存的同步问题。
- 消息队列:适合进程间传递结构化消息。






![Java Swing 基础组件详解 [论文投稿-第四届智能系统、通信与计算机网络]](https://i-blog.csdnimg.cn/direct/2be83f564694413a8070a6f014ec3ef5.png)











