进程、join方法、守护进程、互斥锁

  • 操作系统发展史

    • 发展史
      1. 1946年第一台计算机诞生--20世纪50年代中期,计算机工作还在采用手工操作方式。此时还没有操作系统的概念。2. 20世纪50年代后期,出现人机矛盾:手工操作的慢速度和计算机的高速度之间形成了尖锐矛盾,手工操作方式已严重损害了系统资源的利用率(使资源利用率降为百分之几,甚至更低),不能容忍。3. ?唯一的解决办法:只有摆脱人的手工操作,实现作业的自动过渡。这样就出现了成批处理。??
    • 批处理
      联机批处理系统(即作业的输入/输出由CPU来处理,例如 通过磁带)脱机批处理系统?(I/O--卫星机--高速磁带--主机)
    • 多道技术
      • 什么是多道技术
        即同时把多个程序放入内存,并允许它们交替在CPU中运行,?它们共享系统中的各种硬、软件资源。?当一道程序因I/O请求而暂停运行时,CPU便立即转去运行另一道程序。
      • 多道技术的使用
        1. 空间上的复用多个程序公用一套计算机硬件2.时间上的复用(切换+保存状态) a.当一个程序遇到 I/O?操作,操作系统会剥夺该程序的CPU执行权限 ?(提高 CPU利用率,并且不影响程序的执行效率) b.当一个程序?长时间占用CPU,操作系统会剥夺改程序的 CPU执行权限 (降低程序执行效率)
    • 多道技术之后的发展
      多道程序系统的出现,标志着操作系统渐趋成熟的阶段,先后出现了作业调度管理、处理机管理、存储器管理、外部设备管理、文件系统管理等功能。?由于多个程序同时在计算机中运行,开始有了空间隔离的概念,只有内存空间的隔离,才能让数据更加安全、稳定。?出了空间隔离之外,多道技术还第一次体现了时空复用的特点,遇到IO操作就切换程序,使得cpu的利用率提高了,计算机的工作效率也随之提高。
    • 分时系统、实时系统、通用操作系统
    • 个人计算机操作系统--网络操作系统--分布式操作系统
    • 操作系统
      • 理解
        操作系统就是一个协调、管理和控制计算机硬件资源和软件资源的控制程序
      • 作用
        1. 隐藏了丑陋的硬件调用接口,?为应用程序员提供调用硬件资源的 更简单,更清晰的模型(系统调用接口)2. 将应用程序对硬件资源的竞态请求变得有序化?
  • 进程
    • 什么是进程
      进程是一个执行中的程序进程是一个实体,每一个进程都有自己的地址空间?
    • 进程和程序的异同
      程序是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念。而进程是程序在处理机上的一次执行过程,它是一个动态的概念。程序可以作为一种软件资料长期存在,而进程是有一定生命期的。程序是永久的,进程是暂时的。
    • 进程调度的方法
      1.先来先服务先来先服务(FCFS)调度算法是一种最简单的调度算法,该算法既可用于作业调度,也可用于进程调度。FCFS算法比较有利于长作业(进程),而不利于短作业(进程)。由此可知,本算法适合于CPU繁忙型作业,而不利于I/O繁忙型的作业(进程)。?2.短作业优先?短作业(进程)优先调度算法(SJ/PF)是指对短作业或短进程优先调度的算法,该算法既可用于作业调度,也可用于进程调度。但其对长作业不利;不能保证紧迫性作业(进程)被及时处理;作业的长短只是被估算出来的。?3.时间轮转发时间片轮转(Round Robin,RR)法的基本思路是让每个进程在就绪队列中的等待时间与享受服务的时间成比例。在时间片轮转法中,需要将CPU的处理时间分成固定大小的时间片,例如,几十毫秒至几百毫秒。如果一个进程在被调度选中之后用完了系统规定的时间片,但又未完成要求的任务,则它自行释放自己所占有的CPU而排到就绪队列的末尾,等待下一次调度。同时,进程调度程序又去调度当前就绪队列中的第一个进程。在轮转法中,加入到就绪队列的进程有3种情况: 一种是分给它的时间片用完,但进程还未完成,回到就绪队列的末尾等待下次调度去继续执行。 另一种情况是分给该进程的时间片并未用完,只是因为请求I/O或由于进程的互斥与同步关系而被阻塞。当阻塞解除之后再回到就绪队列。 第三种情况就是新创建进程进入就绪队列。???4.多级反馈队列前面介绍的各种用作进程调度的算法都有一定的局限性。如短进程优先的调度算法,仅照顾了短进程而忽略了长进程,而且如果并未指明进程的长度,则短进程优先和基于进程长度的抢占式调度算法都将无法使用。而多级反馈队列调度算法则不必事先知道各种进程所需的执行时间,而且还可以满足各种类型进程的需要,因而它是目前被公认的一种较好的进程调度算法。在采用多级反馈队列调度算法的系统中,调度算法的实施过程如下所述。(1) 应设置多个就绪队列,并为各个队列赋予不同的优先级。第一个队列的优先级最高,第二个队列次之,其余各队列的优先权逐个降低。该算法赋予各个队列中进程执行时间片的大小也各不相同,在优先权愈高的队列中,为每个进程所规定的执行时间片就愈小。例如,第二个队列的时间片要比第一个队列的时间片长一倍,……,第i+1个队列的时间片要比第i个队列的时间片长一倍。(2) 当一个新进程进入内存后,首先将它放入第一队列的末尾,按FCFS原则排队等待调度。当轮到该进程执行时,如它能在该时间片内完成,便可准备撤离系统;如果它在一个时间片结束时尚未完成,调度程序便将该进程转入第二队列的末尾,再同样地按FCFS原则等待调度执行;如果它在第二队列中运行一个时间片后仍未完成,再依次将它放入第三队列,……,如此下去,当一个长作业(进程)从第一队列依次降到第n队列后,在第n 队列便采取按时间片轮转的方式运行。(3) 仅当第一队列空闲时,调度程序才调度第二队列中的进程运行;仅当第1~(i-1)队列均空时,才会调度第i队列中的进程运行。如果处理机正在第i队列中为某进程服务时,又有新进程进入优先权较高的队列(第1~(i-1)中的任何一个队列),则此时新进程将抢占正在运行进程的处理机,即由调度程序把正在运行的进程放回到第i队列的末尾,把处理机分配给新到的高优先权进程。??
    • 多级反馈队列图解

    • 进程的并行与并发
      并发:看起来像同时运行就可以并行:真正意义上的同时执行 单核计算机不能实现并行,可以实现并发?????
    • 进程的阻塞非阻塞
      阻塞非阻塞:表示程序的运行状态??阻塞:阻塞态( I/O操作,文件操作,sleep都能使运行-->阻塞态)非阻塞:就绪态、运行态??
    • 程序三态转换图

    • 程序的三态代码示例

    • 程序的同步异步
      同步异步:表示程序的提交方式同步:??????任务提交后,原地等待任务的执行,并拿到返回结果才走,期间不做任何事(程序层面的表现就是卡住了)异步:任务提交后,不在原地等待?,二十继续执行下一行代码(结果是要的,但是通过其他方式获取)
  • 创建进程的两种方式
    • 理解创建进程
      创建进程就是在内存中重新开辟一块内存空间将运行产生的代码丢进去?一个进程对应在内存就是一块独立的内存空间进程与进程之间数据是隔离的 无法直接交互但是可以通过某些技术实现间接交互
    • 第一种(直接使用mutiprocessing的Process模块)
      from multiprocessing import Process?import timedef test(name): print(‘%s is running‘%name) time.sleep(3) print(‘%s is over‘%name)?"""windows创建进程会将代码以模块的方式 从上往下执行一遍linux会直接将代码完完整整的拷贝一份windows创建进程一定要在if __name__ == ‘__main__‘:代码块内创建 否则报错"""???if __name__ == ‘__main__‘: p = Process(target=test,args=(‘egon‘,)) # 创建一个进程对象 p.start() # 告诉操作系统帮你创建一个进程 print(‘主‘)??
    • 第二种(继承Process,并覆盖__init__方法,再重写一个run方法)
      # 创建进程的第二种方式from multiprocessing import Process?import time?class MyProcess(Process): def __init__(self,name): super().__init__() self.name= name? def run(self): print(‘%s is running‘ % self.name) time.sleep(3) print(‘%s is over‘ % self.name)?if __name__ == ‘__main__‘: p = MyProcess(‘egon‘) p.start() print(‘主‘)
    • Process模块

      Process模块用来创建进程一般需要传入target目标函数,args函数的参数??强调:1. 需要使用关键字的方式来指定参数2. args指定的为传给target函数的位置参数,是一个元组形式,必须有逗号?参数介绍:1 group参数未使用,值始终为None2 target表示调用对象,即子进程要执行的任务3 args表示调用对象的位置参数元组,args=(1,2,‘egon‘,)4 kwargs表示调用对象的字典,kwargs={‘name‘:‘egon‘,‘age‘:18}5 name为子进程的名称??方法介绍:??1 p.start():启动进程,并调用该子进程中的p.run() 2 p.run():进程启动时运行的方法,正是它去调用target指定的函数,我们自定义类的类中一定要实现该方法 3 p.terminate():强制终止进程p,不会进行任何清理操作,如果p创建了子进程,该子进程就成了僵尸进程,使用该方法需要特别小心这种情况。如果p还保存了一个锁那么也将不会被释放,进而导致死锁4 p.is_alive():如果p仍然运行,返回True5 p.join([timeout]):主线程等待p终止(强调:是主线程处于等的状态,而p是处于运行的状态)。timeout是可选的超时时间,需要强调的是,p.join只能join住start开启的进程,而不能join住run开启的进程 ???属性名称:??1 p.daemon:默认值为False,如果设为True,代表p为后台运行的守护进程,当p的父进程终止时,p也随之终止,并且设定为True后,p不能创建自己的新进程,必须在p.start()之前设置2 p.name:进程的名称3 p.pid:进程的pid4 p.exitcode:进程在运行时为None、如果为–N,表示被信号N结束(了解即可)5 p.authkey:进程的身份验证键,默认是由os.urandom()随机生成的32字符的字符串。这个键的用途是为涉及网络连接的底层进程间通信提供安全性,这类连接只有在具有相同的身份验证键时才能成功(了解即可)?查看进程pid: os.getpid()??查看父进程pid:os.ppid()?

  • join方法
    join 保证所有子进程执行完,主进程才能工作,不然一直阻塞?from multiprocessing import Processimport time?def test(name,i): print(‘%s is running‘%name) time.sleep(i) print(‘%s is over‘%name)?if __name__ == ‘__main__‘: p_list = [] p = Process(target=test,args=(‘egon‘,1)) p1 = Process(target=test,args=(‘kevin‘,2)) p2 = Process(target=test,args=(‘jason‘,3)) start_time = time.time() p.start() # 仅仅是告诉操作系统帮你创建一个进程 至于这个进程什么时候创 操作系统随机决定 p1.start() p2.start() p2.join() p.join() p1.join()? # 主进程代码等待子进程运行结束 才继续运行 # p.join() # 主进程代码等待子进程运行结束 print(‘主‘) print(time.time() - start_time)???‘‘‘执行结果jason is runningegon is runningkevin is runningegon is overkevin is overjason is over主3.094853162765503?‘‘‘???
  • 进程间数据是隔离的
    ‘‘‘?本例子:父进程是说pycharm执行这个py文件就创建了一个进程py文件的代码中?通过Process模块创建了一个进程,?那么从关系上来讲pycharm执行而创建出的就是父进程,Process创建的就是子进程‘‘‘??from multiprocessing import Processimport time?money = 100?def test(): global money money = 99999999?if __name__ == ‘__main__‘: p = Process(target=test) p.start() p.join() print(money)# 执行结果:100??
  • 僵尸进程与孤儿进程
    • 父进程回收子进程资源的两种方式
      1.join方法2.父进程正常死亡所有进程都会步入僵尸进程?
    • 孤儿进程
      子进程没死 父进程意外死亡?针对linux会有儿童福利院(init) ?如果父进程意外死亡他所创建的子进程都会被福利院收养
  • 守护进程
    • 理解
      会随着主进程的结束而结束。主进程创建守护进程  其一:守护进程会在主进程代码执行结束后就终止  其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemonic processes are not allowed to have children注意:进程之间是互相独立的,主进程代码运行结束,守护进程随即终止
    • 代码示例
      from multiprocessing import Processimport time?def test(name): print(‘%s总管正常活着‘%name) time.sleep(3) print(‘%s总管正常死亡‘%name)?if __name__ == ‘__main__‘: p = Process(target=test,args=(‘egon‘,)) p.daemon = True# 将该进程设为守护进程 这句话必须放在start语句之前 否则报错 p.start() time.sleep(0.1) print(‘皇帝jason寿正终寝‘)
  • 互斥锁
    • 为什么有互斥锁
      当多个进程操作同一份数据的时候 会造成数据的错乱这个时候必须加锁处理?本质是:将并发变成串行虽然降低了效率但是提高了数据的安全?
    • 注意事项
      1. 锁不要轻易使用 容易造成死锁现象2. 只在处理数据的部分加锁 不要在全局加锁3. 锁必须在主进程中产生 交给子进程去使用?
    • 代码示例
      from multiprocessing import Process,Lockimport time, json# 查票def search(i): with open(‘data‘,‘r‘,encoding=‘utf-8‘) as f: data = f.read() t_d = json.loads(data) print(‘用户%s查询余票为:%s‘%(i,t_d.get(‘ticket‘)))?# 买票def buy(i): with open(‘data‘,‘r‘,encoding=‘utf-8‘) as f: data = f.read() t_d = json.loads(data) time.sleep(1) if t_d.get(‘ticket‘) > 0: # 票数减一 t_d[‘ticket‘] -= 1 # 更新票数 with open(‘data‘,‘w‘,encoding=‘utf-8‘) as f: json.dump(t_d,f) print(‘用户%s抢票成功‘%i) else: print(‘没票了‘)?def run(i,mutex): search(i) mutex.acquire() # 抢锁 只要有人抢到了锁 其他人必须等待该人释放锁 buy(i) mutex.release() # 释放锁?if __name__ == ‘__main__‘: mutex = Lock() # 生成了一把锁 for i in range(3): p = Process(target=run,args=(i,mutex)) p.start()?‘‘‘执行结果:用户0查询余票为:0用户2查询余票为:0用户1查询余票为:0没票了没票了没票了??‘‘‘??

原文地址:https://www.cnblogs.com/buzaiyicheng/p/11329417.html

时间: 2024-10-12 03:21:08

进程、join方法、守护进程、互斥锁的相关文章

python并发编程-进程理论-进程方法-守护进程-互斥锁-01

操作系统发展史(主要的几个阶段) 初始系统 1946年第一台计算机诞生,采用手工操作的方式(用穿孔卡片操作) 同一个房间同一时刻只能运行一个程序,效率极低(操作一两个小时,CPU一两秒可能就运算完了) 联机批处理系统 脱机批处理系统 多道程序系统 1.空间上的复用 ? 多个程序公用一套计算机硬件 2.时间上的复用 ? 切换+保存状态 ? 保存状态:保存当前的运行状态,下次接着该状态继续执行 ? 切换的两种情况 ? (1) 当一个程序遇到 I/O 操作(不需要使用CPU),操作系统会剥夺该程序的C

Linux环境编程之进程(七):守护进程

守护进程也是一种进程,它由如下特性: 1.生存期较长,在系统自举时启动,仅在系统关闭时终止. 2.没有控制终端,在后台运行. 系统中有很多守护进程,它们执行日常事务活动.如日志进程syslogd.web服务器httpd.邮件服务器sendmail和数据块服务器mysqld等.大多数守护进程都是以超级用户(用户ID为0)特权运行.没有一个守护进程具有控制终端,其终端设置为问号(?),终端前台进程组ID设置为-1.内核守护进程以无控制终端方式启动.用户层守护进程缺少控制终端可能是守护进程调用了set

(七) 一起学 Unix 环境高级编程(APUE) 之 进程关系 和 守护进程

. . . . . 目录 (一) 一起学 Unix 环境高级编程(APUE) 之 标准IO (二) 一起学 Unix 环境高级编程(APUE) 之 文件 IO (三) 一起学 Unix 环境高级编程(APUE) 之 文件和目录 (四) 一起学 Unix 环境高级编程(APUE) 之 系统数据文件和信息 (五) 一起学 Unix 环境高级编程(APUE) 之 进程环境 (六) 一起学 Unix 环境高级编程(APUE) 之 进程控制 (七) 一起学 Unix 环境高级编程(APUE) 之 进程关系

Linux系统开发7 进程关系,守护进程

[本文谢绝转载原文来自http://990487026.blog.51cto.com] <大纲> Linux系统开发7  进程关系守护进程 终端 网络终端 Linux PCB结构体信息 进程组 修改子进程.父进程的组ID 会话组 设置一个会话脱离控制终端 生成一个新的会话 守护进程 守护进程模板 获取当前系统时间  终端 在UNIX系统中用户通过终端登录系统后得到一个Shell进程这个终端成为Shell进 程的控制终端Controlling Terminal在讲进程时讲过控制终端是保存在PCB

python全栈脱产第34天------开启进程的两种方式、join方法、进程对象其他相关的属性和方法、僵尸进程、孤儿进程、守护进程、互斥锁

一.开启进程的两种方式 方式一: from multiprocessing import Processimport time def task(name): print('%s is running' %name) time.sleep(3) print('%s is done' %name) # 在windows系统上,开启子进程的操作必须放到if __name__ == '__main__'的子代码中if __name__ == '__main__': p=Process(target=t

36 线程 队列 守护线程 互斥锁 死锁 可重入锁 信号量

线程 线程是操作系统最小的运算调度单位,被包含在进程中,一个线程就是一个固定的 执行流程 线程和进程的关系 线程不能单独存在 必须存在于进程中, 进程是一个资源单位,其包含了运行程序所需的所有资源 线程才是真正的执行单位 没有线程,进程中的资源无法被利用起来,所以一个进程至少包含一个线程,称之为主线程 当我们启动一个程序时,操作系统就会自己为这个程序创建一个主线程 线程可以由程序后期开启 ,自己开启线程称之为子线程 为什么需要线程 目的只有一个就是提高效率 就像一个车间 如果产量跟不上 就再造一

9 并发编程-(线程)-守护线程&amp;互斥锁

一 .守护线程 无论是进程还是线程,都遵循:守护xxx会等待主xxx运行完毕后被销毁 需要强调的是:运行完毕并非终止运行 1.对主进程来说,运行完毕指的是主进程代码运行完毕 2.对主线程来说,运行完毕指的是主线程所在的进程内所有非守护线程统统运行完毕,主线程才算运行完毕 详细解释: 1.主进程在其代码结束后就已经算运行完毕了(守护进程在此时就被回收), 然后主进程会一直等非守护的子进程都运行完毕后回收子进程的资源(否则会产生僵尸进程),才会结束, 2.主线程在其他非守护线程运行完毕后才算运行完毕

Linux 进程(二):进程关系及其守护进程

进程关系 进程组 进程组是一个或多个进程的集合.通常,它们是在同一作业中结合起来的,同一进程组中的各进程接收来自同一终端的各种信号,每个进程组有一个唯一的进程组ID.每个进程组有一个组长进程,该组长进程的ID等于进程组ID.从进程组创建开始到最后一个进程离开为止的时间称为进程组的生命周期. #include <unistd.h> pid_t getpgrp(void); 返回值:调用进程的进程组ID int setpgid(pid_t pid, pid_t pgid); 返回值:成功,返回0:

将进程设置为守护进程

在正常条件下,我们将程序运行产生的信息打印到控制台实时显示,如果我们想讲一个程序以守护进程的方式进行运行,就需要改变信息的输出方向,将其导向到配置文件里设置的日志文件. 将一个进程转换为守护进程需要进行几个步骤: 1.fork一个新的进程,将父进程退出. 2.将0.1.2三个文件描述符重定向. 3.将1重定向到日志文件. void daemonize() { if(fork() != 0) //将父进程退出 exit(0); setsid(); //设置新的会话 LOG(LOG_LEVEL_IN

Linux进程实践(5) --守护进程

概述 守护进程是在需要在后台长期运行不受终端控制的进程,通常情况下守护进程在系统启动时自动运行,在服务器关闭的时候自动关闭:守护进程的名称通常以d结尾,比如sshd.xinetd.crond.atd等. 守护进程编程规则 调用umask将文件模式创建屏蔽字设置为一个已知值(通常是0) 调用fork(),创建新进程,它会是将来的守护进程 然后使父进程exit,保证子进程不是进程组组长 调用setsid创建新的会话 会话:是一个或者多个进程组的集合,通常一个会话开始与用户登录,终止于用户退出.在此期