目录
例子4 共享内存 创建共享内存段、附加到该内存、打印存储的数据,并最后分离共享内存
例子5 创建和管理共享内存,包括写入数据、等待一段时间(用于模拟数据被其他进程读取或使用的情况),最后清理共享内存资源
例子1 消息队列的创建、消息的接收、发送和队列的删除
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h> // 包含字符串处理函数库
// 定义消息结构体,用于消息队列通信
struct msgbuf {
long mtype; /* 消息类型, 必须大于 0 */
char mtext[256]; /* 消息数据 */
};
int main()
{
// 用于读取消息的结构体
struct msgbuf readBuf;
key_t key;
// 生成IPC键值,使用当前目录下的文件'.'和字符'm'作为输入
key = ftok(".", 'm');
printf("key=%x\n", key); // 打印生成的键值,用于调试
// 创建或获取消息队列,权限设置为0777,允许任何用户读写
int msgId = msgget(key, IPC_CREAT | 0777);
if(msgId == -1 ){
printf("get queue failure\n"); // 如果消息队列创建或获取失败,输出错误消息
return -1; // 出错退出
}
// 清空读取缓冲区
memset(&readBuf, 0, sizeof(struct msgbuf));
// 从消息队列接收类型为888的消息,不使用任何特殊选项
msgrcv(msgId, &readBuf, sizeof(readBuf.mtext), 888, 0);
printf("read from queue: %s\n", readBuf.mtext); // 打印接收到的消息内容
// 设置发送消息的结构体,消息类型为988,内容为"thank you for reach"
struct msgbuf sendBuf = {988, "thank you for reach"};
// 发送消息到消息队列
msgsnd(msgId, &sendBuf, strlen(sendBuf.mtext), 0);
// 删除消息队列
msgctl(msgId, IPC_RMID, NULL);
return 0;
}
例子2 创建消息队列,发送一条消息,接收回应消息
#include <stdio.h> // 包含标准输入输出函数库
#include <sys/types.h> // 包含系统数据类型定义
#include <sys/ipc.h> // 包含IPC(进程间通信)相关的头文件
#include <sys/msg.h> // 包含消息队列相关的函数声明和数据结构
#include <string.h> // 包含字符串处理函数库
// 定义消息结构体,用于消息队列通信
struct msgbuf {
long mtype; /* 消息类型, 必须大于 0 */
char mtext[256]; /* 消息数据 */
};
int main()
{
struct msgbuf sendBuf = {888, "this is message from queue"}; // 发送消息的结构体
struct msgbuf readBuf; // 读取消息的结构体
// 初始化读取缓冲区
memset(&readBuf, 0, sizeof(struct msgbuf));
// 生成IPC键值,使用当前目录下的文件'.'和字符'm'作为输入
key_t key = ftok(".", 'm');
printf("key=%x\n", key); // 打印生成的键值,用于调试
// 创建或获取消息队列,权限设置为0777,允许任何用户读写
int msgId = msgget(key, IPC_CREAT | 0777);
if(msgId == -1) {
printf("get queue failure\n");
return -1; // 如果消息队列创建或获取失败,输出错误消息并退出程序
}
// 向消息队列发送消息
msgsnd(msgId, &sendBuf, strlen(sendBuf.mtext), 0); // 不使用任何特殊选项
printf("send over\n");
// 从消息队列接收类型为988的消息,不使用任何特殊选项
msgrcv(msgId, &readBuf, sizeof(readBuf.mtext), 988, 0);
printf("return from get: %s\n", readBuf.mtext); // 打印接收到的消息内容
// 删除消息队列
msgctl(msgId, IPC_RMID, NULL);
return 0; // 程序正常结束
}
例子3 父进程等待子进程释放信号量才继续运行,同步
#include <stdio.h> // 包含标准输入输出函数库
#include <sys/types.h> // 包含系统数据类型定义
#include <sys/ipc.h> // 包含IPC(进程间通信)相关的头文件
#include <sys/sem.h> // 包含System V信号量相关的函数声明和数据结构
// 为semctl定义的union,用于设置信号量的值
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux-specific) */
};
// P操作函数:尝试获取信号量
void pGetKey(int id)
{
struct sembuf set;
set.sem_num = 0; // 信号量编号
set.sem_op = -1; // 操作类型为减1,表示获取信号量
set.sem_flg = SEM_UNDO; // 在进程终止时撤销操作
semop(id, &set, 1); // 执行操作
printf("get key\n"); // 打印获取信号量的信息
}
// V操作函数:释放信号量
void vPutBackKey(int id)
{
struct sembuf set;
set.sem_num = 0; // 信号量编号
set.sem_op = 1; // 操作类型为加1,表示释放信号量
set.sem_flg = SEM_UNDO; // 在进程终止时撤销操作
semop(id, &set, 1); // 执行操作
printf("put back the key\n"); // 打印释放信号量的信息
}
int main(int argc, char const *argv[])
{
key_t key;
int semid;
key = ftok(".", 2); // 生成IPC键值
semid = semget(key, 1, IPC_CREAT | 0666); // 获取或创建一个信号量
union semun initsem;
initsem.val = 0;
semctl(semid, 0, SETVAL, initsem); // 初始化信号量的值为0
int pid = fork(); // 创建子进程
if(pid > 0){
// 父进程
pGetKey(semid); // 获取信号量
printf("this is father\n");
vPutBackKey(semid); // 释放信号量
semctl(semid, 0, IPC_RMID, NULL); // 删除信号量
}
else if(pid == 0){
// 子进程
printf("this is child\n");
vPutBackKey(semid); // 释放信号量
}else{
// fork失败
printf("fork error\n");
}
return 0;
}
例子4 共享内存 创建共享内存段、附加到该内存、打印存储的数据,并最后分离共享内存
#include <sys/ipc.h> // 包含IPC标准头文件,用于键值的生成等
#include <sys/shm.h> // 包含System V共享内存功能相关的头文件
#include <stdlib.h> // 包含标准库函数,如exit
#include <stdio.h> // 包含标准输入输出函数
#include <string.h> // 包含字符串处理函数
int main()
{
int shmid; // 共享内存标识符
char *shmaddr; // 指向共享内存的指针
key_t key; // IPC键
key = ftok(".", 1); // 使用ftok生成一个唯一键值,当前目录作为路径,1作为项目标识符
// 请求访问键值为key的共享内存,大小为4096字节(1024*4),权限标志为0(只获取不创建)
shmid = shmget(key, 1024 * 4, 0);
if (shmid == -1) {
printf("shmget noOk\n"); // 如果获取共享内存失败,打印错误消息
exit(-1); // 退出程序
}
// 将共享内存附加到进程的地址空间
shmaddr = shmat(shmid, 0, 0); // 第二个参数是指定内存附加到进程空间的地址(0表示系统选择)
if (shmaddr == (void*) -1) {
printf("shmat error\n"); // 附加失败
exit(-1);
}
printf("shmat ok\n"); // 打印附加成功消息
printf("data: %s\n", shmaddr); // 打印共享内存中的数据
// 将共享内存从当前进程的地址空间分离
shmdt(shmaddr);
printf("quit\n"); // 打印退出消息
return 0; // 正常退出程序
}
例子5 创建和管理共享内存,包括写入数据、等待一段时间(用于模拟数据被其他进程读取或使用的情况),最后清理共享内存资源
#include <sys/ipc.h> // 包含IPC标准头文件,用于键值的生成等
#include <sys/shm.h> // 包含System V共享内存功能相关的头文件
#include <stdlib.h> // 包含标准库函数,如exit
#include <stdio.h> // 包含标准输入输出函数
#include <string.h> // 包含字符串处理函数
#include <unistd.h> // 包含常用的系统调用函数,如sleep
int main()
{
int shmid; // 共享内存标识符
char *shmaddr; // 指向共享内存的指针
key_t key; // IPC键
key = ftok(".", 1); // 使用ftok生成一个唯一键值,当前目录作为路径,1作为项目标识符
// 创建共享内存,大小为4KB,权限设置为0666,并设置IPC_CREAT标志以确保如果不存在则创建
shmid = shmget(key, 1024 * 4, IPC_CREAT | 0666);
if (shmid == -1) {
printf("shmget noOk\n"); // 如果获取共享内存失败,打印错误消息
exit(-1); // 退出程序
}
// 将共享内存附加到进程的地址空间
shmaddr = shmat(shmid, 0, 0); // 第二个参数是指定内存附加到进程空间的地址(0表示系统选择)
if (shmaddr == (void *) -1) {
printf("shmat error\n"); // 附加失败
exit(-1);
}
printf("shmat ok\n"); // 打印附加成功消息
// 将字符串 "chenlichen" 复制到共享内存中
strcpy(shmaddr, "helloworld");
// 休眠5秒,模拟等待其他进程/线程读取或操作这段共享内存
sleep(5);
// 将共享内存从当前进程的地址空间分离
shmdt(shmaddr);
// 删除共享内存段
shmctl(shmid, IPC_RMID, 0);
printf("quit\n"); // 打印退出消息
return 0; // 程序正常结束
}