操作系统第四次实验:进程调度实验

操作系统第四次实验:进程调度实验

前言

为了帮助同学们完成痛苦的实验课程设计,本作者将其作出的实验结果及代码贴至CSDN中,供同学们学习参考。如有不足或描述不完善之处,敬请各位指出,欢迎各位的斧正!

一、实验目的

  1. 熟悉PV操作的实现原理。
  2. 熟悉信号量机制。使用信号量机制模拟实现PV操作,从而控制多个进程对共享资源的使用。
  3. 通过在Linux中使用信号量进行进程同步和互斥的方法,进一步理解进程间同步与互斥、临界区与临界资源的概念与含义,并学会 Linux信号量的基本使用方法。

二、实验环境

实验机房软件Ubuntu和在VMware虚拟机上安装的Linux操作系统。

三、实验内容及步骤

本实验基本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_CREATE或O_CREATE | O_EXCL两个取值,O_CREATE表示信号量如存在,则打开之,如不存在,则创建;O_CREATE | O_EXCL表示信号量已存在,则返回error
    mode:信号量访问权限,如0666代表所有人可读写
    value:信号量初始化值
    (4)返回值:成功则返回信号量指针,出错则返回SEM_FAILED。
  2. 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运行,写出运行结果并分析。
操作系统第四次实验:进程调度实验
(2)如下示例(with_sem.c)中,设置了一个信号量mutex,初始值为1,表示当前无人使用临界区,信号量使用完毕后,需要关闭,之后删除。使用gcc -o with_mutex with_mutex.c -lrt编译链接后生成目标代码,再使用./with_mutex &./with_mutex B运行,写出运行结果并分析。
操作系统第四次实验:进程调度实验
(3)编写两个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);
return 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>
#include<unistd.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);
printf("\n");
	sem_close(mutex);
	sem_unlink("mysem");
	exit(0);
	
return 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);
	return 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 win!!!\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);
	return 0;
}

五、实验结果

操作系统第四次实验:进程调度实验
分析:在不使用互斥的程序中,x和B的出现没有什么规律。(进程同步)
操作系统第四次实验:进程调度实验
分析:在使用信号量来对临界资源进行互斥时,x和B以相同的数目交替出现。(进程互斥,进程交替执行)
操作系统第四次实验:进程调度实验
分析:在使用信号量来对临界资源进行互斥时,红方与黑方以相同的次数(一次)交替出现、交替下棋(进程互斥,进程交替执行)

六、实验总结

  1. 用于实现同步、互斥的信号量都是成对出现的。实现互斥的信号量成对的P原语在V原语之前,实现同步的信号量成对的P原语在V原语之后。
  2. 同步执行的进程不会因制约关系而相互等待,所以可以无序执行;并发执行的进程因直接制约关系而需相互等待,相互合作,以实现各进程按相互协调的速度向前推进。
  3. 通过使用信号量,可以实现多个进程对临界资源的互斥访问,从而解决互斥问题,可以实现进程或语句之间的前趋关系,即实现进程之间的直接制约关系,从而解决同步问题。
上一篇:线程


下一篇:1|进程管理 linux l例子