使用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 ...
随机推荐
- Linux下修改Mysql密码的三种方式
前言 有时我们会忘记Mysql的密码,或者想改一个密码,以下将对这两种情况修改密码的三种解决方法做个总结 本文都以用户为 root 为例 一.拥有原来的myql的root的密码 方法一: 在mysql ...
- 程序员,你还不会合理选择Filter、Interceptor、Aspect?
小伙伴们应该听说过过滤器.拦截器.切面,印象上都能够起到截断拦截的作用,在做一些业务需求时,不知道如何选择,今天老顾就来介绍一下他们之间的区别. 过滤器可以拦截到方法的请求和响应 (ServletRe ...
- mysql数据库的十种查询方式及多表查询
--mysql数据库的十种查询方式 -- (1)查询时起别名 SELECT id AS '编号',NAME AS '姓名',age AS '年龄' FROM student; -- (2)查询时添加常 ...
- Java Tomcat 使用(IDEA)
Tomcat 服务器软件的使用 (配置文件, 部署项目 ); 基本的 web 知识回顾: 1. web 服务器 软件: Tomcat (常见的, 主流的, 开源的, 免费的,软件) 1. 软 ...
- RPA 可以给医疗行业带来哪些好处
如今,医疗保健行业通过利用颠覆性科学技术,使护理服务更加高效.医疗保健行业已经转向数字化,很多大型医疗机构开始采用 RPA(机器人流程自动化),使医疗服务的竞争力不断攀升.使用 RPA 可以完美自动化 ...
- linux学习之Ubuntu
查看自己的ubuntu版本,输入以下命令(我的都是在root用户下的,在普通用户要使用sudo)第一行的lsb是因为没有安装LSB,安装之后就不会出现这个东西.LSB(Linux Standards ...
- MySQL for OPS 10:MyCAT 分布式架构
写在前面的话 在学习的索引的时候,有提到,当数据表数据达到 800W 的时候,索引的性能就开始逐步下降.对于一个公司而言,主要业务数据表达到 1000W 都很容易.同时这张表一般都是业务常用的表,操作 ...
- 2018-12-25-win10-uwp-通知列表
原文:2018-12-25-win10-uwp-通知列表 title author date CreateTime categories win10 uwp 通知列表 lindexi 2018-12- ...
- java基础(29):JDBC、DBUtils
1. JDBC 1.1 JDBC概述 JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问 ...
- Python笔记:设计模式之模板方法模式
此模式通过一个模板方法来定义程序的框架或算法,通常模板方法定义在基类中,即原始的模板,然后子类就可以根据不同的需要实现或重写模板方法中的某些算法步骤或者框架的某部分,最后达到使用相同模板实现不同功能的 ...