python3 进程3

管道

在内存中开辟一个管道空间,对多个进程可见。 在通信形式上形成一种约束;

linux 文件类型

b    c      d         -                l               s                      p

目录   普通文件  链接        套接字           管道

multiprocessing    -----> Pipe函数

Pipe(duplex)

功能:创建一个管道

参数:duplex 默认为True 表示管道为双向管道(全双工);

如果设置为False, 则表示管道为单向管道;

返回值:返回两个管道流对象,分配表示管道的两端;

如果参数为True(默认),两个对象均可发送接收;

如果为False时,则第一个对象只能接收,第二个对象只能发送;

说明:1, 向管道发送数据使用send()函数,从管道接收数据使用recv() 函数;

2,recv() 函数为阻塞函数,当管道中数据为空时会阻塞;

3,一次recv() ,只能接收一次send()的内容;

4,send() 可以发送字符串数字列表等多种类型数据;

 from multiprocessing import Process,Pipe
import os,time #创建管道对象
#当参数为False的时候child只能recv parent只能send
# child_conn,parent_conn = Pipe(False) child_conn,parent_conn = Pipe() #子进程函数
def fun(name):
time.sleep(1)
#发送一个字符串到管道
child_conn.send('hello' + str(name))
print(os.getppid(),"----",os.getpid()) jobs = []
#创建5个子进程
for i in range(5):
p = Process(target = fun,args = (i,))
jobs.append(p)
p.start() for i in range(5):
data = parent_conn.recv()
print(data) for i in jobs:
i.join()

消息队列:

multiprocessing ---> Queue

在内存中开辟一个队列模型,用来存放消息,任何拥有队列队形的进程都可以进行消息的存放和取出;

Queue(maxsize = 0)

功能:创建一个消息队列对象;

参数:maxsize 默认为0 表示消息队列可以存放的消息由系统自动分配的空间而定;

> 0 的正整数   表示队列中最多存放多少条消息;

返回值:消息队列对象;

q.put()

1,向消息队列中存放一条消息,当消息队列满的时候,会阻塞;

2, 存放的消息类型可以是数字,列表,字符串等;

q.full()

判断队列是否为满, 如果满则返回True,否则返回False;

q.qsize()

查看当前队列中消息数量;

q.get()

获取消息,每次获取一条; 当消息队列为空时,则为阻塞;

说明: put() 、get() 中block参数和timeout参数

block默认为True,表示两个函数都是阻塞函数;

如果设置为False, 则表示不阻塞;

timeout  当block设置为True时,表示超时等待时间;

 from multiprocessing import Queue 

 #创建消息队列对象
q = Queue(3) i = 0
# 存放消息 
while True:
#判断队列是否满了
if q.full():
print("queue is full")
break
q.put("hello" + str(i))
i += 1 print("当前队列有%d条消息"%q.qsize()) for i in range(q.qsize()):
print("获取消息%s"%q.get()) print("is empty?",q.empty()) print(q.get(True,3)) print("process over")
 from multiprocessing import Process,Queue
import time q = Queue() def fun(name):
time.sleep(1)
q.put("hello" + str(name)) jobs = [] for i in range(10):
p = Process(target = fun,args =(i,))
jobs.append(p)
p.start() for i in jobs:
i.join() while not q.empty():
print(q.get())

共享内存

在内存中开辟一段内存空间存储数据,每次存储的内容会覆盖上次的内容;由于没有对内存进行格式化修饰,所以存储的速度快效率高;

from multiprocessing import Value,Array

obj = Value(ctype,  obj)

功能:开辟共享内存

参数:ctype 要转变的c的类型

obj    要写入共享内存的初始值

obj.value 属性为获取共享内存中的值;

 from multiprocessing import Value,Process
import time
import random def deposite(money):
for i in range(100):
time.sleep(0.03)
money.value += random.randint(1,200) def withdraw(money):
for i in range(100):
time.sleep(0.02)
money.value -= random.randint(1,150) money = Value('i',2000) d = Process(target = deposite,args = (money,))
w = Process(target = withdraw,args = (money,)) d.start()
w.start() d.join()
w.join() print(money.value)

obj =Array(ctype, obj)

功能: 开辟一个共享内存空间;

参数: 要装的c的类型;

obj 放入共享内存中的数据, 是一个列表,要求列表重点数据为相同类型的数据;

如果obj传入一个正数,则表示在共享内存中开辟一个多大的空间,空间中可以存放的数值类型由ctype确定;

返回值: 返回一个可迭代对象通过for循环取值,可以进行修改;

from multiprocessing import Process,Array
import time
import ctypes def fun(shm):
for i in shm:
print(i)
# shm[0] = 'A' # shm = Array('i',[1,2,3,4,5])
shm = Array(ctypes.c_char,6) p = Process(target = fun,args = (shm,))
p.start()
p.join() for i in shm:
print(i)

############

管道                            消息队列                            共享内存

开辟空间 :               内存中                         内存中                                  内存中

读写方式:            可双向/单向              先进先出,按照个数存储          操作内存

效率 :                          一般                             一般                                      较快

是否需要同步互斥 :  不需要                           不需要                                  需要

#############

信号:

kill    -l   查看系统信号

kill  -signame   PID  给进程号PID的进程发送signame信号;

信号:  信号名称     含义       默认处理方式

名称:系统定义

含义:系统定义

处理方式:采用默认方式处理(系统定义     终止   暂停   忽略)

忽略信号(当信号没发生过)

采用自定义方式处理

 import signal
import time signal.alarm(5)
#采用默认方式
# signal.signal(signal.SIGINT,signal.SIG_DFL) #忽略该信号
signal.signal(signal.SIGINT,signal.SIG_IGN)
signal.signal(signal.SIGALRM,signal.SIG_IGN) while True:
time.sleep(2)
print("你按ctrl + c啊")
 from signal import *
import os,time #信号处理函数,有固定参数格式
def handler(sig,frame):
if sig == SIGALRM:
print("收到了时钟信号")
elif sig == SIGINT:
print("收到了SIGINE就不结束") alarm(7) #通过函数 处理信号
signal(SIGALRM,handler)
signal(SIGINT,handler) while True:
print("waiting for signal")
time.sleep(2)

如何发送信号:

os.kill(pid,   sig)

功能:向一个进程发送一个信号

参数:pid  指要发送进程的PID号

sig  指要发送的信号

signal.alarm(sec)

功能:给自己发送一个时钟信号(SIGALRM)

参数:esc  秒数 表示在相应的秒数后发送时钟信号

说明:1,信号是一种异步的进程间通信方式

2,alarm函数在一个进程中如果使用多次,则后面的时钟时间会覆盖前面的时间。

信号的处理:

signal.pause()   阻塞等待一个信号的发生;

signal.signal(signum, hander)

功能: 处理信号

参数:signum  表示可以处理的信号

hander 信号处理的方法:

1, 默认处理方式:SIG_DFL

2,忽略信号:SIG_IGN

       3,自定义的方式: function

说明:1, signal 函数也是一个异步处理信号函数;

2, SIGSTOP 和SIKILL不能被signal函数处理;

####

僵尸进程的信号处理方案  父进程中

signal(SIGCHLD, SIG_IGN)

###

同步和互斥

临界资源:对多个进程或者线程都可见的资源,容易产生争夺,我们将这类资源叫做临界资源;

临界区:对临界资源进行操作的代码区域称之为临界区;

解决资源争夺方法: 同步   或者   互斥

同步: 同步是一种合作关系,为完成某种任务而建立的多个进程或者线程之间的协调调用,持续等待,传递消息告知资源占用情况;

互斥: 互斥是一种制约关系,当一个进程或者线程进入到临界区后会进行枷锁操作,此时其他进程或者线程无法进入到临界区,只有

当该进程或线程使用后进程解锁,其他人才可以使用,这种技术往往是通过阻塞完成;

Event  事件

Event() ----> 事件对象e

e.wait() : 产生一种阻塞 ,知道e被set之后才结束阻塞
e.set() : 将e set操作 wait不再阻塞
e.is_set() : 判断e是否是被设置的状态
e.clear() : 将e 变成 没有被设置的状态

 from multiprocessing import Event 

 #生成事件对象 
e = Event() #检测事件对象,如果被设置则返回True否则返回false
print(e.is_set()) #设置事件对象
e.set() #提供事件的阻塞
e.wait() print("wait.....")
#清除对事件的设置
e.clear() e.wait() print("wait...wait.....")
 from  multiprocessing import Process,Event
import time def wait_event():
print('process1要等主进程操作完我才能操作')
e.wait()
print('终于操作完了,该我了',e.is_set()) def wait_event_timeout():
print('process2要等主进程操作完我才能操作')
e.wait(2)
print('我等不了了,干别的去',e.is_set()) e = Event() p1 = Process(name = 'block',\
target = wait_event)
p1.start()
p2 = Process(name = 'non-block',\
target = wait_event_timeout)
p2.start() print("假设主进程在忙碌的操作临界区")
time.sleep(3)
e.set()
print("主进程开放临界区")

练习:

1. 创建父子进程,分别表示司机和售票员

2. 当售票员捕捉到 SIGINT信号时 给司机发送SIGUSR1信号,
司机打印“老司机开车了”

当售票员捕捉到 SIGQUIT信号时 给司机发送SIGUSR2信号,
司机打印“系好安全带,小心甩出去”

当司机捕捉到 SIGTSTP信号时 给售票员发送SIGUSR1信号,
售票员打印“到站了,下车吧”

3. 到站后 售票员先下车(子进程先退出),然后司机下车

 from signal import *
from multiprocessing import Process
import os
import time def saler_handler(sig,frame):
if sig == SIGINT:
os.kill(os.getppid(),SIGUSR1)
elif sig == SIGQUIT:
os.kill(os.getppid(),SIGUSR2)
elif sig == SIGUSR1:
print("python学完了,出去试试吧")
os._exit(0) def driver_handler(sig,frame):
if sig == SIGUSR1:
print("老司机带你学python")
elif sig == SIGUSR2:
print("python 知识多,积累最重要")
elif sig == SIGTSTP:
os.kill(p.pid,SIGUSR1) def saler():
signal(SIGINT,saler_handler)
signal(SIGQUIT,saler_handler)
signal(SIGUSR1,saler_handler)
signal(SIGTSTP,SIG_IGN)
while True:
time.sleep(2)
print("开着python去远方") p = Process(name = 'zhangjie',\
target = saler)
p.start() # 父进程处理信号部分
signal(SIGUSR1,driver_handler)
signal(SIGUSR2,driver_handler)
signal(SIGTSTP,driver_handler)
signal(SIGINT,SIG_IGN)
signal(SIGQUIT,SIG_IGN) p.join()

最新文章

  1. Maven联网问题
  2. 素数环问题[XDU1010]
  3. extend简单用法
  4. xml、txt、config的一些基本用法
  5. 染色[SDOI2011]
  6. 从零开始学安全(三十六)●利用python 爆破form表单
  7. SQL Server 2016新特性:Live Query Statistics
  8. awk计算最大值,最小值,平均值的脚本
  9. 旋转数组的最小数字(python)
  10. 《Linux内核分析》 第四节 扒开系统调用的三层皮(上)
  11. HTML5学习笔记(四):H5中表单新增元素及改良
  12. CSS中的各种width(宽度)
  13. 第二十一章 springboot + 定时任务
  14. GIS(一)——在js版搜索地图上加入Marker标记
  15. cake build使用:
  16. 20145104张家明 《Java程序设计》第一周学习总结
  17. 20169214 2016-2017-2 《网络攻防实践》第十一周实验 SQL注入
  18. ElasticSearch 从2.2升级到6.2.4所碰到的问题汇总
  19. 基于CentOS与VmwareStation10搭建Oracle11G RAC 64集群环境:4.安装Oracle RAC FAQ-4.7.Oracle 11G R2 RAC修改public网络IP
  20. 170227、java分布式系统开关功能设计(服务升降级)

热门文章

  1. WebAPi获取请求头中对应键值
  2. mysql索引简单分析
  3. angular 常用插件集合
  4. javascript 多个onclick function 取对应值
  5. python vue 项目
  6. Saiku的下载与安装(一)
  7. Linux如何从零开始搭建rsync服务器(centOS6)
  8. Python发送四种格式的post请求的代码样例
  9. 网口扫盲二:Mac与Phy组成原理的简单分析(转)
  10. JavaWeb基础-Session和Cookie