代码要求:
- 利用shmget()创建共享内存;
- 利用shmat()建立共享内存与进程之间的关联;
- 用fork()创建子进程,子进程与父进程共享存储空间;
- 利用信号量机制实现子进程读入数据到共享内存,父进程取出共享内存中的数据保存到文件,完成通信;
- 调用shmdt()断开共享内存连接;
- 调用shmctl()释放共享内存;
- 有注释,能在ubuntu上运行
代码要求:
可参考
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#define SHM_SIZE 1024
// 定义共享内存结构体
typedef struct {
int flag; // 标志位,0表示共享内存空闲,1表示共享内存已被写入数据
char buf[SHM_SIZE]; // 数据缓冲区
} shm_data_t;
// 定义信号量结构体
typedef union {
int val;
struct semid_ds *buf;
unsigned short *array;
} sem_union_t;
// 定义信号量变量
static int sem_id;
// 定义P操作函数
static int sem_p(int sem_id) {
struct sembuf sem_op = {0, -1, SEM_UNDO};
return semop(sem_id, &sem_op, 1);
}
// 定义V操作函数
static int sem_v(int sem_id) {
struct sembuf sem_op = {0, 1, SEM_UNDO};
return semop(sem_id, &sem_op, 1);
}
int main() {
int shmid;
void *shmaddr;
pid_t pid;
shm_data_t *shm_data;
sem_union_t sem_union;
// 创建共享内存
if ((shmid = shmget(IPC_PRIVATE, sizeof(shm_data_t), IPC_CREAT|0666)) < 0) {
perror("shmget error");
exit(1);
}
// 建立共享内存与进程之间的关联
if ((shmaddr = shmat(shmid, NULL, 0)) == (void *)-1) {
perror("shmat error");
exit(1);
}
// 初始化共享内存
shm_data = (shm_data_t *)shmaddr;
shm_data->flag = 0;
// 创建信号量
if ((sem_id = semget(IPC_PRIVATE, 1, IPC_CREAT|0666)) < 0) {
perror("semget error");
exit(1);
}
// 初始化信号量
sem_union.val = 1;
if (semctl(sem_id, 0, SETVAL, sem_union) < 0) {
perror("semctl error");
exit(1);
}
// 创建子进程
if ((pid = fork()) < 0) {
perror("fork error");
exit(1);
} else if (pid == 0) { // 子进程
int i = 0;
char buf[SHM_SIZE];
while (1) {
sem_p(sem_id); // P操作
// 如果共享内存空闲,写入数据
if (shm_data->flag == 0) {
sprintf(buf, "This is data %d from child process.\n", ++i);
strncpy(shm_data->buf, buf, SHM_SIZE);
shm_data->flag = 1;
}
sem_v(sem_id); // V操作
sleep(1); // 等待1秒钟
}
} else { // 父进程
FILE *fp;
char buf[SHM_SIZE];
// 打开文件
if ((fp = fopen("output.txt", "w")) == NULL) {
perror("fopen error");
exit(1);
}
while (1) {
sem_p(sem_id); // P操作
// 如果共享内存已被写入数据,从共享内存中读取数据并保存到文件中
if (shm_data->flag == 1) {
strncpy(buf, shm_data->buf, SHM_SIZE);
fprintf(fp, "%s", buf);
shm_data->flag = 0;
}
sem_v(sem_id); // V操作
sleep(1); // 等待1秒钟
}
// 关闭文件
fclose(fp);
}
// 断开共享内存连接
if (shmdt(shmaddr) < 0) {
perror("shmdt error");
exit(1);
}
// 释放共享内存
if (shmctl(shmid, IPC_RMID, 0) < 0) {
perror("shmctl error");
exit(1);
}
// 释放信号量
if (semctl(sem_id, 0, IPC_RMID, sem_union) < 0) {
perror("semctl error");
exit(1);
}
return 0;
}