#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实现读者写者问题的更多相关文章

  1. System V IPC(2)-信号量

    一.概述                                                    System V信号量与System V消息队列不同.它不是用来在进程间传递数据.它主要 ...

  2. system v和posix的共享内存对比 & 共享内存位置

    参考 http://www.startos.com/linux/tips/2011012822078.html 1)Linux和所有的UNIX操作系统都允许通过共享内存在应用程序之间共享存储空间. 2 ...

  3. 读者写者问题继 读写锁SRWLock

    在<秒杀多线程第十一篇读者写者问题>文章中我们使用事件和一个记录读者个数的变量来解决读者写者问题.问题虽然得到了解决,但代码有点复杂.本篇将介绍一种新方法--读写锁SRWLock来解决这一 ...

  4. 第3章 System V IPC

    3.1 概述 System V IPC 包含:System V消息队列.System V信号量.System V共享内存. 3.2 key_t 键和 ftok函数 这三种类型的System V IPC ...

  5. glibc库详解及与POSIX,system V这些库之间关系的说明

    自己想了解下关于system v,在网上看到一篇详细的说明,与大家分享一下,原文地址http://hi.baidu.com/tekuba/item/570887775696542e5c178918 以 ...

  6. Java实现生产者消费者问题与读者写者问题

    摘要: Java实现生产者消费者问题与读者写者问题 1.生产者消费者问题 生产者消费者问题是研究多线程程序时绕不开的经典问题之一,它描述是有一块缓冲区作为仓库,生产者可以将产品放入仓库,消费者则可以从 ...

  7. 消息队列接口API(posix 接口和 system v接口)

    消息队列 posix API 消息队列(也叫做报文队列)能够克服早期unix通信机制的一些缺点.信号这种通信方式更像\"即时\"的通信方式,它要求接受信号的进程在某个时间范围内对信 ...

  8. System V 机制(转)

    引言 UNIX 内核管理的进程自主地操作,从而产生更稳定的系统.然而,每个开发人员最终都会遇到这样的情况,即其中一组进程需要与另一组进程通信,也许是为了交换数据或发送命令.这种通信称为进程间通信(In ...

  9. 从并发处理谈PHP进程间通信(二)System V IPC

    .container { margin-right: auto; margin-left: auto; padding-left: 15px; padding-right: 15px } .conta ...

随机推荐

  1. Make Them Odd

    time limit per test3 secondsmemory limit per test256 megabytesinput: standard inputoutput: standard ...

  2. python 各层级目录下的import方法

    ---恢复内容开始--- 以前经常使用python2.现在很多东西都切换到了python3,发现很多东西还是存在一些差异化的.跨目录import是常用的一种方法,并且有不同的表现形式,新手很容易搞混. ...

  3. C语言程序设计100例之(7):级数求和

    例7    级数求和 题目描述 已知: Sn =1+1/2+1/3+…+1/n.显然对于任意一个整数 k,当 n 足够大的时候,Sn>k. 现给出一个整数 k,要求计算出一个最小的 n,使得 S ...

  4. dell服务器已有阵列新增的磁盘无法识别显示外来

    问题描述: 今天遇到个插入新硬盘显示外来盘,然后不可用,然后电话问了一下戴尔的工程师 说需要清除一下原来磁盘的阵列信息之类的,才能识别到,这里就做一个笔记记录一下,顺便分享给有需要的朋友! 解决方法: ...

  5. Xml之Schema XSD约束{详细}

    问题: 学习Schema其他标签的定义 约束 引入的方式: 基本格式: 1构建schema: 1.1 最基本的单位元素 1.2 元素属性 1.3 simpleType 定义类型 1.4 复合结构类型 ...

  6. Java Tomcat 使用(IDEA)

    Tomcat 服务器软件的使用 (配置文件,  部署项目 ); 基本的 web 知识回顾: 1. web 服务器 软件:  Tomcat  (常见的, 主流的, 开源的, 免费的,软件)   1. 软 ...

  7. hive引擎的选择:tez和spark

    背景 mr引擎在hive 2中将被弃用.官方推荐使用tez或spark等引擎. 选择 tez 使用有向无环图.内存式计算. spark 可以同时作为批式和流式的处理引擎,减少学习成本. 问题& ...

  8. 记一次收集APP native崩溃信息

    最近在学习 极客时间Android开发高手课 老师推荐了Breakpad开源库来采集native 的crash1.为什么要使用Google Breakpad? 我们在开发过程中,Android JNI ...

  9. MySQL for OPS 12:锁处理

    写在前面的话 在前面的内容中提到过,在以前的 MyISAM 中锁是表级锁,InnoDB 是行级锁.这个锁到底是啥样,怎么找出来,这一节就主要做这个. 定位锁的问题 上一节我们创建了一个 1000万数据 ...

  10. GO Slice

    一.切片(Slice) 1.1 什么是切片 Go 语言切片是对数组的抽象. Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go中提供了一种灵活,功能强悍的内置类型切片("动态数 ...