PyOS 0.3
PyOS - 一个Python写的OS(3) 目录:
实现子函数 在之前实现的OS中,我们的任务存在一个问题,就是不能进行非阻塞子函数调用。为啥呢?看如下例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 def add (x, y ): yield a + b def main (): y = yield add(2 , 2 ) print (y) yield def run (): m = main() sub = m.send(None ) result = sub.send(None ) m.send(result) run()
上面这段函数的调用过程如下图:
问题出在我们的 Task 的结构,如果我们想要进行子函数调用,我们就需要一个 栈。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 class Task (object ): taskid = 0 def __init__ (self,target ): Task.taskid += 1 self.tid = Task.taskid self.target = target self.sendval = None self.stack = [] def run (self ): while True : try : result = self.target.send(self.sendval) if isinstance (result, SystemCall): return result if isinstance (result, types.GeneratorType): self.stack.append(self.target) self.sendval = None self.target = result else : if not self.stack: return self.sendval = result self.target = self.stack.pop() except StopIteration: if not self.stack: raise self.sendval = None self.target = self.stack.pop()
具体解释在注释里。
封装一些IO操作 有了子函数后,我们就可以对之前的一些 IO 操作进行封装,隐藏 具体的 yield 信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 def Accept (sock ): yield ReadWait(sock) yield sock.accept() def Send (sock,buffer ): while buffer: yield WriteWait(sock) len = sock.send(buffer) buffer = buffer[len :] def Recv (sock,maxbytes ): yield ReadWait(sock) yield sock.recv(maxbytes)
比如上面就是三个Socket相关的函数,现在我们可以用这些系统库重写我们上一次的 Echo Server。
重写 Echo Server 这里我们不再需要直接OS call,而是使用一些封装的库函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 from coroutine.os.pyos1 import *from socket import *def handle_client (client, addr ): print ('Connection from ' , addr) while True : data = yield Recv(client,65536 ) print ('Server receive ' , data) if not data: break print ('Server echo back' , data) yield Send(client,data) client.close() print ('Client closed.' ) def server (port ): print ('Server start..' ) sock = socket(AF_INET, SOCK_STREAM) sock.setsockopt(SOL_SOCKET,SO_REUSEADDR,1 ) sock.bind(("" ,port)) sock.listen(1024 ) while True : yield ReadWait(sock) client, addr = sock.accept() yield NewTask(handle_client(client, addr)) sched = Scheduler() sched.schedule(Task(server(45000 ))) sched.mainloop()
写在最后 这个系列就高于段落了,我们的PyOS停留在了0.3,其实还有很多东西可以考虑,比如:
任务之间的通讯
阻塞任务,比如数据库读取
任务和线程结合
异常处理
最后最后 其实,这个系列主要是想探索Python的协程并发编程,Python 3.5 以后引入了 async/await
关键字和一个相关的异步IO库 asyncio
,这些内容都跟这个系列有些许的联系。
关于Python的并发,如果感兴趣还可以看:
Stackless Python
Greenlet
Eventlet
Cogen