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

前言

为了帮助同学们完成痛苦的实验课程设计,本作者将其作出的实验结果及代码贴至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. 通过使用信号量,可以实现多个进程对临界资源的互斥访问,从而解决互斥问题,可以实现进程或语句之间的前趋关系,即实现进程之间的直接制约关系,从而解决同步问题。

标签: int, 实验, include, 操作系统, 信号量, mutex, 调度, sem, chess

相关文章推荐

添加新评论,含*的栏目为必填