【Linux学习笔记】39:Linux下C模拟读者写者问题
来源:互联网 发布:杭州腾亿网络 编辑:程序博客网 时间:2024/05/21 09:22
只开了一块缓冲区,所以不需要用mutex互斥信号量对其保护,直接交替PV操作就行了。应当找时间系统学习一下Linux下的C/C++编程,有很多有意思的功能。下面两个程序可以开两个terminal,编译好后,先执行生产者,再在另一个terminal里执行消费者的程序,然后在生产者的程序里输入(生产的)字符串就行了。因为用的是scanf的%s读入字符串,所以中间有空格时会陆续读入,这种时候观察两个进程的状态挺有意思。
生产者程序
#include<stdio.h>#include<sys/ipc.h>#include<sys/shm.h>#include<stdlib.h>#include<sys/stat.h>#include<sys/sem.h>#define SEM_KEY 6666#define true 1#define false 0//共用体union semun { int setval; struct semid_ds *buf; unsigned short *array;};int main(int argc ,char *argv[]){ int shmid;//信号量的标识码ID,创建失败时为-1 char *addr;//公用缓冲区(共享内存)首地址 //shmget()创建一个共享内存,权限为0666 shmid=shmget(ftok(".",1000),getpagesize(),IPC_CREAT | 0666); //创建失败时为-1 if(shmid==-1) { perror("shmget error:"); exit(EXIT_FAILURE); } //输出共享内存的标识码ID printf("共享内存的标识码ID:=%d\n",shmid); //获取共享内存的起始地址,且为可读可写 addr=shmat(shmid,0,0); //获取失败时为-1 if(-1==*addr) { perror("shmat error:"); exit(EXIT_FAILURE); } /* int semget(key_t _key,int _nsems,int _semflg); 功能:创建一个新的信号量或获取一个已经存在的信号量的键值。 */ //创建2个信号量的信号集 int semid=semget(SEM_KEY, 2, IPC_CREAT | 0600); //创建失败时为-1 if (-1 == semid) { perror("semget"); exit(EXIT_FAILURE); } printf("信号集的标识码ID:=%d\n", semid); //初始化信号集 union semun sem_args; unsigned short array[2]={0,1}; sem_args.array = array;//赋值给共用体 //SETALL代表设置信号集中所有的信号量的值。1,代表2个,sem_args是具体初始化的值放在共用体中 int ret=semctl(semid, 1, SETALL, sem_args); //设置失败时为-1 if (-1 == ret) { perror("semctl"); exit(EXIT_FAILURE); } //对资源的使用处理操作 /* struct sembuf{ unsigned short sem_num;//第几个信号量,第一个信号量为0 short sem_op;//对该信号量的操作(+/-) short sem_flg;//常被设置为SEM_UNDO,使得如果一个进程在没有释放信号量的情况下结束了执行,该进程掌握的信号量由系统自己释放 }; */ struct sembuf P_full={0, -1, SEM_UNDO}; struct sembuf V_full={0, +1, SEM_UNDO}; struct sembuf P_empty={1, -1, SEM_UNDO}; struct sembuf V_empty={1, +1, SEM_UNDO}; printf("<这里是生产者进程,在这里输入生产出的字符串>\n"); //不断生产 while(true) { /* int semop(int semid ,struct sembuf *_sops ,size_t _nsops); 功能:用户改变信号量的值。也就是使用资源还是释放资源使用权 */ semop(semid, &P_empty, 1);//P(empty)等待至空缓冲区数量不为0 scanf("%s",addr); printf(">%s被读入了缓冲区\n",addr); semop(semid, &V_full, 1);//V(full)满缓冲区数量+1 if(addr[0]=='@') break;//跳出循环,准备结束程序 }return 0;}
消费者程序
#include<stdio.h>#include<sys/ipc.h>#include<sys/shm.h>#include<stdlib.h>#include<sys/sem.h>#include<string.h>#include<sys/stat.h>#define SEM_KEY 6666#define true 1#define false 0//共用体union semun { int setval; struct semid_ds *buf; unsigned short *array;};int main(int argc ,char *argv[]){ int shmid;//信号量的标识码ID,创建失败时为-1 char *addr;//公用缓冲区首地址 //打开刚才原程序1创建的共享内存,权限为0666 shmid= shmget(ftok(".",1000),getpagesize(), IPC_CREAT | 0666); printf("共享内存的标识码ID:=%d\n",shmid); //创建失败时为-1 if(shmid==-1) { perror("shmget error:"); exit(EXIT_FAILURE); } addr=shmat(shmid,0,0);//获取共享内存的起始地址,且为可读可写 if(-1==*addr) { perror("shmat error:"); exit(EXIT_FAILURE); } int semid=semget(SEM_KEY, 0, IPC_CREAT | 0600);//取得信号量 if(-1==semid) { perror("semget"); exit(EXIT_FAILURE); } printf("信号集的标识码ID:=%d\n", semid); //对资源的使用处理操作 struct sembuf P_full={0, -1, SEM_UNDO}; struct sembuf V_full={0, +1, SEM_UNDO}; struct sembuf P_empty={1, -1, SEM_UNDO}; struct sembuf V_empty={1, +1, SEM_UNDO}; printf("<这里是消费者进程,不要在这里输入任何东西>\n"); //不断消费 while(true) { semop(semid, &P_full, 1);//P(full)等待至满缓冲区数量不为0 //如果检测到生产者输入的第一个字符是@ if(addr[0]=='@') break;//跳出循环,准备结束程序 printf("消费ing...\n"); sleep(3);//消费需要时间 printf(">消费了"); puts(addr);//输出这次消费的东西 semop(semid, &V_empty, 1);//V(empty)空缓冲区数量+1 } if(-1==semctl(semid,1,IPC_RMID,0))//删除信号量 { perror("semctl error:"); exit(EXIT_FAILURE); } if(-1==shmdt(addr))//释放共享内存,使其不再有任何指向它的指针 { perror("shmdt error:"); exit(EXIT_FAILURE); } if (shmctl(shmid,IPC_RMID,0)==-1)//删除共享内存 { perror("shctl error:"); exit(EXIT_FAILURE); }return 0;}
输入@符号就可以结束两个进程了,下面是运行的结果。
在做和进程有关的编程学习时,sleep()函数真的是一个非常好用的便于观察和思考的方法。
阅读全文
0 0
- 【Linux学习笔记】39:Linux下C模拟读者写者问题
- linux读者写者问题
- 读者写者 问题C线程实现 linux平台
- 经典同步问题linux下的C实现:生产者-消费者问题,读者-写者问题,哲学家问题
- 经典同步问题linux下的C实现:生产者-消费者问题,读者-写者问题,哲学家问题
- linux 读者写者问题 读者优先c++
- linux 读者写着问题
- C 优先读者 读者/写者问题
- Unix下读者写者同步问题的模拟程序
- Linux---读者写者模型
- linux:读者写者模型
- William Stallings 《操作系统内核和设计原理》书中Linux下C语言实现读者写者问题(写者优先)代码
- C#模拟读者写者问题
- c# 多线程学习笔记(五)读者写者问题
- Linux多线程──读者写者问题
- Linux多线程──读者写者问题
- linux 读者写着问题 c++
- linux C++ 多线程 读者写者实现
- Git三大特色之Stage(暂存区)
- printf的返回值
- 【队内胡策 11.1】 T1 T2
- 基础扫盲帖:比特率和波特率有什么不同?
- Google 开源项目 word2vec 的分析
- 【Linux学习笔记】39:Linux下C模拟读者写者问题
- java面试题
- Android MVP模式 简单易懂的介绍方式
- AsyncTask的基础使用
- ubuntu16.04搜狗输入法不能打出汉字的问题
- Linux常用基本命令
- 什么是网关,网关的作用
- spring各jar包作用于spring常用注解
- Cg Programming/Unity/Lighting Textured Surfaces光照纹理表面