//reader_writer.c
//reader_writer.c
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
#include <error.h>
#include <stdlib.h>
#include <wait.h>
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/sem.h>
/*
功能:写者写完通知读者读取
读者读完通知写者再写
共享资源为共享内存
*/
typedef struct{
int value;
int semid;
}Storage;
union semun{
int val;
struct semid_ds *buf;
unsigned short *array;
};
/*
struct sembuf{
unsigned short sem_num;//信号量集中信号量的编号(即哪个信号量),0代表第1个信号量
short sem_op;
short sem_flg;
}
*/
void writer(Storage *s)
{
int i = 0;
//int semop(int semid, struct sembuf *sops, unsigned nsops)
struct sembuf v_s1 = {0, 1, SEM_UNDO};
struct sembuf p_s2 = {1, -1, SEM_UNDO};
for(; i < 10; i++){
s->value = i;
printf("writer write %d from sharememery\n",s->value);
sleep(1);
semop(s->semid, &v_s1, 1);
semop(s->semid, &p_s2, 1);
}
return ;
}
void reader(Storage *s)
{
int i = 0;
struct sembuf p_s1 = {0, -1, SEM_UNDO};
struct sembuf v_s2 = {1, 1, SEM_UNDO};
for(; i < 10; i++){
semop(s->semid, &p_s1, 1);
s->value = i;
printf("reader read %d from sharememery\n",s->value);
sleep(1);
semop(s->semid, &v_s2, 1);
}
return ;
}
int main()
{
//int shmget(key_t key, size_t size, int shmflg);
key_t key = ftok("/etc/passwd",1);
int shmid = shmget(key, sizeof(Storage), IPC_CREAT | IPC_EXCL | 0664);
if(shmid < 0){
perror("shmget failed");
}
//void *shmat(int shmid, const void *shmaddr, int shmflg);
Storage *s = (Storage *)shmat(shmid, 0, 0);
if(s == (Storage *)-1){
perror("shmat failed");
}
s->value = 0;
//int semget(key_t key, int nsems, int semflg) 创建信号量集,nsems表示有多少个信号量
s->semid = semget(key, 2, IPC_CREAT | IPC_EXCL | 0664);
if(s->semid < 0){
perror("semget failed");
}
//int semctl(int semid,int semnum,int cmd,.../*union semun arg*/)初始化信号量集,semnum = 0:表示全部的信号量
union semun un;
un.array[0] = 0;
un.array[1] = 0;//给两个信号量赋初值为0
if(semctl(s->semid, 0, SETALL, un) < 0){
perror("semctl failed");
}
pid_t pid = fork();
if(pid < 0){
perror("fork failed");
}else if(pid == 0){//child process writer
writer(s);
//解除共享内存
if(shmdt(s) < 0){
perror("shmdtc failed");
}
}else{//father process reader
reader(s);
wait(NULL);
//删除信号量集
if(semctl(s->semid, 0, IPC_RMID, NULL) < 0){
perror("semctl rm failed");
}
//解除共享内存映射
if(shmdt(s) < 0){
perror("shmdtf failed");
}
//删除共享内存
if(shmctl(shmid, IPC_RMID, 0) < 0){
perror("shmctl failed");
}
}
return 0;
}