Linux实验报告

实验一:
实验题目:
读者-写者问题为数据库访问建立了一个模型。例如,一个系统,其中有许多竞争的进程试图读写其中的数据,多个进程同时读是可以接受的,但如果一个进程正在更新数据库,则所有的其他进程都不能访问数据库,即使读操作也不行。问题是:如何对读者和写者进行编程。
实验目的:
练习进程间通信编程
加深对ipc问题的理解
提高在Linux环境下的编程能力
实验原理:
在该解法中,第一个读者对信号量db 执行down操作,随后的读者只是递增一个计数器rc。当读者离开时,它们递减这个计数器,而最后一个读者则对信号量执行up,这样就允许一个被阻塞的写者(如果存在的话)可以访问该数据库。
在该解法中,隐含着一个需要说明的条件。假设一个读者正使用数据库,另一个读者来了。同时有两个读者并不存在问题,第二个读者被允许进入。如果第三个和更多的读者来了也同样被允许。
现在假设一个写者到来。由于写者的访问是排他的,不能允许写者进入数据库,只能被挂起。只要还有一个读者在活动,就允许后续的读者进来。这种策略的结果是,如果有一个稳定的读者流存在,那么这些读者将在到达后被允许进入,而写者就始终被挂起,直到没有读者为止。如果来了新的读者,比如每2妙钟一个,而每一个读者花5妙钟完成其工作,那么,写者将永远不能被执行。
为了避免这种情况的发生,在一个写者到达且已经有一个写者等待时,读者在写者之后被挂起,而不是立即允许进入。用这种方式,在一个写者到达时如果有正在工作的读者,
那么该写者只要等待这个读者完成,而不必等候其后来到的读者。
为代码:
typedef int semaphore;
semaphore mutex=1; /*控制rc的访问*/
semaphore db=1; /*控制对数据库的访问*/
int rc=0; /*正在读或者即将读的进程数目*/
void reader(void)
{
while(TRUE){
down(&mutex); /*获得对rc的互斥访问权*/
rc=rc+1; /*增加一个读者*/
if(rc==1)down(&db); /*如果这是第一个读者.....*/
up(&mutex); /*释放对rc的互斥访问权*/
read_data_base(); /*访问数据库*/
down(&mutex); /*获取rc的互斥访问权*/
rc=rc-1; /*减少一个读者*/
if(rc==0)up(&db); /*如果这是最后一个读者*/
up(&mutex); /*释放对rc的互斥访问权*/
use_data_read(); /*非临界区*/
}
}
void writer(void)
{
while(TRUE){
think_up_data(); /*非临界区*/
down(&db); /*获取互斥访问权*/
write_data_base(); /*更新数据*/
up(&db); /*释放互斥访问*/
}
}
程序代码:
wjy.h:
#include
#include
#include
#include
#include
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
}

;
int cr_sem(int key, int semnu)//create semaphores
{
union semun sem;
int semid;
int i;
semid = semget(key, semnu, IPC_CREAT | 0666);
if (-1 == semid)
return -1;
sem.val = 1;//initialize the semaphore
for (i = 0; i < semnu; i++)
semctl(semid, i, SETVAL, sem);
return semid;
}
int cr_shm(int key, int size)//create shared memory segment
{
int shmid = shmget(key, size, IPC_CREAT | 0666);
return shmid;
}
void * at_shm(int shmid)//enable access to the shared memory
{
return shmat(shmid, 0, 0);
}
int del_shm(int shmid)//delete the shared memory segment
{
return shmctl(shmid, IPC_RMID, 0);
}
int del_sem(int shmid, int num)//delete a semaphore identifier
{
return semctl(shmid, num, IPC_RMID, 0);
}
int P(int semid, int no)//P operation
{
struct sembuf sops = {no, -1, 0};//-1 for P operation
return semop(semid, &sops, 1);
}
int V(int semid, int no) //V operation
{
struct sembuf sops ={no, +1, 0};//+1 for P operation
return semop(semid, &sops, 1);
}
wjy.c:
#include "ps.h"
#include
#include
#define KEY 4321
#define SIZE 4 //specifies the amount of memory required in bytes
#define RMUTEX 0 //读操作互斥量
#define WMUTEX 1 //对数据库访问互斥量
struct readwrite
{
int n; //编号
char role; //w 代表writer,r 代表reader
int delay; //sleep的时间
int extime; //表示read或write的时间
};
int reading(int semid, int wmutex, int rmutex, int *readcount, struct readwrite member)
{
P(semid, RMUTEX); //读者进入数据库,获得对读的互斥访问权
*readcount=*readcount+1; //读者计数器加1
if (*readcount == 1) //对第一个读者,判断有写者进入,若有挂起等待
P(semid, WMUTEX); //没有写者进入,读者阻塞后来的写者
V(semid, RMUTEX); //释放对读的互斥访问权,后来的读者可以共同访问
printf("R%d begins reading...\n", member.n); //到达的读者同时进行读操作
sleep(member.extime); //执行读操作的时间,各读操作时间不同
printf("R%d finishes reading!\n", member.n);
P(semid, RMUTEX); //获得对读的互斥访问权
*readcount=*readcount-1; //读者读完数据计数器减1
if (*readcount == 0) //对最后一个读者
V(semid, WMUTEX); //释放写者,使之有机会访问数据库
V(semid, RMUTEX); //释放对读的互斥访问权
return 0;
}
int writing(int semid, int r_w, int wrtime, struct readwrite member)
{
P(semid, WMUTEX); //获得对数据库的互斥访问权
printf("W%d begins writing...\n", member.n);
sleep(wrtime); //执行write操作的时间
printf("W%d finishes writing!\n", member.n);
V(semid, WMUTEX); //释放对数据库的互斥访问权
return 0;
}
main()
{
int semid; //semaphore identifier
int shmid; //shared memory identifier
int *readcount; //正在读或者即将读的进程数目
int i, pid;
//初始化readwrite数组,一共有8个
struct readwrite member[8]={

{1, 'W', 1, 10}, {2, 'R', 3, 4},
{3, 'W', 3, 2}, {4, 'W', 3, 5}, {5, 'R', 7, 3} ,
{6, 'R', 9, 4}, {7, 'R', 11, 4}, {8, 'W', 12, 4}};//W表示writer,R代表reader

semid = cr_sem(KEY, 2); //创建两个互斥量 RMUTEX和WMUTEX
if (semid == -1) //创建失败
{
printf("Fail to creat semaphore\n"); //报错
exit(0);
}

shmid = cr_shm(KEY, SIZE); //创建shared memory segment
if (shmid == -1) //创建失败
{
printf("Fail to creat share memory\n");
del_sem(semid, 2);
exit(0);
}

readcount = (int *)at_shm(shmid); //连接到共享内存
if((int)readcount == -1) //连接失败
{
printf("Cann't attach share momery error\n");
del_shm(shmid);
del_sem(semid, 2);
exit(0);
}
*readcount = 0;
printf("Eight readers and writers in the datebase...\n" );
for (i = 0; i < 8; i++)
{
while (-1 == (pid = fork()) );//循环创建8个进程
if (!pid) //子进程
{
sleep(member[i].delay); //读写进程按不同时间到达
printf("%c%d arrives.\n", member[i].role, member[i].n);
if('R' == member[i].role)//如果是reader则调用reading操作
{
reading(semid, WMUTEX, RMUTEX, readcount, member[i]);
}
else//是writer则执行writing操作
{
writing(semid, WMUTEX, member[i].extime, member[i]);
}
exit(0);
}
}
for (i = 0; i < 8; i++)
wait(0);
//must wait or while child processes using semophore or sharing memory, parent process delete them
shmdt(readcount); //detach shared memory
del_sem(semid, 2); //删除信号量
del_shm(shmid); //删除共享内存
exit(1);
}
运行结果:
实验二
实验题目:
实现一个多线程的程序,其中一个线程负责从键盘接受输入,另一个线程负责将输入保存在文件中。
实验目的:
练习线程间通信编程
加深对posix的理解
提高在Linux环境下的编程能力
实验原理:
利用多线程的方法,创造两个线程(a_thread和main),在main中读入输入的字符串并存入work_area中。另一个线程a_thread读work_area中的数据,并写入文件。
伪代码:
void *thread_function(void *arg);
pthread_mutex_t work_mutex; /* protects both work_area and time_to_exit */
#define WORK_SIZE 1024
char work_area[WORK_SIZE];
int time_to_exit = 0;
int main() {
creat_pthread();
down(&work_mutex);
while(true){
readToBufer();
up(&work_mutex);
while(1){
down(&work_mutex);
if(buffer:= null)
{
sleep(1);
}
else
{break;}
}

join();
}
a_thread(){
creatFile();
sleep(1);
down(&work_mutex);
while( input != end )
{
writeToFile(buffer);
up(&work_mutex);
}
}
程序代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
void *thread_function(void *arg);
pthread_mutex_t work_mutex; /* protects both work_area and time_to_exit */
#define WORK_SIZE 1024
char work_area[WO

RK_SIZE];
int time_to_exit = 0;
int main() {
int res;
pthread_t a_thread;
void *thread_result;
res = pthread_mutex_init(&work_mutex, NULL);
if (res != 0) {
perror("Mutex initialization faile");
exit(EXIT_FAILURE);
}
res = pthread_create(&a_thread, NULL, thread_function, NULL);
if (res != 0) {
perror("Thread creation failed");
exit(EXIT_FAILURE);
}
pthread_mutex_lock(&work_mutex);
printf("Input some text. Enter 'end' to finish\n");
while(!time_to_exit) {
fgets(work_area, WORK_SIZE, stdin);
pthread_mutex_unlock(&work_mutex);
while(1) {
pthread_mutex_lock(&work_mutex);
if (work_area[0] !='\0') {
pthread_mutex_unlock(&work_mutex);
sleep(1);
}
else {
break;
}
}
}
pthread_mutex_unlock(&work_mutex);fgets(work_area, WORK_SIZE, stdin);
printf("\nWaiting for thread to finish...\n");
res = pthread_join(a_thread, &thread_result);
if (res != 0) {
perror("Thread join faile");
exit(EXIT_FAILURE);
}
printf("Thread joined\n");
pthread_mutex_destroy(&work_mutex);
exit(EXIT_SUCCESS);
}
void *thread_function(void *arg) {
int out;
out=open("record",O_RDWR|O_CREAT);
sleep(1);
pthread_mutex_lock(&work_mutex);
while(strncmp("end", work_area, 3) != 0) {
write(out,work_area,strlen(work_area));
work_area[0] = '\0';
pthread_mutex_unlock(&work_mutex);
sleep(1);
pthread_mutex_lock(&work_mutex);
while (work_area[0] == '\0' ) {
pthread_mutex_unlock(&work_mutex);
sleep(1);
pthread_mutex_lock(&work_mutex);
}
}
time_to_exit = 1;
work_area[0] ='\0';
pthread_mutex_unlock(&work_mutex);
pthread_exit(0);
}
运行结果:

相关推荐
相关主题
热门推荐