【操作系统】实验三 进程的互斥与同步

目录

实验目的及要求

实验环境

实验原理

实验内容及步骤

实验源代码

实验结果与分析

实验收获与体会


本人一直想找时间系统整理一下之前做过的一些实验,便于后续用到的时候可以尽快的使用,po出来也便于大家交流学习,有问题欢迎交流指正,与诸君共勉!

操作系统实验三,进程的互斥与同步。

实验目的及要求

1. 熟悉PV操作的实现原理。

2. 熟悉信号量机制。使用信号量机制模拟实现PV操作,从而控制多个进程对共享资源的使用。

3. 通过在Linux中使用信号量进行进程同步和互斥的方法,进一步理解进程间同步与互斥、临界区与临界资源的概念与含义,并学会 Linux信号量的基本使用方法。

实验环境

VMware虚拟机、CentOS操作系统

实验原理

本实验基于POSIX有名信号量实现(既可用于进程间同步,也可用于线程间同步),其介绍如下。

  1. sem_open:创建并初始化一个有名信号量,如该信号量已经存在,则打开它。
  1. 函数原型:sem_t* sem_open(const char *name, int oflag, mode_t mode, int value);
  2. 头文件:#include<semaphore.h>
  3. 参数:name: 文件名路径,如’mysem’,会创建/dev/shm/sem.mysem

oflag:创建标志,有O_CREAT或O_CREAT | O_EXCL两个取值,O_CREAT表示信号量如存在,则打开之,如不存在,则创建;O_CREATE | O_EXCL表示信号量已存在,则返回error

mode:信号量访问权限,如0666代表所有人可读写

value:信号量初始化值

  1. 返回值:成功则返回信号量指针,出错则返回SEM_FAILED。
  1. sem_wait:测试指定信号量的值,相当于P操作。若信号量大于0,则减1立刻返回,如信号量值等于0,则阻塞直到信号量值大于0,此刻立即减1,然后返回。

(1)函数原型:int sem_wait(sem_t *sem);

(2)头文件:#include<semaphore.h>

(3)参数:sem,要测试的信号量指针。

(4)返回值:成功则返回0,出错则返回-1。

3.  sem_post:信号量值加1,相当于V操作。唤醒正在等待该信号量的某个进程或线程。

(1)函数原型:int sem_post(sem_t *sem)

(2)头文件:#include<semaphore.h>

(3)参数:sem,要访问的信号量指针。

(4)返回值:成功则返回0,出错返回-1。

4.  int sem_close(sem_t *sem):关闭有名信号量,进程中,如果使用完信号量,应使用该函数关闭有名信号量。

5.  int sem_unlink(const char *name):删除系统中的信号量,如果有任何进程/线程引用这个信号量,sem_unlink函数不会起到任何作用,即只有最后一个使用该信号量的进程来执行sem_unlink才有效。

实验内容及步骤

1.  编写一个C语言程序,进行10次循环,每个循环中,屏幕输出两次给定的字符。在使用互斥和不使用互斥的两种情况下,观察多个进程运行时的输出情况。

(1) 使用gcc -o no_mutex no_mutex.c编译链接后生成目标代码,

再使用./no_mutex&./no_mutex B运行,写出运行结果并分析。

  1. 如下示例(with_sem.c)中,设置了一个信号量mutex,初始值为1,表示当前无人使用临界区,信号量使用完毕后,需要关闭,之后删除。使用gcc -o with_mutex with_mutex.c -lrt编译链接后生成目标代码,再使用./with_mutex &./with_mutex B运行,写出运行结果并分析。

  1. 编写两个C语言black_chess.c以及red_chess.c,分别模拟下象棋过程中红方走子和黑方走子过程。走子规则:红先黑后,红、黑双方轮流走子,到第10步,红方胜,黑方输。

解题思路:设置以下两个同步信号量hei:初值1,代表黑方已经走子,轮到红方走子(满足“红先黑后”),hong:初值为0,代表红方尚未走子。

红方进程代码:red_chess.c如下,请编写出黑方代码black_chess.c,编译:

gcc -o red_chess red_chess.c -lrt

gcc -o black_chess black_chess.c -lrt

 运行:

./red_chess&./black_chess

写出运行结果,并分析总结。

实验源代码

	no_mutex.c
#include<stdio.h>
#include<stdlib.h>

int main(int argc, char* argv[])
{
	char message = 'x';
	int i = 0;
	if (argc > 1) {
		message = argv[1][0];
	}
	for (i = 0;i < 10;i++) {
		printf("%c", message);
		fflush(stdout);
		sleep(rand() % 3);
		printf("%c", message);
		fflush(stdout);
		sleep(rand() % 2);
	}
	sleep(10);
	exit(0);
}
	with_mutex.c
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<semaphore.h>
#include<fcntl.h>
#include<sys/stat.h>

int main(int argc, char* argv[])
{
	char message = 'x';
	int i = 0;
	if (argc > 1) {
		message = argv[1][0];
	}
	sem_t* mutex = sem_open("mysem", O_CREAT, 0666, 1);
	for (i = 0;i < 10;i++) {
		sem_wait(mutex);
		printf("%c", message);
		fflush(stdout);
		sleep(rand() % 3);
		printf("%c", message);
		fflush(stdout);
		sem_post(mutex);
		sleep(rand() % 2);
	}
	sleep(10);
	sem_close(mutex);
	sem_unlink("mysem");
	exit(0);
}
	red_chess.c
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<semaphore.h>
#include<fcntl.h>
#include<sys/stat.h>

int main(int argc,char *argv[]){
	int i=0;
	
	sem_t *hei=sem_open("chess_black_sem",O_CREAT,0666,1);
	sem_t *hong=sem_open("chess_red_sem",O_CREAT,0666,0);
	for(i=0;i<10;i++){
		sem_wait(hei);
		if(i!=9){
			printf("Red chess had moved,black chess go!\n");
		}else{
			printf("Red chess win!!!\n");
		}
		fflush(stdout);
		sem_post(hong);
	}
	
	sleep(10);
	sem_close(hei);
	sem_close(hong);
	sem_unlink("chess_red_sem");
	sem_unlink("chess_black_sem");
	exit(0);
}
	black_chess.c
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<semaphore.h>
#include<fcntl.h>
#include<sys/stat.h>

int main(int argc,char *argv[]){
	int i=0;
	
	sem_t *hei=sem_open("chess_black_sem",O_CREAT,0666,1);
	sem_t *hong=sem_open("chess_red_sem",O_CREAT,0666,0);
	for(i=0;i<10;i++){
		sem_wait(hong);
		if(i!=9){
			printf("Black chess had moved,red chess go!\n");
		}else{
			printf("Black chess lost!!!\n");
		}
		fflush(stdout);
		sem_post(hei);
	}
	
	sleep(10);
	sem_close(hei);
	sem_close(hong);
	sem_unlink("chess_red_sem");
	sem_unlink("chess_black_sem");
	exit(0);
}

实验结果与分析

  1. 编写c语言程序no_mutex.c,如图1。

1 编写c语言程序no_mutex.c

使用gcc -o no_mutex no_mutex.c编译链接后生成目标代码,

使用./no_mutex&./no_mutex B运行,运行结果如图2。

2 运行no_mutex结果

运行结果分析:在不使用互斥的情况下,进程同步,从进程运行的输出来看,xB随机出现。

  1. 编写c语言程序with_mutex.c如图3。

3 with_mutex.c程序

使用gcc -o with_mutex with_mutex.c -lrt编译链接后生成目标代码。

使用./with_mutex &./with_mutex B运行,运行结果如图4。

4 with_mutex.c程序编译运行结果

运行结果分析:在使用互斥的情况下,xB以相同数目交替出现。进程间互斥,故进程交替执行。

  1. 编写c语言程序black_chess.c以及red_chess.c,红方代码red_chess.c如图5,按照走子规则编写黑方代码black_chess.c如图6。

5 编写程序red_chess.c

6编写程序black_chess.c

编译:gcc -o red_chess red_chess.c -lrt -pthread

gcc -o black_chess black_chess.c -lrt -pthread

运行:./red_chess&./black_chess 结果如图7。

7 red_chess black_chess运行结果

运行结果分析:在使用信号量控制临界资源互斥时,红方走子和黑方走子每方一次交替发生,此时进程间互斥,进程交替执行。

实验收获与体会

本次实验中通过对于实验代码的编写,我巩固了PV操作的原理,对信号量机制也有了更为深刻的理解,学会了使用信号量模拟实现PV操作的方法,从而学会了控制多个进程对共享资源的使用的方法。‘

通过对实验代码运行结果的观察,我更加理解了进程间的同步与互斥、临界区与临界资源等概念,在实验过程中也再一次巩固了我对于Linux系统常用指令的使用,这将为我今后操作系统的学习打下牢固的基础。

实验结果往往能给我更加深刻的印象以及对课本理论知识更为深刻的理解,今后的理论知识学习过程中也应该注重动手实践。

  • 22
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值