admin 管理员组文章数量: 1087649
python的信号量机制
- 信号通信
一个进程向另一个进程发送一个信号来传递某种信息,接收者根据接收到的信号进行相应的行为终端命令:
kill -l 查看系统信号
kill -sig PID 向一个进程发送信号信号介绍:
信号名称 信号含义 默认处理方法
SIGHUP 连接断开
SIGINT CTRL-C
SIGQUIT CTRL-\
SIGTSTP CTRL-Z
SIGKILL 终止一个进程
SIGSTOP 暂停一个进程
SIGALRM 时钟信号
SIGCHID 子进程状态改变时给父进程发出、
- python 发送信号
signal、os模块os.kill(pid,sig)功能:发送信号参数: pid 目标进程 signal.alarm(sec)功能:向自身发送时钟信号 --> SIGALRM参数:sec 时钟时间
* 进程中只能有一个时钟,第二个会覆盖第一个时间同步执行:按照顺序逐句执行,一步完成再做下一步
异步执行:再执行过程中利用内核记录延迟发生或者准备处理的事件,这样不影响应用层的持续执行,当事件发生时再由内核告知应用层处理* 信号是唯一的异步通信方法signal.pause()功能:阻塞等待接收一个信号signal.signal(signum,handler)功能:处理信号参数:signum 要处理的信号handler 信号的处理方法:SIG_DFL 表示使用默认的方法处理SIG_IGN 表示忽略这个信号func 传入一个函数,表示用指定函数处理函数格式要求:def func(sig,frame)sig: 捕获到的信号frame: 信号对象
- 信号处理函数演示
from signal import *
import time#信号处理函数
def handler(sig,frame):if sig == SIGALRM:print('接受到时钟信号')elif sig == SIGINT:print('接受到CTRL-C')#def CTRL_C(sig,frame):
# print('接收到CTRL-C')alarm(5)signal(SIGALRM,handler)
#signal(SIGINT,CTRL_C) 使用CTRL_C函数处理信号
signal(SIGINT,handler)while True:time.sleep(2)print('Wating for a signal')
- 信号量
原理:给定一个数量,对多个进程可见,且多个进程都可以操作。进程通过对数量多少的判断执行各自的行为。(生产者/消费者)multiprocessing --> Semaphore()sem = Semaphore(num)功能:创建信号量参数:信号量初始值返回:信号量对象sem.get_value() 获取信号量值
sem.acquire() 将信号量减1 当信号量为0时会阻塞
sem.release() 将信号量加1
- 信号量的简单实现
#演示信号量的创建和方法
from multiprocessing import Semaphore,Process
from time import sleep
import os#创建信号量
sem = Semaphore(3)def fun():print('进程{}等待信号量'.format(os.getpid()))#消耗一个信号量sem.acquire() # 为0则阻塞print('进程{}消耗一个信号量'.format(os.getpid()))sleep(3)sem.release()print('进程{}添加一个信号量'.format(os.getpid()))jobs = []
for i in range(4):p = Process(target = fun)jobs.append(p)p.start()for i in jobs:i.join()print(sem.get_value())
- 进程的同步和互斥
临界资源:多个进程后者线程都能够操作的共享资源
临界区:操作临界资源的代码段同步:同步是一种合作关系,为完成某个任务,多进程或者多线程之间形成一种协调,按照约定或条件执行操作临界资源。互斥:互斥是一种制约关系,当一个进程或者线程使用临界资源时进行上锁处理,当另一个进程使用时会阻塞等待,直到解锁后才能继续使用。multiprocessing --> Event创建事件对象
e = Event()设置事件阻塞
e.wait([timeout])事件设置 当事件被设置后e.wait()不再阻塞
e.set()清除设置 当事件设置被clear后 e.wait又会阻塞
e.clear()事件状态判断
e.is_set()
- 通过event事件实现父子进程分别读取文件的前后部分
#使用父子进程分别将文件的前后两半部分读取到一个文件中
from multiprocessing import Process,Event
import os#获取读文件的大小
size = os.path.getsize('file')def son_process():print('子进程等待进入临界区')e.wait()fr = open('file','r')fw = open('file2','a') # 以追加方式打开文件n = size//2fr.seek(n,0) # 将游标设置到读文件的一半#读取后半部分文件while True:if n < 1024:data = fr.read(n)fw.write(data)breakdata = fr.read(1024)fw.write(data)n -= 1024fr.close()fw.close()print('子进程释放临界区')e = Event()
p1 = Process(target = son_process)
p1.start()#父进程读取文件的前半部分
fr = open('file','r')
fw = open('file2','w')n = size // 2
while True:if n < 1024:data = fr.read(n)fw.write(data)breakdata = fr.read(1024)fw.write(data)n -= 1024fw.close()
fr.close()
e.set()
p1.join()
- Lock锁
创建对象
lock = Lock()lock.acquire() 上锁,如果锁已经是上锁状态调用此函数会阻塞
lock.release() 解锁with lock: 上锁............解锁
- 通过上锁互斥使用终端输出
#演示锁互斥使用终端输出
from multiprocessing import Process,Lock
import sys#两个进程都要进行锁的约束
def writer1():lock.acquire()for i in range(20):sys.stdout.write('Writer1想先向终端写入\n')lock.release()def writer2():with lock:for i in range(20):sys.stdout.write('Writer2想先向终端写入\n')lock = Lock()
w1 = Process(target = writer1)
w2 = Process(target = writer2)w1.start()
w2.start()w1.join()
w2.join()
- 通过signal发送信号完成任务(linux下)
题目:司机和售票员的故事:× 创建父子进程分别代表司机和售票员× 当售票员收到SIGINT信号,给司机发送SIGUSR1信号此时司机打印'老司机发车了'× 当售票员收到SIGQUIT信号,给司机发送SIGUSR2信号此时司机打印'车速有点快,系好安全带'× 当司机捕捉到SIGTSTP信号,给售票员发送SIGUSR1,售票员打印'到站了,请下车'× 到站后,售票员先下车,司机下车(子进程先退出)说明:SIGINT SIGQUIT SIGTSTP从键盘发出
- 代码:
# -*- coding:UTF-8 -*-
from multiprocessing import Process
import os
from signal import *
from time import sleepdef saler_handler(sig,frame):if sig == SIGINT:os.kill(os.getppid(),SIGUSR1)elif sig == SIGQUIT:os.kill(os.getppid(),SIGUSR2)elif sig == SIGUSR1:print('到站了,请下车')os._exit(0) # 子进程退出,可不写#子进程代表售票员
def saler():signal(SIGINT,saler_handler)signal(SIGQUIT,saler_handler)signal(SIGUSR1,saler_handler)signal(SIGTSTP,SIG_IGN)while True:sleep(2)print('python带你去远方')def driver_handler(sig,frame):if sig == SIGUSR1:print('老司机开车了')elif sig == SIGUSR2:print('车速有点快,系好安全带')elif sig == SIGTSTP:os.kill(p.pid,SIGUSR1)p = Process(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的信号量机制
版权声明:本文标题:python的信号量机制 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.roclinux.cn/b/1686562276a10616.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论