Python高级编程之生成器(Generator)与coroutine(四):一个简单的多任务系统
啊,终于要把这一个系列写完整了,好高兴啊
在前面的三篇文章中介绍了Python的Python的Generator和coroutine(协程)相关的编程技术,接下来这篇文章会用Python的coroutine技术实现一个简单的多任务的操作系统
代码如下,可看注释
#-*-coding:utf-8 -*-
'''
用Python和coroutine实现一个简单的多任务系统
'''
# ##Step 1:Define Tasks###################################
import select
class Task(object):
taskid = 0 def __init__(self,target):
Task.taskid += 1
self.tid = Task.taskid # Task id
self.target = target # Target coroutine
self.sendval = None # Value to send def run(self):
return self.target.send(self.sendval)
# ############################################### # ##Step 2:The Scheduler#########################
import Queue
class Scheduler(object):
def __init__(self):
self.ready = Queue.Queue()
self.taskmap = {} # 正在等待的Tasks,key是taskid
self.exit_waiting = {} # 异步IO
# Holding areas for tasks blocking on I/O.These are
# dictionaries mapping file descriptions to tasks
# 键值为文件描述符
self.read_waiting = {}
self.write_waiting = {} def iotask(self):
while True:
if self.ready.empty():
# 如果ready为空,表示没有正在等待执行的队列
# timeout 为None,表示不关心任何文件描述符的变化
self.iopool(None)
else:
# ready不为空,则设置select函数不管文件描述符是否发生变化都立即返回
self.iopool(0)
yield def new(self,target):
newtask = Task(target)
self.taskmap[newtask.tid] = newtask
self.schedule(newtask)
return newtask.tid def schedule(self,task):
# 把task放到任务队列中去
self.ready.put(task) def exit(self,task):
print "Task %d terminated" %task.tid
del self.taskmap[task.tid]
# Notify other tasks waiting for exit
# 把正在等待的任务加入到正在执行的队列中去
for task in self.exit_waiting.pop(task.tid,[]):
self.schedule(task) def waitforexit(self,task,waittid):
'''
让一个任务等待另外一个任务,把这个任务加入到exit_waiting中去
返回True表示这个task正在等待队列中
'''
if waittid in self.taskmap:
self.exit_waiting.setdefault(waittid,[]).append(task)
return True
else:
return False def waitforread(self,task,fd):
'''
functions that simply put a task into to
one of the above dictionaries
'''
self.read_waiting[fd] = task def waitforwrite(self,task,fd):
self.write_waiting[fd] = task def iopool(self,timeout):
'''
I/O Polling.Use select() to determine which file
descriptors can be used.Unblock any associated task
'''
if self.read_waiting or self.write_waiting:
# 获取I/O事件,一旦获取到,就放入到执行队列中取,等待执行
r,w,e = select.select(self.read_waiting,
self.write_waiting,[],timeout)
for fd in r:
self.schedule(self.read_waiting.pop(fd)) for fd in w:
self.schedule(self.write_waiting.pop(fd)) def mainloop(self):
self.new(self.iotask()) # Launch I/O polls
while self.taskmap:
task = self.ready.get()
try:
result = task.run()
# 如果task执行的是System call,则对当前环境进行保存
# 然后在执行System Call
if isinstance(result,SystemCall):
# 把当前的环境保存,即保存当前运行的task和sched
result.task = task
result.sched = self
result.handle()
continue
except StopIteration:
self.exit(task)
# print("task is over")
continue
self.schedule(task)
# ##Step 2:The Scheduler######################### # ##SystemCall#########################
class SystemCall(object):
'''
所有系统调用的基类,继承自该类的类要重写handle函数
'''
def handle(self):
pass class GetTid(SystemCall):
'''
获取任务ID
'''
def handle(self):
self.task.sendval = self.task.tid
self.sched.schedule(self.task) class NewTask(SystemCall):
'''
新建一个Task
'''
def __init__(self,target):
self.target = target def handle(self):
# 在这里把target封装成Task
# 是在这里把新生成的task加入到执行队列当中去
tid = self.sched.new(self.target)
self.task.sendval = tid
# 把执行这个系统调用的父task重新加入到执行队列中去
# 这一点很关键,因为判断一个task是否结束是通过taskmap的
# 这个task只是暂时被挂起,要重新放到queue中去
self.sched.schedule(self.task) class KillTask(SystemCall):
'''
杀死一个Task
'''
def __init__(self,tid):
self.tid = tid def handle(self):
task = self.sched.taskmap.get(self.tid,None)
# task指的是要被kill掉的那个task
# self.task指的是发起KillTask这个系统调用task
if task:
task.target.close()
self.task.sendval = None
else:
self.task.sendval = False
# target.close()只是产生一个StopIteration异常
self.sched.schedule(self.task) class WaitTask(SystemCall):
'''
让任务进行等待 系统调用
'''
def __init__(self,tid):
self.tid = tid def handle(self):
result = self.sched.waitforexit(self.task,self.tid)
self.task.sendval = result
# 如果等待的是一个不存在的task,则立即返回
if not result:
self.sched.schedule(self.task) class ReadWait(SystemCall):
'''
异步读 系统调用
'''
def __init__(self,f):
self.f = f def handle(self):
fd = self.f.fileno()
self.sched.waitforread(self.task,fd) class WriteWait(SystemCall):
'''
异步写 系统调用
'''
def _init__(self,f):
self.f = f def handle(self):
fd = self.f.fileno()
self.sched.waitforwrite(self.task,fd)
Python高级编程之生成器(Generator)与coroutine(四):一个简单的多任务系统的更多相关文章
- Python高级编程之生成器(Generator)与coroutine(二):coroutine介绍
原创作品,转载请注明出处:点我 上一篇文章Python高级编程之生成器(Generator)与coroutine(一):Generator中,我们介绍了什么是Generator,以及写了几个使用Gen ...
- Python高级编程之生成器(Generator)与coroutine(一):Generator
转载请注明出处:点我 这是一系列的文章,会从基础开始一步步的介绍Python中的Generator以及coroutine(协程)(主要是介绍coroutine),并且详细的讲述了Python中coro ...
- Python高级编程之生成器(Generator)与coroutine(三):coroutine与pipeline(管道)和Dataflow(数据流_
原创作品,转载请注明出处:点我 在前两篇文章中,我们介绍了什么是Generator和coroutine,在这一篇文章中,我们会介绍coroutine在模拟pipeline(管道 )和控制Dataflo ...
- python高级编程技巧
由python高级编程处学习 http://blog.sina.com.cn/s/blog_a89e19440101fb28.html Python列表解析语法[]和生成 器()语法类似 [expr ...
- 第十一章:Python高级编程-协程和异步IO
第十一章:Python高级编程-协程和异步IO Python3高级核心技术97讲 笔记 目录 第十一章:Python高级编程-协程和异步IO 11.1 并发.并行.同步.异步.阻塞.非阻塞 11.2 ...
- python高级编程之选择好名称:完
由于时间关系,python高级编程不在放在这边进行学习了,如果需要的朋友可以看下面的网盘进行下载 # # -*- coding: utf-8 -*- # # python:2.x # __author ...
- python高级编程之列表推导式
1. 一个简单的例子 在Python中,如果我们想修改列表中所有元素的值,可以使用 for 循环语句来实现. 例如,将一个列表中的每个元素都替换为它的平方: >>> L = [1, ...
- python高级编程:有用的设计模式3
# -*- coding: utf-8 -*-__author__ = 'Administrator'#python高级编程:有用的设计模式#访问者:有助于将算法从数据结构中分离出来"&qu ...
- python高级编程:有用的设计模式2
# -*- coding: utf-8 -*- __author__ = 'Administrator' #python高级编程:有用的设计模式 #代理 """ 代理对一 ...
随机推荐
- HDUOJ-------Naive and Silly Muggles
Naive and Silly Muggles Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/ ...
- C# MediaPlayer的详细用法
AxWindowsMediaPlayer的详细用法 作者:龙昊雪 AxWindowsMediaPlayer的详细用法收藏 function StorePage(){d=document;t=d.sel ...
- UNIX域套接字编程和socketpair 函数
一.UNIX Domain Socket IPC socket API原本是为网络通讯设计的,但后来在socket的框架上发展出一种IPC机制,就是UNIX Domain Socket.虽然网络soc ...
- STM32以太网ETH
注:stm32F1系列中F103片上不含MAC控制器,所以不支持以太网,只有F105和F107才支持
- yii2 数据库操作详解(转载)
开始使用数据库首先需要配置数据库连接组件,通过添加 db 组件到应用配置实现("基础的" Web 应用是 config/web.php),DSN( Data Source Name ...
- Apache优化:修改最大并发连接数(转)
Apache是一个跨平台的web服务器,由于其简单高效.稳定安全的特性,被广泛应用于计算机技术的各个领域.现在,Apache凭借其庞大的用户数,已成为用户数排名第一的web服务器. 尽 管如此,在实际 ...
- eclipse软件与git配合使用创建git仓库
一.在eclipse上安装git,和安装其他插件一样 help->Install new software->add... 在弹出框中输入name:git,location:http:// ...
- django官方文档学习-入门part3创建用户视图
一.官方的约定: 1.在django中有一个约定.那就是每一个app自己的模板最好放在自己app目录下的templates子目录下. 但是这个还没有完成.最好还是在templates目录下加一个app ...
- mysql如何查找某字段所在表
如果是5.0以上的,以root用户连接,可以看到一个叫information_schema的表, 然后只要:use information_schema; select `TABLE_NAME`fro ...
- TRIZ系列-创新原理-9~11-预先反作用原理、预处理原理、预先防范原理
一.预先反作用原理表述例如以下: 1)预先给物体施加反作用,以补偿过量的或者不想要的压力. 假设知道系统在执行过程中,会有不利的或者有害的作用(负面作用)产生,则能够预先採取一定的措施来抵消.控制这样 ...