操作系统的课程设计

多线程和多进程同步方法解决水果分配问题:

水果分配的问题:

桌上有一只盘子,每次只能放入5只水果。爸爸专放苹果,

妈妈专放橘子,一个儿子专等吃盘子中的橘子,一个女儿专等吃盘子中的苹果.用P,V操作实现爸爸、妈妈、儿子、女儿进程的同步控制。

补充:设有两个篮子,分别有若干个苹果或橘子,爸爸和妈妈将每次从水果篮子中拿出一个水果放入水果盘中,儿子女儿则挑选各自喜欢的水果。

(1) 分析问题,写出伪代码

(2) 线程实现

(3) 进程实现

python3.5.2 threading 和multiprocessing模块

一、 实验题目... 3

二、 实验目的和要求... 3

三、 环境配置... 4

四、 设计思路... 6

五、 代码实现... 7

六、 总结... 17

一、    实验题目

1.      Linux 系统简单使用

(1)认识Linux

(2)ubuntu安装

(3)终端的简单使用

(4)python3.5.2源码安装

2.      多线程和多进程同步方法解决水果分配问题:

水果分配的问题:

桌上有一只盘子,每次只能放入5只水果。爸爸专放苹果,

妈妈专放橘子,一个儿子专等吃盘子中的橘子,一个女儿专等吃盘子中的苹果.用P,V操作实现爸爸、妈妈、儿子、女儿进程的同步控制。

补充:设有两个篮子,分别有若干个苹果或橘子,爸爸和妈妈将每次从水果篮子中拿出一个水果放入水果盘中,儿子女儿则挑选各自喜欢的水果。

(1) 分析问题,写出伪代码

(2) 线程实现

(3) 进程实现

二、    实验目的和要求

1. 认识和学会使用linux系统:

Linux 是一种可以在PC机上执行的类似UNIX的操作系统,是一个完全免费的操作系统。1991年,芬兰学生Linus Torvalds开发了这个操作系统的核心部分,因为是Linus 改良的minix系统,故称之为Linux.

2. 理解线程和进程的互斥和同步原理:

同步是操作系统级别的概念,是在多道程序的环境下,存在着不同的制约关系,为了协调这种互相制约的关系,实现资源共享和进程协作,从而避免进程之间的冲突,引入了进程同步。

进程互斥是间接制约关系。当一个进程进入临界区使用临界资源时,另一个进程必须等待。只有当使用临界资源的进程退出临界区后,这个进程才会解除阻塞状态。

3. 使用信号量和互斥量解决问题:

通过设置一个表示资源个数的信号量S,通过对信号量S的P和V操作来实现进程的的互斥。

通过设置一个表示资源个数的信号量S,通过对信号量S的P和V操作来实现进程的的互斥。

P和V操作分别来自荷兰语Passeren和Vrijgeven,分别表示占有和释放。P V操作是操作系统的原语,意味着具有原子性。

P操作首先减少信号量,表示有一个进程将占用或等待资源,然后检测S是否小于0,如果小于0则阻塞,如果大于0则占有资源进行执行。

V操作是和P操作相反的操作,首先增加信号量,表示占用或等待资源的进程减少了1个。然后检测S是否小于0,如果小于0则唤醒等待使用S资源的其它进程。

三、    环境配置

1. 安装ubuntu

(1)    下载系统镜像,ubuntu-16.04.1-desktop-amd64.iso

(2)    制作启动U盘,使用Ultraiso软件将系统镜像写入U盘

(3)    开机进入BIOS界面,从U盘启动。

(4)    对磁盘分区,等待安装结束。

(5)    设置root密码,sudo passwd root 命令后输入两遍密码。

2. 熟悉ubuntu的使用

常用命令:

(1)    su命令,切换用户

(2)    pwd命令,打印当前工作目录的绝对路径

(3)    ls命令,打印当前目录下的文件

(4)    cd命令,切换工作目录

(5)    mv命令,移动文件或目录

(6)    rm命令,删除文件或目录

(7)    shutdown命令,关闭计算机

(8)    reboot命令,重启电脑

(9)    tar命令,解压命令

3. 安装vim编辑器

在终端下运行apt-get install –y vim即可。

安装结束后,输入vim命令,显示如下图就说明安装成功:

Figure 1 安装vim后输入vim显示的结果

4. 源码安装python3.5.2

因为linux内置的python的版本为2.7.5,所以为了程序设计的方便,使用3.5.2版本的。终端下输入python即可进入python交互模式。

安装前

Figure2 内置python运行结果

安装步骤:

(1)    进入下载目录,tar –zxvf Python-3.5.2.tar.gz 解压到当前目录下

(2)    进入解压目录,cd Python-3.5.2

(3)    验证系统配置,./configure

(4)    编译和安装,make && make install

(5)    建立软链接,在/usr/bin目录下生成python3的软链接文件

安装结果:

Figure3 python3安装结果

四、    设计思路

1. 题目分析

father、mather、son、daughter是四个线程或进程。

盘子plate是它们共享的变量,对盘子的操作要互斥。

Father和daughter要对apple同步。

Mother和son要对orange同步。

2.     伪代码
father:
while(True):
       p(empty)
       p(mutex)
       putapple
       v(mutex)
       v(apple)

mother:
while(True):
    p(empty)
    p(mutex)
    put orange
    v(mutex)
    v(orange)

son:
while(True):
    p(orange)
    p(mutex)
    get orange
    v(mutex)
    v(empty)

daughter:
while(True):
    p(apple)
    p(mutex)
    get apple
    v(mutex)
    v(empty)

五、    代码实现

1.     线程实现

(1)   原理

threading.py模块提供了对线程的操作。

创建线程threading.Thread(target,  args),target是要运行的函数,args是函数所需的参数。

创建信号量threading.Semaphore(value),value是信号量的初始值。acquire() 信号量-1,当为0时,阻塞当前线程。release() 信号量+1,大于0,唤醒等待此信号量的一个线程。

创建互斥锁,threading.Lock(),acquire() 加锁,release()解锁。

(2)   变量

定义list类型的 apples_basket 存放所有的苹果

定义list类型的 oranges_basket 存放所有的橘子

定义list类型的plate当做水果盘,可以放入苹果和橘子

定义方法father ,用于将苹果放入水果盘,也就是把apples_basket的一个苹果,放入plate列表中。并打印相关信息。

定义方法mather ,用于将苹果放入水果盘,也就是把oranges_basket的一个橘子,放入plate列表中。并打印相关信息。

定义方法son ,用于从水果盘取出一个橘子,也就是把plate的一个橘子,拿出来,并打印相关信息。

定义方法daughter ,用于从水果盘取出一个苹果,也就是把plate的一个苹果,拿出来,并打印相关信息。

(3)   代码

import random

import threading

import time

empty =threading.Semaphore(5)  # 盘子的容量

apple =threading.Semaphore(0)  # 同步苹果的信号量

orange =threading.Semaphore(0)  # 同步橘子的信号量

mutex = threading.Event()  # 表示四个进程互斥的访问盘子

plate = list()  # 模拟水果盘

lock = threading.Lock()  # plate互斥锁

mutex.set()  # 设置为True

def father(basket):

global empty, mutex, lock, apple

while len(basket) != 0:  # 当苹果篮子中没有苹果,则终止

# 1.p(empty)

empty.acquire()  # 将容量empty减去1

# 2.p(mutex)

mutex.clear()  # mutex设置为False 其它线程将等待

# 3.put apple

if lock.acquire():

temp = basket.pop()

plate.append(temp)  # 从苹果篮子里拿出一个苹果放入水果盘

print('->father put anapple({0}) into plate.'.format(temp))

print('  current plate = ', plate)

lock.release()

# 4.v(mutex)

mutex.set()  # mutex设置为True, 其它线程可以使用

# 5.v(apple)

apple.release()

time.sleep(random.random())

def mother(basket):

global empty, mutex, lock, orange

while len(basket) != 0:  # 当橘子篮子中没有橘子,则终止

# 1.p(empty)

empty.acquire()  # 将容量empty减去1

# 2.p(mutex)

mutex.clear()  # mutex设置为False 其它线程将等待

# 3.put(orange)

if lock.acquire():

temp = basket.pop()

plate.append(temp)

print('->mother put anorange({0}) into plate.'.format(temp))

print('  current plate = ', plate)

lock.release()

# 4.v(mutex)

mutex.set()  # mutex设置为True, 其它线程可以使用

# 5.v(orange)

orange.release()

time.sleep(random.random())

def son(count):

global empty, mutex, lock, orange

for i in range(count):

# 1.p(orange)

orange.acquire()  # orange -1

# 2.p(mutex)

mutex.clear()  # mutex设置为False 其它线程将等待

# 3.get orange

if lock.acquire():

for fruit in plate:

if fruit.startswith('Orange'):

temp = fruit

plate.remove(fruit)

break

print('->son take an orange({0})from plate.'.format(temp))

print('  current plate = ', plate)

lock.release()

# 4.v(mutex)

mutex.set()  # mutex设置为True, 其它线程可以使用

# 5.v(empty)

empty.release()  # 将empty + 1

time.sleep(random.random())

def daughter(count):

global empty, mutex, lock, apple

for i in range(count):

# 1.p(apple)

apple.acquire()  # apple -1

# 2.p(mutex)

mutex.clear()  # mutex设置为False 其它线程将等待

# 3.get apple

if lock.acquire():

for fruit in plate:

if fruit.startswith('Apple'):

temp = fruit

plate.remove(fruit)

break

print('->daughter take anapple({0}) from plate'.format(temp))

print('  current plate = ', plate)

lock.release()

# 4.v(mutex)

mutex.set()  # mutex设置为True, 其它线程可以使用

# 5.v(empty)

empty.release()  # 将empty + 1

time.sleep(random.random())

if __name__ == '__main__':

# 初始化苹果和橘子的个数

apples_basket = ['Apple-A', 'Apple-B','Apple-C', "Apple-D"]  # 模拟苹果篮子,一共有4个苹果要放入水果盘

oranges_basket = ['Orange-A', 'Orange-B','Orange-C']  # 模拟橘子篮子,一共有3个橘子要放入水果盘

# 创建4个线程

father = threading.Thread(name='Father',target=father, args=(apples_basket, ))  #father 线程

mother = threading.Thread(name='Mother',target=mother, args=(oranges_basket, )) # mother 线程

son = threading.Thread(name='Son',target=son, args=(len(oranges_basket), )) # son 线程

daughter =threading.Thread(name='Daughter', target=daughter, args=(len(apples_basket),))  # daughter 线程

# 启动线程

daughter.start()

son.start()

father.start()

mother.start()

(4)   结果

Figure4线程实现结果

2.     进程实现

(1)         原理

multiprocessing.py模块提供了对线程的操作。

创建线程multiprocessing.Process(target,  args),target是要运行的函数,args是函数所需的参数。

创建信号量multiprocessing.Semaphore(value),value是信号量的初始值。acquire() 信号量-1,当为0时,阻塞当前线程。release() 信号量+1,大于0,唤醒等待此信号量的一个线程。

创建互斥锁,multiprocessing.Lock(),acquire() 加锁,release()解锁。

(2)         变量

定义list类型的 apples_basket 存放所有的苹果

定义list类型的 oranges_basket 存放所有的橘子

定义list类型的plate当做水果盘,可以放入苹果和橘子

定义方法father ,用于将苹果放入水果盘,也就是把apples_basket的一个苹果,放入plate列表中。并打印相关信息。

定义方法mather ,用于将苹果放入水果盘,也就是把oranges_basket的一个橘子,放入plate列表中。并打印相关信息。

定义方法son ,用于从水果盘取出一个橘子,也就是把plate的一个橘子,拿出来,并打印相关信息。

定义方法daughter ,用于从水果盘取出一个苹果,也就是把plate的一个苹果,拿出来,并打印相关信息。

(3)         代码

import random

import multiprocessing

import time

empty =multiprocessing.Semaphore(5)  # 盘子的容量

apple =multiprocessing.Semaphore(0)  # 同步苹果的信号量

orange =multiprocessing.Semaphore(0)  # 同步橘子的信号量

mutex =multiprocessing.Event()  # 表示四个进程互斥的访问盘子

manager =multiprocessing.Manager()

plate = manager.list()  # 模拟水果盘

lock =multiprocessing.Lock()  # plate互斥锁

mutex.set()  # 设置为True

def father(basket):

global empty, mutex, lock, apple

while len(basket) != 0:  # 当苹果篮子中没有苹果,则终止

# 1.p(empty)

empty.acquire()  # 将容量empty减去1

# 2.p(mutex)

mutex.clear()  # mutex设置为False 其它线程将等待

# 3.put apple

if lock.acquire():

temp = basket.pop()

plate.append(temp)  # 从苹果篮子里拿出一个苹果放入水果盘

print('->father put anapple({0}) into plate.'.format(temp))

print('  current plate = ', plate)

lock.release()

# 4.v(mutex)

mutex.set()  # mutex设置为True, 其它线程可以使用

# 5.v(apple)

apple.release()

time.sleep(random.random())

def mother(basket):

global empty, mutex, lock, orange

while len(basket) != 0:  # 当橘子篮子中没有橘子,则终止

# 1.p(empty)

empty.acquire()  # 将容量empty减去1

# 2.p(mutex)

mutex.clear()  # mutex设置为False 其它进程将等待

# 3.put(orange)

if lock.acquire():

temp = basket.pop()

plate.append(temp)

print('->mother put anorange({0}) into plate.'.format(temp))

print('  current plate = ', plate)

lock.release()

# 4.v(mutex)

mutex.set()  # mutex设置为True, 其它进程可以使用

# 5.v(orange)

orange.release()

time.sleep(random.random())

def son(count):

global empty, mutex, lock, orange

for i in range(count):

# 1.p(orange)

orange.acquire()  # orange -1

# 2.p(mutex)

mutex.clear()  # mutex设置为False 其它进程将等待

# 3.get orange

if lock.acquire():

for fruit in plate:

if fruit.startswith('Orange'):

temp = fruit

plate.remove(fruit)

break

print('->son take an orange({0})from plate.'.format(temp))

print('  current plate = ', plate)

lock.release()

# 4.v(mutex)

mutex.set()  # mutex设置为True, 其它进程可以使用

# 5.v(empty)

empty.release()  # 将empty + 1

time.sleep(random.random())

def daughter(count):

global empty, mutex, lock, apple

for i in range(count):

# 1.p(apple)

apple.acquire()  # apple -1

# 2.p(mutex)

mutex.clear()  # mutex设置为False 其它进程将等待

# 3.get apple

if lock.acquire():

for fruit in plate:

if fruit.startswith('Apple'):

temp = fruit

plate.remove(fruit)

break

print('->daughter take anapple({0}) from plate'.format(temp))

print('  current plate = ', plate)

lock.release()

# 4.v(mutex)

mutex.set()  # mutex设置为True, 其它进程可以使用

# 5.v(empty)

empty.release()  # 将empty + 1

time.sleep(random.random())

if __name__ == '__main__':

# 初始化苹果和橘子的个数

apples_basket = ['Apple-A', 'Apple-B','Apple-C', "Apple-D"]  # 模拟苹果篮子,一共有4个苹果要放入水果盘

oranges_basket = ['Orange-A', 'Orange-B','Orange-C']  # 模拟橘子篮子,一共有3个橘子要放入水果盘

# 创建4个进程

father =multiprocessing.Process(name='Father', target=father, args=(apples_basket,))  # father 进程

mother =multiprocessing.Process(name='Mother', target=mother, args=(oranges_basket,))  # mother 进程

son = multiprocessing.Process(name='Son',target=son, args=(len(oranges_basket), )) # son 进程

daughter =multiprocessing.Process(name='Daughter', target=daughter,args=(len(apples_basket), ))  # daughter 进程

# 启动进程

daughter.start()

son.start()

father.start()

mother.start()

daughter.join()

son.join()

father.join()

mother.join()

print("End!")

(4)         结果

Figure5进程实现结果

六、    总结

因为之前就在慕课网上看过linux使用的教程,学过centos7字符界面的使用。在课程设计前就装好了win10 + Ubuntu 16.04 LTS双系统。所以在熟悉linux使用上并没有花时间。

初期使用linux最大的麻烦就是安装软件。安装方式有源码安装和二进制包安装。使用熟练后装软件的速度还是比windows上慢。不过各有优缺点。因为软件开发在linux上比较方便,就逐渐从windows平台转移到linux上了。

Ubuntu这个发行版本的图形界面做的还是比较美观的。

使用linux的过程中让我对多用户操作系统更加了解,虽然windows系统也是多用户操作系统,但是平常使用的时候都是超级管理员身份,所以感触不深。Linux对文件权限管理十分严格,只有相应的用户身份才能获得使用这个文件的特定权限。

使用python的原因是python的语法简洁、优雅。没有c和c++的指针,实现比较方便。Java的代码太过繁琐,不适合快速实现想法。

Python的中文文档相对较少,有些模块是对c的封装,看不见源码。所以在学习threading.py 和multiprocessing.py 的时候百度的东西十分琐碎,影响了开发速度。

本次实验后,对线程和进程也有了更深更具体的体会。进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。

具体区别如下:

地址空间和其它资源:进程间相互独立,同一进程的各线程间共享。某进程内的线程在其它进程不可见。

通信:进程间通信IPC,线程间可以直接读写进程数据段(如全局变量)来进行通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。

调度和切换:线程上下文切换比进程上下文切换要快得多。

Python对线程的支持不如java等语言好。因为Python多线程下,每个线程的执行方式:
1.取GIL
2.执行代码直到sleep或者是python虚拟机将其挂起。
3.释放GIL

可见,某个线程想要执行,必须先拿到GIL,我们可以把GIL看作是“通行证”,并且在一个python进程中,GIL只有一个。拿不到通行证的线程,就不允许进入CPU执行。每次释放GIL锁,线程进行锁竞争、切换线程,会消耗资源。并且由于GIL锁存在,python里一个进程永远只能同时执行一个线程(拿到GIL的线程才能执行),这就是为什么在多核CPU上,python的多线程效率并不高。

但是并不意味着python的多线程就没有用了,在执行密集型代码(文件处理、网络爬虫等),多线程能够有效提升效率(单线程下有IO操作会进行IO等待,造成不必要的时间浪费,所以python的多线程对IO密集型代码比较友好。

在多核CPU下,用多进程效率高,在单核CPU下,使用多线程效率高。

此次课程设计收获最大的还是学会了,怎么用信号量控制线程和多个进程之间的同步和互斥。

操作系统课程设计-线程和进程的同步与互斥相关推荐

  1. 操作系统二轮复习(进程的同步与互斥)

    文章目录 进程互斥与同步四原则 进程互斥的软件实现方法 单标志法(空闲让进) 双标志先检查法(忙则等待) 双标志后检查法(空闲让进.有限等待) 皮特森算法(让权等待) 小结 进程互斥的硬件实现方法 中 ...

  2. Linux并发程序课程设计报告,网络操作系统课程设计--进程机制与并发程序设计-linux下生产者与消费者的问题实现.doc...

    网 络 操 作 系 统 课 程 设 计 网络操作系统课程设计 设计内容:进程机制与并发程序设计inux下生产者与消费者的问题实现进程机制与并发程序设计inux下生产者与消费者的问题实现 (1)掌握基本 ...

  3. python枪战项目计划书_燕山大学操作系统课程设计计划书

    燕山大学操作系统课程设计计划书 燕山大学课程设计计划书 课程设计名称:操作系统 题目:多道程序缓冲区协同操作 年级:2016级 开发小组名称:WWW. 小组负责人: 课题组成员: 姓名 学号 班级 分 ...

  4. python操作系统课程设计_操作系统课程设计.pdf

    计算机科学与通信工程学院 操作系统课程设计报告 题目:linux系统下实现PV 操作 班级: 软件工程1401 姓名: 吴帅帅 学号: 3140608020 指导老师: 牛德姣 2016 年12 月2 ...

  5. 西工大计算机操作系统实验报告,西工大计算机操作系统课程设计实验报告bh05xh5...

    <西工大计算机操作系统课程设计实验报告bh05xh5>由会员分享,可在线阅读,更多相关<西工大计算机操作系统课程设计实验报告bh05xh5(7页珍藏版)>请在人人文库网上搜索. ...

  6. HDU操作系统课程设计实验三

    HDU操作系统课程设计实验三 一.设计目的 二.内容要求 三.实验内容 信号量的使用 1.实现一个模拟的shell,基本功能加find.grep命令 2.实现一个管道通信程序,基本功能加有名管道通信 ...

  7. 操作系统课程设计geekos project1-3

    概述 实验环境 GeekOS-0.3.0 Bochs和Vmware介绍 开发过程 编译运行 配置文件 前导知识 一.全局描述符表GDT(Global Descriptor Table) 二.段选择子( ...

  8. 操作系统课程设计报告2021-2022——pintos

    操作系统课程设计报告 2021-2022 目录 操作系统课程设计报告 2021-2022 第一章 实验项目介绍 环境配置 ( 一 ). Ubuntu 服务器搭建 图形界面搭建 ( 二 ). Pinto ...

  9. 操作系统课程设计报告总结(下)

    操作系统课程设计报告总结(下) 实验六 银行家算法的模拟与实现 实验目的 总体设计 背景知识 基本原理 模块介绍 详细设计 关键代码及分析 实验结果与分析 小结与心得体会 银行家算法源码 实验七 磁盘 ...

最新文章

  1. 【Ubuntu入门到精通系列讲解】Ubuntu 图形界面入门
  2. 互联网趋势关键词:交流,为价值付费,资源整合
  3. Spring boot使用Bootstrap
  4. 对归并排序进行c语言编程实现,归并排序及C语言实现
  5. 文本”Hello, world.”显示的颜色是?
  6. 【2050 Programming Competition - 2050 一万人码 】非官方部分题解(HDU)
  7. IEnumerable接口
  8. JS--------文件操作基本方法:上传/下载
  9. java静态注解处理器_java – 使用mapstruct中的builder(使用immutables注释处理器)将对象映射到不可变对象...
  10. matlab二进制十进制十六进制和任意进制之间的转换
  11. 谷歌研发开源协议,助听器有望原生支安卓系统
  12. gunicorn的用法
  13. Windows XP优化设置之网络篇
  14. 号码检测,节省成本利器
  15. 关于程序的入口函数(main _start...)
  16. matlab符号函数subs,什么是matlab subs函数?
  17. 寻找大学目标及行动步骤——记ITAEM团队第二期宣讲会(2014.05.14)
  18. ffmpeg批量提取mp4视频文件中的音频
  19. 什么因素影响阿里云国际版云服务器延迟?
  20. EPLAN_语言翻译工具的使用

热门文章

  1. php网页自定义头像系统,怎样用canvas实现自定义头像功能
  2. hadoop学习笔记411
  3. 芯片设计制造和人工智能
  4. <Verilog实现除法器> Verilog实现恢复余数(restoring)除法器
  5. 常见前端面试题:html语义化
  6. tracer王_跨界明星,从王天天到Tracer85车手,兴趣玩成专业。
  7. a+=b和a=a+b是一样的吗?
  8. A40上tensorflow的安装
  9. 伯乐识马,天九共享独角兽加速合作大会盛大开幕
  10. 网络安全kali之利用宏感染word文档获取shell