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()

Python之路PythonThread,第三篇,进程3的更多相关文章

  1. Python之路(第四十篇)进程池

    一.进程池 进程池也是通过事先划分一块系统资源区域,这组资源区域在服务器启动时就已经创建和初始化,用户如果想创建新的进程,可以直接取得资源,从而避免了动态分配资源(这是很耗时的). 线程池内子进程的数 ...

  2. Python之路PythonThread,第二篇,进程2

    python3   进程2 僵尸进程处理方法: 3,创建二级子进程处理 4,在父进程中使用信号处理的方法忽略子进程发来的信号: signal(SIGCHLD,DIG,IGN) # 创建二级子进场解决僵 ...

  3. Python之路PythonThread,第一篇,进程1

    python3 进程1 多任务编程: 可以有效的利用计算机资源,同时执行多个任务, 进程:进程就是程序在计算机中一次执行的结果: 进程和程序的区别: 程序是一个静态文件的描述,不占用计算机的系统资源: ...

  4. Python之路【第三篇补充】:Python基础(三)

    参考老师:http://www.cnblogs.com/wupeiqi lambda表达式 学习条件运算时,对于简单的 if else 语句,可以使用三元运算来表示,即: # 普通条件语句 if 1 ...

  5. Python之路【第三篇】:Python基础(二)

    函数的理解 面向过程:根据业务逻辑从上到下写垒代码 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 函数作用是你的程序有良好的扩展性.复用性. 同样的功能要是用3次以上的话就建议 ...

  6. 【Python之路】第三篇--Python基本数据类型

    运算符 1.算数运算: # 在py2的 取整除运算中 9//2 = 4.0 # 引入 from __future__ import division 9//2 = 4.5 # py3中不需要! 2.比 ...

  7. Python之路【第三篇】:文件操作

    一.文件操作步骤 打开文件,得到文件句柄并赋值给一个变量 通过句柄对文件进行操作 关闭文件 歌名:<大火> 演唱:李佳薇 作词:姚若龙 作曲:马奕强 歌词: 有座巨大的停了的时钟 倾倒在赶 ...

  8. Python之路【第三篇】python基础 之基本数据类型 补充

    字符串格式化 Python的字符串格式化有两种方式: 百分号方式.format方式 百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存.[PEP-310 ...

  9. Python之路【第三篇】:模块

    定义: 包:包含__init__.py文件.模块(也是.py文件) 当包被其它模块调用时,首先会执行该包下的__init__文件 包含有模块,包可以有多级 模块的导入: import from...i ...

  10. Python之路【第三篇】编码

    Python代码——>字节码——>机器码——>计算机 Windows: cmd ==> python 文件路径 cmd ==>python >> 输入命令 L ...

随机推荐

  1. Javascript 将 HTML 页面生成 PDF 并下载

    最近碰到个需求,需要把当前页面生成 pdf,并下载.弄了几天,自己整理整理,记录下来,我觉得应该会有人需要 :) html2canvas 简介 我们可以直接在浏览器端使用html2canvas,对整个 ...

  2. Vue 项目骨架屏注入与实践

    作为与用户联系最为密切的前端开发者,用户体验是最值得关注的问题.关于页面loading状态的展示,主流的主要有loading图和进度条两种.除此之外,越来越多的APP采用了“骨架屏”的方式去展示未加载 ...

  3. 3.Liunx网络管理命令

    大纲: 1.网络信息:hostname.netstat.ifconfig ,route 2.网络配置:netconfig 3.网络测试:ping

  4. Windows下定时任务

    windows计划任务 1.写一个PHP程序,命名为test.php,内容如下所示: <? $fp = fopen("test.txt", "a+"); ...

  5. nginx升级教程

    1.说明 CVE-2016-4450,可通过构造特定数据包,可引发nginx引用空指针,导致nginx出错从而造成拒绝服务攻击. 影响1.3.9到1.11.0的所有版本,进行修复的1.10.1和1.1 ...

  6. Kali配置教程

    1.配置软件源 所有操作没有说明,都是以root身份执行. 打开一个终端执行: cat >> /etc/apt/sources.list <<EOF deb http://mi ...

  7. Spring FactoryBean应用

    Spring 中有两种类型的Bean,一种是普通Bean,另一种是工厂Bean 即 FactoryBean.FactoryBean跟普通Bean不同,其返回的对象不是指定类的一个实例,而是该Facto ...

  8. OGG文件获取创建日期

    转载:http://blog.sina.com.cn/s/blog_b0ed98070102v1tr.html 搜索关键字: OGG文件的数据结构以及读取其注释信息的代码 实例说明: "DA ...

  9. Java 求两个数百分比%

    int num1 = 500; int num2 = 312; // 创建一个数值格式化对象 NumberFormat numberFormat = NumberFormat.getInstance( ...

  10. react router @4 和 vue路由 详解(四)vue如何在路由里面定义一个子路由

    完整版:https://www.cnblogs.com/yangyangxxb/p/10066650.html 6.vue如何在路由里面定义一个子路由? 给父路由加一个 children:[] 参考我 ...