读者写者

操作系统课程设计实验报告


设计题目四:读者写者


一、设计题目要求

(1)掌握信号量通信机制,实现进程之间通过信号进行通信;

(2)掌握匿名管道及有名管道通信机制,实现进程之间通过管道进行通信;

(3)理解System V IPC通信机制工作原理;

(4)掌握共享内存、消息、管道、信号量通信实现方法。

二、实验说明

   (1)利用共享主存解决读者-写者问题

(2)要求由写者创建一个共享主存,并向其中写入数据,读者进程随后从该共享区 中访问数据

三、程序设计思路及流程图

程序功能简介:

读者功能描述:有一个数据块被多个用户共享,读者部分对数据块是只读的,而且允许多个读者同时读;

写者功能描述: 写者部分对数据块是只写的,当一个写者正在向数据块写信息的时候,不允许其他用户使用,无论是读还是写。

程序设计思路:

(1)为基于共享主存解决读者写者问题,需要由写进程首先创建一个共享主存,并将该共享主存区分别映射到读者进程和写者进程的虚拟空间

(2)随后,写进程开始向共享主存写数据,读进程从共享主存区获取数据

程序流程图:

见附录A

 

四、涉及的背景知识及所用函数简介

1、shmat函数

函数原型 :void *shmat(int shmid, const void *shmaddr, int shmflg)

头文件 :sys/types.h  sys/shm.h

作用 :将参数shmmid所指的共享内存和目前进程连接(attach)

参数 :shmaddr不为0,参数shmflg也没有指定SHM_RND旗标,则参数 shmaddr为连接地址;

shmaddr不为0,参数shmflg设置了SHM_RND旗标,则参数shmaddr 会自动调整为SHMLAB的整数倍;

shmaddr为0,核心自动选择一个地址。

返回值 :成功,返回共享内存识别代码;出错,-1,错误原因存于error中

2、pthread_create函数

头文件 :pthread.h

函数原型 :int pthread_create(pthread_t *thread,const pthread_attr_t  *attr,void  *(*start_rtn)(void*),void *arg);

作用 :创建一个线程

参数 :thread           待创建线程的id指针

           pthread_attr_t      创建线程时的线程属性

           *start_rtn(void * )   返回值是void*类型的指针函数

           arg              函数start_rtn的参数

返回值 :成功返回0;失败返回错误编号

3、pthread_join函数

函数原型 :int pthread_join( pthread_t thread, void ** rval_ptr)

头文件 :pthread.h

作用 :1)调用者将挂起并等待指定线程终止

                2)当新线程调用pthread_exit()退出或者return时,进程中的其 他线可通过pthread_join()获得进程的退出状态

参数 :thread 线程的ID号

            rval_ptr 线程的返回状态

返回值 :成功返回0;失败返回错误编码

4、shmctl 函数

函数原型 :int shmctl(int shmid, int cmd, struct shmid_ds *buf)

头文件 :sys/types.h  sys/shm.h

作用 :完成对共享内存的控制

参数 :shmid 共享内存标识符;

IPC_STAT:得到共享内存的状态,把共享内存的shmid_ds结构 复制到buf中;

IPC_SET:改变共享内存的状态,把buf所指的shmid_ds结构中的 uid、gid、mode复制到共享内存的shmid_ds结构内;

IPC_RMID:删除这片共享内存;

buf 共享内存管理结构体,具体说明参见共享内存内核结构定义部 分。

返回值 :成功返回0,失败返回-1,错误原因存于error中。

5、pthread_mutex_init 函数

函数原型 :pthread_mutex_init(pthread_mutex_t *restrict mutex,const  pthread_mutexattr_t *restrict attr);

头文件 :pthread.h  

作用 :该函数用于C函数的多线程编程中,互斥锁的初始化

返回值 :函数成功完成之后会返回零,其他任何返回值都表示出现了错误。函数成功执行后,互斥锁被初始化为未锁住态。

    6、pthread_mutex_lock函数

函数原型 :int pthread_mutex_lock(pthread_mutex_t *mutex);        

头文件 :pthread.h 

作用 :当pthread_mutex_lock()返回时,该互斥锁已被锁定。线程调用 该函数让互斥锁上锁,如果该互斥锁已被另一个线程锁定和拥有,则 调用该线程将阻塞,直到该互斥锁变为可用为止。

返回值 :在成功完成之后会返回零。其他任何返回值都表示出现了错误。如 果出现以下任一情况,该函数将失败并返回对应的值。

    7、pthread_mutex_unlock函数

函数原型 :int pthread_mutex_unlock(pthread_mutex_t *mutex);

头文件 :pthread.h  

作用 :释放互斥锁,与pthread_mutex_lock成对存在。

参数 :需要解锁的锁变量对象

8、pthread_mutex_destroy函数

函数原型 :int pthread_mutex_destroy(pthread_mutex_t *mutex);

头文件 :pthread.h  

作用 :销毁互斥锁

参数 :mutex 指向要销毁的互斥锁的指针

返回值 :互斥锁销毁函数在执行成功后返回 0,否则返回错误码。

五、程序所用数据结构简介

pthread_mutex_t mutex, Rmutex;

互斥信号量,对缓冲区的互斥使用,读者和写者之间互斥。int counter;

记录读者的数量来与写者互斥。int num_reader, num_writer;

分别记录读者写者的数量。pthread_t threads_r[100], threads_w[100];

读者写者线程数组线程。

int shmid;

共享内存块号。

char *shmaddr;

共享内存块地址。char *shmaddread;

读者共享内存块地址。struct shmid_ds buf;

共享内存的数据结构定义。void Read_operation();

读者读数据。void Writer_the_data();

写者写数。void *reader_thread(void *arg);

读者线程执行函数。void *writer_thread(void *arg);

写者线程执行函数void Quit();

删除共享内存和数据结构,退出程序。

 

 

六、程序源代码

见附录B

七、调试方案及调试过程记录与分析

测试结果、调试过程:

 

第一次测试结果:使用一块缓冲区,用while(1)循环来创建线程,只能执行一次写 操作,读操作可以多次执行,读操作不符合预期结果,还要注意对信号量的初始化操作。

第一次调试:向老师请教后,得知原因应该是系统已经自己定义好了共享内存的读写规则,循环时,只能写入一次,之后写者被阻塞。所以改为由用户选择输入创建读者线程还是写着线程。

第二次测试结果:修改之后可以正常执行,结果正确。

八、程序运行结果分析

一块缓冲区可以被多个读者同时读,读到的是相同的内容;一块缓冲区只能被一个写者写。程序刚开始时,没有内容,必须要写者先写入内容,读者才可以读。通过编程实现,对于读者写者之间的互斥关系理解更深刻。


程序源代码:
/*
**************************************************************************************
*Project/File	:main.c
*By				
*Mail			:
*Status			:finished
*version		:1.0
*Created Time	:2014年10月14日星期二20时24分30秒
**************************************************************************************
*Note:
*有一个数据块被多个用户共享,其中一部分用户是读者,另一部分是写者。
**************************************************************************************
*/

#include"reader_writer.h"

int main(void)
{
    int choose;
    int i;
    counter = 0;
    num_reader = 1;
  	num_writer = 1;
    while((shmid = shmget(KEY, SIZE, IPC_CREAT | 0600))== -1);//创建共享内存;
	printf("Welcome to the ******  Reader And Writer  ******\n");
    while(1) 
    {        
        printf("\n**********1.Create a reader, and read the memory;\n");
        printf("**********2.Create a writer, and write to the memory;\n");
        printf("**********3.Exit the Reader And Writer!\n");
        printf("Please input your choose:\n");
        scanf("%d", &choose);

        pthread_mutex_init(&mutex, NULL); 
        pthread_mutex_init(&Rmutex, NULL); 			//初始化信号量;

        switch(choose)
        {
            case 1:
            pthread_create(&threads_r[num_reader++],NULL,reader_thread, NULL); 
            break;
            case 2:
            pthread_create(&threads_w[num_writer++],NULL,writer_thread,NULL); 
            break;
            case 3:
            Quit();
            break;
            default:
            printf("Not find your choose, please input again!\n");
        }       
    }
	return 0; 	

}
/*
**************************************************************************************
*Project/File	:reader.c
*By				:
*Mail			:
*Status			:finished
*version		:1.0
*Created Time	:2014年10月14日星期二20时24分30秒
**************************************************************************************
*Note:
*读者对数据块是只读的,而且允许多个读者同时读;
*当读者使用数据块时,不允许任何一个写者使用。
**************************************************************************************
*/
#include"reader_writer.h"

void *reader_thread(void *arg)
{
    pthread_mutex_lock(&Rmutex);//P(Rmutex);

	if(counter == 0)		//If counter = 0 then P(mutex);
		pthread_mutex_lock(&mutex);
	counter = counter + 1;

	pthread_mutex_unlock(&Rmutex);		//V(Rmutex);

	Read_operation();

	pthread_mutex_lock(&Rmutex);		//P(Rmutex);

	if(counter == 1)		//If counter = 1 then V(mutex);
		pthread_mutex_unlock(&mutex);
	counter = counter + 1;

	pthread_mutex_unlock(&Rmutex);		//V(Rmutex);
}
/*
**************************************************************************************
*Project/File	:writer.c
*By				:
*Mail			:
*Status			:finished
*version		:1.0
*Created Time	:2014年10月14日星期二20时24分30秒
**************************************************************************************
*Note:
*写者对数据块是只写的,当一个写者正在向数据块写信息的时候,不允许其他用户使用,无论读者写者。
**************************************************************************************
*/

#include"reader_writer.h"

void *writer_thread(void *arg)
{
	pthread_mutex_lock(&mutex);		//P(mutex);

	Writer_the_data();

	pthread_mutex_unlock(&mutex);			//V(mutex);
}
/*
**************************************************************************************
*Project/File	:reader_writer.c
*By				:
*Mail			:
*Status			:finished
*version		:1.0
*Created Time	:2014年10月14日星期二20时24分30秒
**************************************************************************************
*Note:
*这里实现了所有.c文件所用到的函数;
**************************************************************************************
*/
#include"reader_writer.h"
void Read_operation()
{
    shmaddread = shmat(shmid, NULL, 0);		
	printf("This is Reader %d, reading the share memory:%s\n", num_reader - 1, shmaddread);
	shmdt(shmaddread);
}
void Writer_the_data()
{
    char string[100];
    shmaddr = (char*)shmat(shmid, NULL, 0);
	strcpy(string, "Message was writing by Writer");
    string[strlen(string) + 1] = '\0';
    string[strlen(string)] = num_writer - 1 + '0';
    strcpy(shmaddr, string);
    printf("Writer %d has writen to the memory!\n", num_writer - 1);
	shmdt(shmaddr);
}
void Quit()
{
    int i;
    shmctl(shmid, IPC_RMID, NULL);;//销毁共享内存;
	pthread_mutex_destroy(&mutex);						//销毁互斥信号量;
    pthread_mutex_destroy(&Rmutex);
    for(i=0;i<num_reader;i++) 				//销毁线程;
        pthread_join(threads_r[i],NULL); 
    for(i=0;i<num_writer;i++) 
        pthread_join(threads_w[i],NULL);
    exit(0);
}
/*
**************************************************************************************
*Project/File	:reader_writer.h
*By				:
*Mail			:
*Status			:finished
*version		:1.0
*Created Time	:2014年10月14日星期二20时24分30秒
**************************************************************************************
*Note:
*将所有.c文件所用到的头文件包含进去;
*包含所有的宏定义;
*全局变量的定义;
*函数的声明;
**************************************************************************************
*/
#ifndef reader_writer_h
#define reader_writer_h

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pthread.h"
#include "signal.h"
#include "unistd.h"
#include "sys/shm.h"
#include "sys/ipc.h"
#include "sys/types.h"
#define SIZE 1024
#define KEY 1234

pthread_mutex_t mutex, Rmutex;
int counter;
int num_reader, num_writer;
pthread_t threads_r[100], threads_w[100];

int pid;
int shmid;
char *shmaddr;
char *shmaddread;
struct shmid_ds buf;

void Read_operation();
void Writer_the_data();

void *reader_thread(void *arg);
void *writer_thread(void *arg);
void Quit();

#endif

Makefile
vpath %.h ./
main:main.o reader.o writer.o reader_writer.o reader_writer.h
	gcc -o main -pthread main.o reader.o writer.o reader_writer.o
main.o:main.c reader.c writer.c reader_writer.c reader_writer.h
	gcc -c main.c reader.c writer.c reader_writer.c 
reader.o:reader.c reader_writer.c reader_writer.h
	gcc -c reader.c writer.c reader_writer.c 
writer.o:writer.c reader_writer.c reader_writer.h
	gcc -c writer.c reader_writer.c 
reader_writer.o:reader_writer.c reader_writer.h
	gcc -c reader_writer.c 


 

你可能感兴趣的:(读者写者)