目录
本人一直想找时间系统整理一下之前做过的一些实验,便于后续用到的时候可以尽快的使用,po出来也便于大家交流学习,有问题欢迎交流指正,与诸君共勉!
操作系统实验三,进程的互斥与同步。
实验目的及要求
1. 熟悉PV操作的实现原理。
2. 熟悉信号量机制。使用信号量机制模拟实现PV操作,从而控制多个进程对共享资源的使用。
3. 通过在Linux中使用信号量进行进程同步和互斥的方法,进一步理解进程间同步与互斥、临界区与临界资源的概念与含义,并学会 Linux信号量的基本使用方法。
实验环境
VMware虚拟机、CentOS操作系统
实验原理
本实验基于POSIX有名信号量实现(既可用于进程间同步,也可用于线程间同步),其介绍如下。
oflag:创建标志,有O_CREAT或O_CREAT | O_EXCL两个取值,O_CREAT表示信号量如存在,则打开之,如不存在,则创建;O_CREATE | O_EXCL表示信号量已存在,则返回error mode:信号量访问权限,如0666代表所有人可读写 value:信号量初始化值
(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运行,写出运行结果并分析。
解题思路:设置以下两个同步信号量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);
}
实验结果与分析
- 编写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结果
运行结果分析:在不使用互斥的情况下,进程同步,从进程运行的输出来看,x和B随机出现。
- 编写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程序编译运行结果
运行结果分析:在使用互斥的情况下,x和B以相同数目交替出现。进程间互斥,故进程交替执行。
- 编写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系统常用指令的使用,这将为我今后操作系统的学习打下牢固的基础。
实验结果往往能给我更加深刻的印象以及对课本理论知识更为深刻的理解,今后的理论知识学习过程中也应该注重动手实践。