使用system V实现读者写者问题
#include <stdio.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/wait.h> typedef int semophore;
semophore mutex = ;
semophore cnt = ;
semophore db = ;
//char mutex[] = "mutex";
//char db[] = "db";
int semId;
void read(int cnt)
{
fprintf(stdout, "NO.%d reading...\n",cnt);
//for (int i = 0; i < 1000000; i++);
sleep();
fprintf(stdout, "NO.%d read finished.\n",cnt); }
void write()
{
fprintf(stdout, "writing...\n");
//for (int i = 0; i < 1000000; i++);
sleep();
fprintf(stdout, "write finished.\n");
} union semun {
int val;
struct semid_ds *buf;
unsigned short int *array;
struct seminfo *__buf;
};
/*
struct sembuf{ //结构定义在 linux/sem.h,无需重复定义
unsigned short sem_num; //信号在信号集中的索引,0代表第一个信号,1代表第二个信号
short sem_op; //操作类型
short sem_flg; //操作标志
};
*/ /*
void p(const char *s)
{
/*
semun arg;
int tmp;
int r;
if (strcmp(s, mutex) == 0)
{
//fprintf(stdout,"mutex:%d\n",semctl(semId, 0, GETVAL, arg));
while(1){
if(semctl(semId, 0, GETVAL, arg)<=0)
wait(&r);
else break;
}
tmp = semctl(semId, 0, GETVAL, arg);
//if(tmp<=0) waitpid();
arg.val = tmp - 1;
semctl(semId, 0, SETVAL, arg);
}
else if (strcmp(s, db) == 0)
{
//fprintf(stdout,"db:%d\n",semctl(semId, 1, GETVAL, arg));
while(1){
if(semctl(semId, 1, GETVAL, arg)<=0)
wait(&r);
else break;
}
tmp = semctl(semId, 1, GETVAL, arg);
arg.val = tmp - 1;
semctl(semId, 1, SETVAL, arg);
} sembuf arg;
arg.sem_op = 1;
arg.sem_flg = IPC_UNDO;
if(strcmp(s, mutex)==0)
{
arg.sem_num = 0;
semop(semId,&arg,1);
}
else if(strcmp(s, db)==0)
{
arg.sem_num = 1;
semop(semId,&arg,1);
} }
*/
/*
void v(const char *s)
{
/*
semun arg;
int tmp;
if (strcmp(s, mutex) == 0)
{
tmp = semctl(semId, 0, GETVAL, arg);
arg.val = tmp + 1;
semctl(semId, 0, SETVAL, arg);
}
else if (strcmp(s, db) == 0)
{
tmp = semctl(semId, 1, GETVAL, arg);
arg.val = tmp + 1;
semctl(semId, 1, SETVAL, arg);
} sembuf arg;
arg.sem_op = -1;
arg.sem_flg = IPC_UNDO;
if(strcmp(s, mutex)==0)
{
arg.sem_num = 0;
semop(semId,&arg,1);
}
else if(strcmp(s, db)==0)
{
arg.sem_num = 1;
semop(semId,&arg,1);
}
}
*/ //P操作函数
int p(int index)
{
struct sembuf buf = {, -}; if (index < )
{
perror("index of array cannot equals a minus value!\n");
return -;
}
buf.sem_num = index;
if (semop(semId, &buf, ) == -)
{
perror(" a wrong operation to semaphore occurred!\n");
return -;
}
return ;
} //V操作函数
int v(int index)
{
struct sembuf buf = {, }; if (index < )
{
perror("index of array cannot equals a minus value!\n");
return -;
}
buf.sem_num = index;
if (semop(semId, &buf, ) == -)
{
perror(" a wrong operation to semaphore occurred!\n");
return -;
}
return ;
}
void* reader(void* args)
{
p(mutex);
cnt++;
if (cnt == )
{
p(db);
}
v(mutex); read(cnt); p(mutex);
cnt--;
if (cnt == )
{
v(db);
}
v(mutex);
}
void* writer(void* args)
{
p(db);
write();
v(db);
} int main()
{
semun arg; key_t key = ;
if ((key = ftok(".", )) == -)
{
perror("ftok error:");
_exit();
}
semctl(semId, , IPC_RMID, arg); //semid = semget(key, 1, IPC_CREAT|0660); if ((semId = semget(key, , IPC_CREAT | IPC_EXCL | )) >= )
{
arg.val = ;
if (semctl(semId, , SETVAL, arg) < )
{
fprintf(stdout, "semctl error %s\n", strerror(errno));
return -;
}
if (semctl(semId, , SETVAL, arg) < )
{
fprintf(stdout, "semctl error %s\n", strerror(errno));
return -;
} }
else if (errno == EEXIST)
{
semId = semget(key, , );
//fprintf(stdout,"Taskr :: errno==EEXIST\n");
arg.val = ;
if (semctl(semId, , SETVAL, arg) < )
{
fprintf(stdout, "semctl error %s\n", strerror(errno));
return -;
}
if (semctl(semId, , SETVAL, arg) < )
{
fprintf(stdout, "semctl error %s\n", strerror(errno));
return -;
}
}
else
{
fprintf(stdout, "semget error %s\n", strerror(errno));
return -;
}
pthread_t tids[];
for(int i = ; i < ; ++i)
{ //参数依次是:创建的线程id,线程参数,调用的函数,传入的函数参数
if(i== || i== || i==)
{
fprintf(stdout,"turn NO.%d want to read.\n",i);
int ret = pthread_create(&tids[i], NULL, reader, NULL);
if (ret != )
{
fprintf(stdout, "reading error\n");
}
}
else{
fprintf(stdout,"turn NO.%d want to write.\n",i);
int ret = pthread_create(&tids[i], NULL, writer, NULL);
if (ret != )
{
fprintf(stdout, "writing error\n");
}
}
} pthread_exit(NULL);
return ;
}
结果如图(读者优先):

非常感谢 @神一城 老师的指点,之前自己没有学清楚 system V 中关于信号量的内容,使用了 semctl 这种直接赋值的操作,其实这样和直接使用 int 变量再加一些条件判断实现一样,而这样就等同于没有原子性,完全没有体现出信号量的作用,只是把信号量当作了一个普通变量。
这里向之前受到错误博客内容误导的朋友道歉。
使用system V实现读者写者问题的更多相关文章
- System V IPC(2)-信号量
一.概述 System V信号量与System V消息队列不同.它不是用来在进程间传递数据.它主要 ...
- system v和posix的共享内存对比 & 共享内存位置
参考 http://www.startos.com/linux/tips/2011012822078.html 1)Linux和所有的UNIX操作系统都允许通过共享内存在应用程序之间共享存储空间. 2 ...
- 读者写者问题继 读写锁SRWLock
在<秒杀多线程第十一篇读者写者问题>文章中我们使用事件和一个记录读者个数的变量来解决读者写者问题.问题虽然得到了解决,但代码有点复杂.本篇将介绍一种新方法--读写锁SRWLock来解决这一 ...
- 第3章 System V IPC
3.1 概述 System V IPC 包含:System V消息队列.System V信号量.System V共享内存. 3.2 key_t 键和 ftok函数 这三种类型的System V IPC ...
- glibc库详解及与POSIX,system V这些库之间关系的说明
自己想了解下关于system v,在网上看到一篇详细的说明,与大家分享一下,原文地址http://hi.baidu.com/tekuba/item/570887775696542e5c178918 以 ...
- Java实现生产者消费者问题与读者写者问题
摘要: Java实现生产者消费者问题与读者写者问题 1.生产者消费者问题 生产者消费者问题是研究多线程程序时绕不开的经典问题之一,它描述是有一块缓冲区作为仓库,生产者可以将产品放入仓库,消费者则可以从 ...
- 消息队列接口API(posix 接口和 system v接口)
消息队列 posix API 消息队列(也叫做报文队列)能够克服早期unix通信机制的一些缺点.信号这种通信方式更像\"即时\"的通信方式,它要求接受信号的进程在某个时间范围内对信 ...
- System V 机制(转)
引言 UNIX 内核管理的进程自主地操作,从而产生更稳定的系统.然而,每个开发人员最终都会遇到这样的情况,即其中一组进程需要与另一组进程通信,也许是为了交换数据或发送命令.这种通信称为进程间通信(In ...
- 从并发处理谈PHP进程间通信(二)System V IPC
.container { margin-right: auto; margin-left: auto; padding-left: 15px; padding-right: 15px } .conta ...
随机推荐
- CF1244C The Football Season
题目链接 problem 给定\(n,p,w,d\),求解任意一对\((x,y)\)满足\[xw+yd=p\\ x + y \le n\] \(1\le n\le 10^{12},0\le p\le ...
- Windows许可证 即将过期
最近打开电脑,系统总是自动弹出Windows许可证即将过期的弹窗,现在总结方法如下. 命令都是在运行窗口输入的打开方式:win+R组合键或者右键点击win10开始菜单,点击“运行”查看系统版本:win ...
- 【STM32H7教程】第31章 STM32H7的USART应用之RS485
完整教程下载地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980 第31章 STM32H7的USART应用之RS48 ...
- IT兄弟连 Java语法教程 流程控制语句 控制循环结构1
Java语言没有提供goto语句来控制程序的跳转,这种做法提高了程序流程控制的可读性,但降低了程序流程控制的灵活性.为了弥补这种不足,Java提供了continue和break来控制循环结构.除此之外 ...
- 五分钟搞定 HTTPS 配置,二哥手把手教
01.关于 FreeSSL.cn FreeSSL.cn 是一个免费提供 HTTPS 证书申请.HTTPS 证书管理和 HTTPS 证书到期提醒服务的网站,旨在推进 HTTPS 证书的普及与应用,简化证 ...
- 用go-module作为包管理器搭建go的web服务器
本篇博客主要介绍了如何从零开始,使用Go Module作为依赖管理,基于Gin来一步一步搭建Go的Web服务器.并使用Endless来使服务器平滑重启,使用Swagger来自动生成Api文档. 源码在 ...
- python基础(11):函数(一)
1. 什么是函数 1.我们到⽬前为⽌,已经可以完成⼀些软件的基础功能了.那么我们来完成这样⼀个功能: 约会: print("拿出⼿机") print("打开陌陌" ...
- Java生鲜电商平台-OMS订单系统中并发问题和锁机制的探讨与解决方案
Java生鲜电商平台-OMS订单系统中并发问题和锁机制的探讨与解决方案 说明:Java开源生鲜电商中OMS订单系统中并发问题和锁机制的探讨与解决方案: 问题由来 假设在一个订单系统中(以火车票 ...
- RPA之AA
RoboticProcessAutomation(即机器人流程自动化),RPA机器人能够模仿大多数人类用户的行为, 比如可以登录应用程序,移动文件和文件夹,复制和粘贴数据,填写表单,从文档中提取结构化 ...
- bower私服部署
目录 bower私服部署 简介 工具清单 安装 安装nodejs 安装git 安装private-bower 配置private-bower 启动private-bower 开放端口 开机启动/注册为 ...