操作系统 实验三 进程线程同步编程练习

【要求】所有练习题保留题目要求,在题目要求后面作答:

代码要求有注释,代码中适当标注关键代码为红色。

要有运行结果的截图。

每题最后应该有对程序的适当分析和总结!

注意格式排版,内容分析注意列条目,展开清楚地阐述。


1、实现多个进程之间互斥访问临界资源(进程个数不限,先写出PV操作的伪算法,然后进行算法实现

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>

int mutex;
char ch;

int main()
{
	pid_t pid;
	pid_t pids[2];
	int i, j;
	struct sembuf p, v;
	mutex = semget(IPC_PRIVATE, 1, 0666|IPC_CREAT); // 创建信号量
	semctl(mutex, 0, SETVAL, 1);  // 互斥信号量mutex赋初值为1

	// 定义p操作 信号量申请操作
	p.sem_num = 0;
	p.sem_op = -1;
	p.sem_flg = SEM_UNDO;

	// 定义v操作 信号量释放操作
	v.sem_num = 0;
	v.sem_op = 1;
	v.sem_flg = SEM_UNDO;

	for(i = 0;i <= 2; i++){
		pid = fork();
		if(pid == 0){ // 子进程
			while(1){
				printf("%d want to enter --WAIT\n",i);
				semop(mutex, &p, 1); // 信号量操作的申请wait
				printf("%d is in\n",i);
				sleep(3);
				semop(mutex, &v, 1); // 信号量操作的释放signal
				printf("%d is out --SIGNAL OK\n",i);
			}//while
		}else{pids[i] = pid;}
	} //for

	do{
		ch = getchar();
		if(ch == 'q') // 杀死所有进程
			for(i = 0;i <=2; i++)
				kill(pids[i], SIGTERM);
	}while(ch!='q');
}

三个pid进程(i=0,1,2)互斥访问临界资源mutex,每次访问前申请信号量执行p操作,指令完成后释放信号量执行v操作;最后手动结束所有进程


2、不死锁的哲学家进餐问题(课本有3种解决方法,可以选择一种或多种,先写出PV操作的伪算法,然后进行算法实现

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>

int P(int sem_id) // 申请资源
{
	struct sembuf sem_b;
	sem_b.sem_num = 0;
	sem_b.sem_op = -1;
	sem_b.sem_flg = SEM_UNDO;

	// 调用库函数,进行p操作
	if (semop(sem_id, &sem_b, 1) == -1)
	{
		fprintf(stderr, "P failed\n");
		return 0;
	}
	return 1;
}

int V(int sem_id) // 释放资源
{
	struct sembuf sem_b;
	sem_b.sem_num = 0;
	sem_b.sem_op = 1;
	sem_b.sem_flg = SEM_UNDO;

	// 调用库函数,进行v操作
	if (semop(sem_id, &sem_b, 1) == -1)
	{
		fprintf(stderr, "V failed\n");
		return 0;
	}
	return 1;
}

int roomnum = 0;
int chopstick[5];
char ch;

int main()
{
	roomnum = semget(IPC_PRIVATE, 1, 0666 | IPC_CREAT); // 创建信号量
	semctl(roomnum, 0, SETVAL, 4); // 至多只允许四个哲学家同时进餐
	int i = 0;
	pid_t pid;
	pid_t pids[5];
	for (i = 0; i < 5; i++)
	{
		chopstick[i] = semget(IPC_PRIVATE, 1, 0666 | IPC_CREAT);
		semctl(chopstick[i], 0, SETVAL, 1);
	}
	for (i = 0; i < 5; i++)
	{
		pid = fork();
		if (pid == 0) // child process manager code
		{
			while (1)
			{
				// 哲学家在思考,请勿打扰
				printf("Philosopher %d is thinking,No disterb\n",i);
				sleep(1);

				// 哲学家饿了,准备进入房间
				P(roomnum); // 这时申请资源
				printf("Philosopher %d is hungry,so he entered the room\n",i);

				// 哲学家拿左筷子
				P(chopstick[i]);
				printf("Philosopher %d pick up left chopstick\n", i);

				// 哲学家拿右筷子
				P(chopstick[(i + 1) % 5]);
				printf("Philosopher %d pick up right chopstick\n", i);

				// 有两只筷子后,开始进餐
				printf("Philosopher %d begins to eat!\n", i);
				sleep(5 - i);

				printf("Philosopher %d ends to eat!\n", i); //吃完饭了

				// 释放右筷子
				V(chopstick[(i + 1) % 5]);
				printf("Philosopher %d pick down right chopstick\n", i);

				// 吃完饭了,释放左筷子
				V(chopstick[i]);
				printf("Philosopher %d pick down left chopstick\n", i);

				// 哲学家进餐结束,释放资源
				V(roomnum);
				printf("Philosopger %d out of the room\n", i);

			}
		}else{pids[i] = pid;}
	}
}

	do{
		ch = getchar();
		if(ch == 'q') // 杀死所有进程
			for(i = 0; i < 5; i++)
				kill(pids[i], SIGTERM);
	}while(ch!='q');
}


3、三个进程P1、P2、P3互斥使用一个包含N个单元的缓冲区。P1每次用produe()产生一个正整数并用put()送入缓冲区某一空单元中;P2每次用getodd()从该缓冲区中取出一个奇数并用countodd()统计奇数个数;P3每次用geteven()从该缓冲区中取出一个偶数并用counteven()统计偶数个数。请用信号量机制实现这三个进程的同步和互斥活动,并说明所定义信号量的含义。(先写出PV操作的伪算法,然后进行算法实现


//定义P(wait)、V(signal)操作
int p(int sem_id) // 申请资源
{
	struct sembuf sem_b;
	sem_b.sem_num = 0;
	sem_b.sem_op = -1;
	sem_b.sem_flg = SEM_UNDO;

	// 调用库函数,进行p操作
	if (semop(sem_id, &sem_b, 1) == -1)
	{
		fprintf(stderr, "P failed\n");
		return 0;
	}
	return 1;
}

int v(int sem_id) // 释放资源
{
	struct sembuf sem_b;
	sem_b.sem_num = 0;
	sem_b.sem_op = 1;
	sem_b.sem_flg = SEM_UNDO;

	// 调用库函数,进行v操作
	if (semop(sem_id, &sem_b, 1) == -1)
	{
		fprintf(stderr, "V failed\n");
		return 0;
	}
	return 1;
}

// 使用信号量机制定义
semaphore mutex = 1; // 互斥访问缓冲区
semaphore empty = n; // 缓冲区中有n个单元
semaphore odd = 0;   // 奇数个数初始化为0
semaphore even = 0;  // 偶数个数初始化为0

void P1(){
    while(true){
        int num = produce();// 产生一个正整数num

        p(empty);  // 消耗掉一个空单元

        p(mutex);  // 申请访问缓冲区;
        put(num);
        v(mutex);  // 释放缓冲区

        if(num % 2 == 0)   // 如果num为偶数向P3发出信号
            v(even);
        else		   // 如果num为奇数向P2发出信号
            v(odd);
    }
}

void P2(){
    while(true){
        p(odd);     // 收到来自P1已产生奇数的信号

        p(mutex);   // 申请访问缓冲区
        getodd();   // 从缓冲区中取出一个奇数
        v(mutex);   // 释放缓冲区

        v(empty);   // 释放一个空单元,向P1发出信号

        countodd(); // 统计奇数个数
    }
}

void P3(){
    while(true){
        p(even);     // 收到来自P1已产生偶数的信号

        p(mutex);    // 申请访问缓冲区
        geteven();   // 从缓冲区释放一个偶数
        v(mutex);    // 释放缓冲区

        v(empty);    // 释放一个空单元,向P1发出信号

        counteven(); // 统计偶数个数
    }
}

  • 0
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

再见以前说再见

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值