目录
例子1 消息队列的创建、消息的接收、发送和队列的删除
例子2 创建消息队列,发送一条消息,接收回应消息
例子3 父进程等待子进程释放信号量才继续运行,同步
例子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); // 初始化信号量的值为0int 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> // 包含常用的系统调用函数,如sleepint 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; // 程序正常结束
}