⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 article_3327.txt

📁 操作系统原理模拟 操作系统实验及课程设计,如果你正在做操作系统实验或课程设计,我保证肯定有用的.
💻 TXT
字号:
  2读者2写者问题编程实现

一、 设计思路

主程序使用shmget()函数来获得一个共享内存区的IPC标识符,shmat()函数将获得
的共享内存区附加到主程序上。共享内存区存放一个share的数据结构如下:


typedef struct
{
  int buff[512];            /*buffer for writer and reader*/
  int in;                   /*indicate the writers where to put num in
the buffer*/
  int out;                  /*indicate the readers where to get num from
the buffer*/
  int val;                  /*the current value of num which need to be
put into the buffer*/
  long long sum;            /*the final sum*/
}share;

 接下来使用fork()创建4个子进程,分别为2个写者和2个读者。读写者需要同步互
斥。因此使用semget()函数来获取信号量,并需要定义P、V操作。由于子进程可继
承父进程所附加的共享内存区,因此不需要再在各个子进程中附加共享内存,只需
在传递参数时将共享内存地址传给子进程即可。最后需要记得回收资源。

二、 具体实现

这次我实现了2个程序,一个为in_turn.c,实现了2写者轮流写,2读者轮流读;另
一个为not_in_turn.c,是以类似锁的方式实现的,即只保证一个时刻只有一个读
者和一个写者,不保证轮流性。2种方法一个比较大的区别是前者是6个信号量,而
后者是4个信号量。这里主要说下in_turn.c,即轮流的实现。

一开始需要在主程序中获取和附加共享内存,并对共享内存中的数值进行初始化。
接下来获取信号量:

int in1_id,in2_id,out1_id,out2_id,empty_id,full_id; 

定义P、V操作(初始化sembuf结构):

struct sembuf P,V;

P.sem_num=0;

P.sem_op=-1;

P.sem_flg=0;

V.sem_num=0;

V.sem_op=1;

V.sem_flg=0;

然后需要对信号量赋初值(调用semctl( )函数):

初值赋1的信号量:in1_id,out1_id

初值赋0的信号量:in2_id,out2_id,full_id

初值赋512(共享内存中数组大小)的信号量:empty_id

这样赋值的原因是要给writer1一开始就运行的机会,当它执行一次write操作流程
如下:

1.       P(empty_id)

2.       P(in1_id)

3.       Write num to buff

4.       V(in2_id)

5.       V(full_id)

其他writer2、reader1、reader2流程可类推。这里写的数值使用共享内存

中的share结构中的val。Val从1开始,每个写进程将它写到buff[in]后将它

递增1,读进程每次将buff[out]中的值读出,加入自己的一个sum中,无论

是读还是写进程都循环50000次,读进程在循环结束后将自己计算的sum

加入共享内存的sum中,这样就能保证从1加到100000了。

    由于需要写到100000,而只有512的缓存,所以需要循环利用,使用了对512进
行取模运算,这样就能实现了。

主进程在获取完共享内存和信号量之后就是调用fork()函数了,主程序需要调用4
次fork( ),然后调用waitpid等待他们运行结束,以免产生僵死进程。子进程在结
束前应该调用shmdt( )将共享内存区解除。父进程在等待所有的子进程返回后也需
要调用shmdt(),还要释放所有的信号量(调用semctl)。

三、 心得与体会

       这次作业耗费的时间还是蛮多的,主要不是设计方案问题,而是一些细节
上问题很多,比如一开始的时候对共享内存的使用不是很了解,进行了多次实验,
然后是信号量上的一个问题困扰了我很久,就是PV操作的sem_flag的置位问题。一
开始参考其他资料将其置位SEM_UNDO,孰不知此置位方式在某个子进程结束时,相
应的操作将被取消。这样会导致其他子进程被阻塞。设置此标志位是为了防止进程
在没有释放共享资源就退出时,内核将代为释放。后来将它改为0,程序就正确了。

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -