/*
名称:有名信号量实现读者-写着问题(写者优先)
说明:本实验实现的是写者优先的读者写者问题。和读者优先类似,写者优先是当读者写者在同时申请访问文件时(如果有写者正在写入文件),那么其他写者能更容易的访问到文件(因为“它不用排队”,即在本实验中不用等待queue信号量)。
打个不确切的比方,就像是“读者”和“写者”两个人去买票,本应该老老实实都该排队。但如果“写者”在队伍的前面有熟人(有其他写者正在写入),那么它就可以不用在后面等,类似于插个队(插在熟人写者后面),等熟人写者买完票之后,它就可以买票。这就是写者优先。
读者优先也类似,不同的是,读者在买票的过程中如果遇到熟人,它就可以和熟人一起买票(同时访问文件)。
具体实现的算法,和以前写的“读者优先类似”。需要有一个保存正在访问,更确切的说是等待“队伍”前面的写者人数,如果这个变量不等于0,则其他写者不用等待queue信号量。(不用排队)。
而对于读者,每次访问文件都得老老实实申请queue信号量(排队)。
*/
读者:
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
#define SIZE 4096
//创建模式权限
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
int main(int argc,char **argv)
{
sem_t * mut_cou = NULL; /* 用于读者数量的互斥访问*/
sem_t * rw = NULL; //用于读者和写着之间互斥访问共享文件
sem_t * queue = NULL; //排队信号量
int *rea_cou = NULL; //共享的变量,用于保存当前读者的人数
char * sha_buf = NULL; //共享缓冲区,模拟共享文件
int shm_fd = 0; //用于映射共享内存
int wait_time = 0;
pid_t pid = getpid();
//创建mutex_count信号量,初始值为1
if((mut_cou = sem_open("mutex_count",O_CREAT,FILE_MODE,1)) == SEM_FAILED)
{
printf("sem_open 1 %s Error\n",argv[0]);
exit(-1);
}
//创建rw信号量,初始值为1
if((rw = sem_open("rw",O_CREAT,FILE_MODE,1)) == SEM_FAILED)
{
printf("sem_open 2 %s Error\n",argv[0]);
exit(-1);
}
//创建排队信号量,初始值为1
if((queue = sem_open("queue",O_CREAT,FILE_MODE,1)) == SEM_FAILED)
{
printf("sem_open 3 %s Error\n",argv[0]);
exit(-1);
}
//创建共享内存空间
shm_fd = shm_open("buf", O_CREAT | O_RDWR, 0666);
ftruncate(shm_fd,SIZE);
sha_buf =(char*) mmap(0,SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
if (sha_buf == MAP_FAILED) {
printf("Map buf failed\n");
return -1;
}
//创建共享变量(读者数量)内存空间
/* create the shared memory segment */
shm_fd = shm_open("rea_cou", O_CREAT | O_RDWR, 0666);
/* configure the size of the shared memory segment */
ftruncate(shm_fd,1);
/* now map the shared memory segment in the address space of the process */
rea_cou = (int *)mmap(0,SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
if (rea_cou == MAP_FAILED) {
printf("Map count failed\n");
return -1;
}
while(1)
{
sem_wait(queue); //申请排队信号量
sem_wait(mut_cou); //申请访问变量rea_cou(正在读文件的人数)
if(0 == *rea_cou) //如果当前人数为0,则要申请互斥信号量rw
sem_wait(rw);
++(*rea_cou); //读者+1
sem_post(mut_cou); //释放变量访问锁
sem_post(queue);
printf("I am reader process .My pid is %d.",pid);
printf("I am reading the file.And the content is %s\n",sha_buf);
sem_wait(mut_cou); //申请访问变量rea_cou,准备修改rea_cou
--(*rea_cou); //读者-1
if(0 == (*rea_cou)) //如果是最后一个读者的话,则释放共享文件访问锁
sem_post(rw);
sem_post(mut_cou); //释放变量访问锁
wait_time = rand()%5;
sleep(wait_time); //随机休息
}
return 0;
}
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
#define SIZE 4096
//创建模式权限
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
int main(int argc,char **argv)
{
sem_t * mut_cou = NULL; /* 用于读者数量的互斥访问*/
sem_t * rw = NULL; //用于读者和写着之间互斥访问共享文件
sem_t * queue = NULL;
int * wr_cou;
int *rea_cou = NULL; //共享的变量,用于保存当前读者的人数
char * sha_buf = NULL; //共享缓冲区,模拟共享文件
int shm_fd = 0; //用于映射共享内存
int wait_time = 0;
pid_t pid = getpid();
//创建mutex_count信号量,初始值为1
if((mut_cou = sem_open("mutex_count",O_CREAT,FILE_MODE,1)) == SEM_FAILED)
{
printf("sem_open 1 %s Error\n",argv[0]);
exit(-1);
}
//创建rw信号量,初始值为1
if((rw = sem_open("rw",O_CREAT,FILE_MODE,1)) == SEM_FAILED)
{
printf("sem_open 2 %s Error\n",argv[0]);
exit(-1);
}
//创建排队信号量,初始值为1
if((queue = sem_open("queue",O_CREAT,FILE_MODE,1)) == SEM_FAILED)
{
printf("sem_open 3 %s Error\n",argv[0]);
exit(-1);
}
//创建共享内存空间
/* create the shared memory segment */
shm_fd = shm_open("buf", O_CREAT | O_RDWR, 0666);
/* configure the size of the shared memory segment */
ftruncate(shm_fd,SIZE);
/* now map the shared memory segment in the address space of the process */
sha_buf =(char*) mmap(0,SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
if (sha_buf == MAP_FAILED)
{
printf("Map buf failed\n");
return -1;
}
//创建共享变量(读者数量)内存空间
/* create the shared memory segment */
shm_fd = shm_open("rea_cou", O_CREAT | O_RDWR, 0666);
/* configure the size of the shared memory segment */
ftruncate(shm_fd,1);
/* now map the shared memory segment in the address space of the process */
rea_cou = (int *)mmap(0,SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
if (rea_cou == MAP_FAILED) {
printf("Map count failed\n");
return -1;
}
//创建共享变量(写者数量)内存空间
shm_fd = shm_open("wr_cou", O_CREAT | O_RDWR, 0666);
ftruncate(shm_fd,1);
wr_cou = (int *)mmap(0,SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
if (wr_cou == MAP_FAILED) {
printf("Map count failed\n");
return -1;
}
while(1)
{
sem_wait(rw); //申请访问文件
if(0 == *wr_cou) //如果是第一个写者,则需要排队。
sem_wait(queue);
++(*wr_cou); //写者人数加1
printf("I am %d writer.I am writing to the file.\n",pid);
sprintf(sha_buf,"%d writer recorded the infomation",pid);
--(*wr_cou); //写者人数减1
if(0 == *wr_cou ) //如果是最后一个写者则释放queue
sem_post(queue);
sem_post(rw);
wait_time = rand()%5;
sleep(wait_time); //随机休息
}
return 0;
}