操做系统的发展html
详情见:操做系统的发展史python
从理论角度看,是对正在运行的程序过程的抽象;
从实现角度看,是一种数据结构,目的在于清晰地刻画动态系统的内在规律,有效管理和调度进入计算机系统主存储器运行的程序。
2,特征:linux
所谓同步就是一个任务的完成须要依赖另一个任务时,只有等待被依赖的任务完成后,依赖的任务才能算完成,这是一种可靠的任务序列
。要么成功都成功,失败都失败,两个任务的状态能够保持一致。nginx
所谓异步是不须要等待被依赖的任务完成,只是通知被依赖的任务要完成什么工做,依赖的任务也当即执行,只要本身完成了整个任务就算完成了
。至于被依赖的任务最终是否真正完成,依赖它的任务没法肯定,因此它是不可靠的任务序列
。web
8,阻塞与非阻塞:算法
阻塞和非阻塞这两个概念与程序(线程)等待消息通知(无所谓同步或者异步)时的状态有关。也就是说阻塞与非阻塞主要是程序(线程)等待消息通知时的
shell
同步阻塞形式windows
异步阻塞形式安全
同步非阻塞形式网络
异步非阻塞形式
9,建立进程
但凡是硬件,都须要有操做系统去管理,只要有操做系统,就有进程的概念,就须要有建立进程的方式,一些操做系统只为一个应用程序设计,好比微波炉中的控制器,一旦启动微波炉,全部的进程都已经存在。
而对于通用系统(跑不少应用程序),须要有系统运行过程当中建立或撤销进程的能力,主要分为4中形式建立新的进程:
1. 系统初始化(查看进程linux中用ps命令,windows中用任务管理器,前台进程负责与用户交互,后台运行的进程与用户无关,运行在后台而且只在须要时才唤醒的进程,称为守护进程,如电子邮件、web页面、新闻、打印)
2. 一个进程在运行过程当中开启了子进程(如nginx开启多进程,os.fork,subprocess.Popen等)
3. 用户的交互式请求,而建立一个新进程(如用户双击暴风影音)
4. 一个批处理做业的初始化(只在大型机的批处理系统中应用)
不管哪种,新进程的建立都是由一个已经存在的进程执行了一个用于建立进程的系统调用而建立的。
1. 在UNIX中该系统调用是:fork,fork会建立一个与父进程如出一辙的副本,两者有相同的存储映像、一样的环境字符串和一样的打开文件(在shell解释器进程中,执行一个命令就会建立一个子进程) 2. 在windows中该系统调用是:CreateProcess,CreateProcess既处理进程的建立,也负责把正确的程序装入新进程。 关于建立子进程,UNIX和windows 1.相同的是:进程建立后,父进程和子进程有各自不一样的地址空间(多道技术要求物理层面实现进程之间内存的隔离),任何一个进程的在其地址空间中的修改都不会影响到另一个进程。 2.不一样的是:在UNIX中,子进程的初始地址空间是父进程的一个副本,提示:子进程和父进程是能够有只读的共享内存区的。可是对于windows系统来讲,从一开始父进程与子进程的地址空间就是不一样的。
10,进程的结束
1. 正常退出(自愿,如用户点击交互式页面的叉号,或程序执行完毕调用发起系统调用正常退出,在linux中用exit,在windows中用ExitProcess)
2. 出错退出(自愿,python a.py中a.py不存在)
3. 严重错误(非自愿,执行非法指令,如引用不存在的内存,1/0等,能够捕捉异常,try...except...)
4. 被其余进程杀死(非自愿,如kill -9)
在python程序中的进程操做
1,查看进程的 PID 号
每个进程都有一个本身的 PID 号,能够在任务管理器,详细信息中找到这个进程。
import os
import time
print(os.getpid()) # 获取当前运行的python程序的进程id process id
print(os.getppid()) # parent process id 获取当前进程的父id
time.sleep(100)
2, python当中建立进程来替我作事情
multiprocess 模块:multiple [ˈmʌltɪpl] adj. 数量多的;多种多样的 n. 倍数
process [prəˈses] n. 过程;进程;
仔细说来,multiprocess不是一个模块而是python中一个操做、管理进程的包。 在这个包中几乎包含了和进程有关的全部子模块。因为提供的子模块很是多,为了方便归类记忆,将这部分大体分为四个部分:建立进程部分,进程同步部分,进程池部分,进程之间数据共享。
3,其中的 process 模块介绍
process 模块是一个建立进程的模块,借助这个模块,就能够完成进程的建立
建立的是子进程。
3.1,参数介绍:
Process([group [, target [, name [, args [, kwargs]]]]]),由该类实例化获得的对象,表示一个子进程中的任务(还没有启动)
强调:
1, 须要使用关键字的方式来指定参数
2.,args指定的为传给target函数的位置参数,是一个元组形式,必须有逗号
参数介绍:
1, group参数未使用,值始终为None
2, target表示调用对象,即子进程要执行的任务
3, args表示调用对象的位置参数元组,args=(1,2,'egon',)
4, kwargs表示调用对象的字典,kwargs={'name':'egon','age':18}
5, name为子进程的名称
3.2,方法介绍:
1 ,p.start():启动进程,并调用该子进程中的p.run()
2, p.run():进程启动时运行的方法,正是它去调用target指定的函数,咱们自定义类的类中必定要实现该方法
3, p.terminate():强制终止进程p,不会进行任何清理操做,若是p建立了子进程,该子进程就成了僵尸进程,使用该方法须要特别当心这种状况。若是p还保存了一个锁那么也将不会被释放,进而致使死锁
4, p.is_alive():若是p仍然运行,返回True
5, p.join([timeout]):主线程等待p终止(强调:是主线程处于等的状态,而p是处于运行的状态)。timeout是可选的超时时间,须要强调的是,p.join只能join住start开启的进程,而不能join住run开启的进程
3.3,属性介绍:
1 ,p.daemon:默认值为False,若是设为True,表明p为后台运行的守护进程,当p的父进程终止时,p也随之终止,而且设定为True后,p不能建立本身的新进程,必须在p.start()以前设置
2 ,p.name:进程的名称
3 ,p.pid:进程的pid
4 ,p.exitcode:进程在运行时为None、若是为–N,表示被信号N结束(了解便可)
5, p.authkey:进程的身份验证键,默认是由os.urandom()随机生成的32字符的字符串。这个键的用途是为涉及网络链接的底层进程间通讯提供安全性,这类链接只有在具备相同的身份验证键时才能成功(了解便可)
3.4,在windows中使用process模块的注意事项
在Windows操做系统中因为没有fork(linux操做系统中建立进程的机制),在建立子进程的时候会自动 import 启动它的这个文件,而在 import 的时候又执行了整个文件。所以若是将process()直接写在文件中就会无限递归建立子进程报错。因此必须把建立子进程的部分使用if __name__ ==‘__main__’ 判断保护起来,import 的时候 ,就不会递归运行了。
4,使用 process 模块建立子进程
4.1 ,建立第一个子进程
from multiprocessing import Process
def func():
print(123)
print('我是子进程')
if __name__ == '__main__':
p = Process(target=func ) # 建立一个进程对象
p.start() # 直到执行start才有了进程
print('执行主进程的内容了')
# windows操做系统中 建立进程的语句必定要放在if __name__ == '__main__':条件语句下面
# 由于windows操做系统在建立子进程的时候会将文件整个重新执行,放在外面就会,不断的建立子进程,成递归。
4.2,验证并非一个进程
import os
from multiprocessing import Process
def func():
print('子进程',os.getpid())
print(123)
if __name__ == '__main__':
p = Process(target=func ) # 建立一个进程对象
print('主进程',os.getpid())
p.start()
print('主进程',os.getpid())
# 结果
主进程 4552
主进程 4552
子进程 6024
4.3,为何不是打印 主,子,主?
在执行p.start()时,只是告诉操做系统我要建立进程,并不等待结果。两个进程是异步的。
5,这是一个同步的进程
from multiprocessing import Process
def func():
print(123)
if __name__ == '__main__':
func()
6,异步阻塞
两个进程是异步的
import os import time from multiprocessing import Process def func(): print('子进程',os.getpid()) print(123) if __name__ == '__main__': p = Process(target=func ) # 建立一个进程对象 print('主进程',os.getpid()) p.start() # 子进程执行 time.sleep(10) # 主程序发生阻塞 print('取完钱了')
# 主进程阻塞,不影响子进程的执行
7,同步阻塞
import time
def func():
print(123)
if __name__ == '__main__':
time.sleep(10) # 发生阻塞 ,等待结果
func()
print('取完钱了')
8,传参,执行顺序
import os
import time
from multiprocessing import Process
def func(money):
time.sleep(3)
print('取钱 :%d'%money)
if __name__ == '__main__':
p = Process(target=func,args=(1,) ) # 能够给子进程传参,但必须传的是一个元组
p.start() #只传一个值时后面也要跟一个逗号。
print('取完钱了')
# 异步进程,虽然子进程并无结束(没有取完钱)可是主进程已经向后执行(打印取完钱了)
# 虽然是异步进程,两进程的执行互不干扰,可是若是子进程没有执行完,即使主进程已经执行完,主进程也不会结束。只有子进程执行完才会结束主进程。
9,解决上面的问题 join方法
import os
import time
from multiprocessing import Process
def func(money):
time.sleep(3)
print('取钱 :%d'%money)
if __name__ == '__main__':
p = Process(target=func,args=(1,) )
p.start()
p.join() # p.join 就是主进程会阻塞在join的位置,等待p进程结束
print('取完钱了')
# 可是,这样又将程序阻塞,变成相似于同步
10,开启多个子线程 和 join 的使用
import os
from multiprocessing import Process
def func():
print('%d :子进程%d干的事儿,父进程:%d'%(i,os.getpid(),os.getppid()))
if __name__ == '__main__':
p = Process(target=func)
p1 = Process(target=func)
p2 = Process(target=func)
p.start()
p1.start()
p2.start()
# p.join() # 此处加上这一句,意味着,只有p子进程结束才能执行后面的。但无论其余子进程。
print('------主进程------')
11,join 的使用
import os
import time
from multiprocessing import Process
def func(i):
time.sleep(1)
print('%d :子进程%d干的事儿,父进程:%d'%(i,os.getpid(),os.getppid()))
11.1,
if __name__ == '__main__':
# 100
for i in range(10):
p = Process(target=func,args=(i,))
p.start() # 建立的子进程,执行的顺序是无序的
p.join() # 只会管最后一个建立的子进程,其余的而无论。
# 后面的程序,会在最后一个建立的子进程结束后才执行
# join若是放在for里面,就会是建立一个子程序,而且执行完以后才在建立新的子程序。
print('------主进程------')
11.2,让最后一句话在全部子进程执行完后在打印。
if __name__ == '__main__':
# 100
p_lst = []
for i in range(10):
p = Process(target=func,args=(i,))
p.start()
p_lst.append(p)
for p in p_lst:
p.join()
print('------主进程------')
12,另外一种开启进程的方式
import os
from multiprocessing import Process
class MyProcess(Process):
def run(self):
print('子进程:%d'%os.getpid())
self.walk() # --->在子进程中调用
def walk(self): # 自定义的 能够不定义
print('子进程:%d' % os.getpid())
if __name__ == '__main__':
p = MyProcess()
p.start() # ---> # start会自动调用run方法
# p.walk() # ---> 在主进程中调用
print('主进程 :',os.getpid())
# 必须建立一个类 必须继承Process类
# 必须实现一个run方法
12.1,传参形式
import os
from multiprocessing import Process
class MyProcess(Process):
def __init__(self,arg1,arg2): # 传参
super().__init__()
self.arg1 = arg1
self.arg2 = arg2
def run(self):
print('子进程:%d,%s,%s'%(os.getpid(),self.arg1,self.arg2))
self.walk() # --->在子进程中调用
def walk(self): # 自定义的 能够不定义
print('子进程:%d' % os.getpid())
if __name__ == '__main__':
p = MyProcess(1,2)
p.start() # ---> run方法
# p.walk() # ---> 在主进程中调用
print('主进程 :',os.getpid())
13, 数据隔离
# 进程与进程之间的数据是隔离的,不共享的
from multiprocessing import Process
n = 100
def func():
global n
n = n - 1
print(n)
if __name__ == '__main__':
for i in range(10):
p = Process(target=func)
p.start()
p.join()
print('主进程 :',n)
14, 进程操做实例
import socket from multiprocessing import Process def talk(conn): conn.send(b'connected') ret = conn.recv(1024) print(ret) if __name__ == '__main__': sk = socket.socket() sk.bind(('127.0.0.1', 8080)) sk.listen() while True: conn,addr = sk.accept() p = Process(target=talk,args=(conn,)) p.start() conn.close() sk.close()
import socket sk = socket.socket() sk.connect(('127.0.0.1',8080)) ret = sk.recv(1024) print(ret) msg = input('>>>') sk.send(msg.encode('utf-8')) sk.close()