成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

【tulip】 - IOCP

Sunxb / 2474人閱讀

摘要:簡(jiǎn)單來(lái)說(shuō)就是一個(gè)操作系統(tǒng)提供的回調(diào)機(jī)制。其中這一步是創(chuàng)建,是做一個(gè)調(diào)用,后面的是輪詢,這一步是根據(jù)返回的查找對(duì)應(yīng)的回調(diào)函數(shù)回調(diào)。這樣狀態(tài)從多個(gè)線程的多個(gè)棧上,變成了只有一個(gè)線程,但是在線程內(nèi)部有一個(gè)來(lái)維護(hù)單線程內(nèi)多個(gè)并發(fā)流程的狀態(tài)。

為了讓I/O阻塞的時(shí)候,程序還可以去干別的。除了使用線程模型,讓操作系統(tǒng)的內(nèi)核去調(diào)度多個(gè)線程,Windows提供了IOCP機(jī)制。簡(jiǎn)單來(lái)說(shuō)就是一個(gè)操作系統(tǒng)提供的回調(diào)機(jī)制。分成四個(gè)步驟

生成key,并建立映射關(guān)系:向操作系統(tǒng)創(chuàng)建一個(gè)key,程序內(nèi)部把這個(gè)key和一個(gè)回調(diào)函數(shù)對(duì)應(yīng)起來(lái)

調(diào)用:執(zhí)行阻塞的I/O操作,并指定key來(lái)對(duì)應(yīng)這個(gè)I/O操作

輪詢,返回key:程序輪詢操作系統(tǒng)詢問(wèn)是否有新的I/O操作完成,如果有完成的會(huì)返回對(duì)應(yīng)的key

用key查找,并回調(diào):因?yàn)閯?chuàng)建key的時(shí)候內(nèi)部已經(jīng)和一個(gè)回調(diào)函數(shù)對(duì)應(yīng)起來(lái)了,所以這個(gè)時(shí)候之前映射好的函數(shù)會(huì)被回調(diào)

前面的例子太復(fù)雜了,我們把a(bǔ)ccept后面的操作全部忽略掉。多帶帶看一個(gè)服務(wù)器接收客戶端連接的代碼:

import socket
from asyncio import _overlapped
import struct

listen_sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM, proto=socket.IPPROTO_IP)
listen_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
listen_sock.bind(("0.0.0.0", 9090))
listen_sock.listen(0)
NULL = 0
concurrency=0xffffffff
_iocp = _overlapped.CreateIoCompletionPort(_overlapped.INVALID_HANDLE_VALUE, NULL, 0, concurrency)
_overlapped.CreateIoCompletionPort(listen_sock.fileno(), _iocp, 0, 0)
conn_sock = socket.socket(listen_sock.family)
conn_sock.settimeout(0)
ov = _overlapped.Overlapped(NULL)
ov.AcceptEx(listen_sock.fileno(), conn_sock.fileno())
def on_accepted():
    buf = struct.pack("@P", listen_sock.fileno())
    conn_sock.setsockopt(socket.SOL_SOCKET, _overlapped.SO_UPDATE_ACCEPT_CONTEXT, buf)
    conn_sock.settimeout(listen_sock.gettimeout())
    print("connected from %s:%s" % conn_sock.getpeername())
    return conn_sock, conn_sock.getpeername()
callback_map = {}
if ov.pending:
    callback_map[ov.address] = on_accepted
else:
    on_accepted()
while True:
    # wait maximum 1 second
    status = _overlapped.GetQueuedCompletionStatus(_iocp, 1000)
    if status is None:
        continue # try again
    err, transferred, key, address = status
    callback = callback_map[address]
    callback()
    break

這段代碼使用了Python 3.4。其中 _overlapped.Overlapped(NULL) 這一步是創(chuàng)建key,ov.AcceptEx(listen_sock.fileno(), conn_sock.fileno()) 是做一個(gè)I/O調(diào)用,后面的 _overlapped.GetQueuedCompletionStatus(_iocp, 1000) 是輪詢,callback_map[address] 這一步是根據(jù)返回的key查找對(duì)應(yīng)的回調(diào)函數(shù)回調(diào)。
這種實(shí)現(xiàn)方式與前面基于線程的方式顯著不同:

程序內(nèi)狀態(tài)的上下文的保存不再由操作系統(tǒng)負(fù)責(zé),而是通過(guò)callback_map由程序代碼自己來(lái)負(fù)責(zé)的

操作系統(tǒng)只負(fù)責(zé)維護(hù)阻塞I/O操作與對(duì)應(yīng)的key(也就是overlapped.address這個(gè)東西)的關(guān)系。程序內(nèi)的多個(gè)并發(fā)流程(本例子里只有一個(gè)客戶端)需要由程序自身通過(guò)key和callback_map來(lái)自己做調(diào)度。

這樣狀態(tài)從多個(gè)線程的多個(gè)棧上,變成了只有一個(gè)線程,但是在線程內(nèi)部有一個(gè)callback_map來(lái)維護(hù)單線程內(nèi)多個(gè)并發(fā)流程的狀態(tài)。某種程度上來(lái)說(shuō),相對(duì)于多線程是把一些操作系統(tǒng)的上下文保存和調(diào)度職責(zé)從操作系統(tǒng)內(nèi)核移到了網(wǎng)絡(luò)程序里。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/45303.html

相關(guān)文章

  • tulip】 - I/O阻塞的小例子

    摘要:在了解了的實(shí)現(xiàn)方式的基礎(chǔ)之上,希望能夠把流程阻塞的功能在的框架之上實(shí)現(xiàn),從而可以制作一個(gè)簡(jiǎn)單的類似,這樣的集群調(diào)度工具。我們先來(lái)看一個(gè)最基本的網(wǎng)絡(luò)編程的例子這是一個(gè)服務(wù)器。 接下來(lái),會(huì)把Python tulip這個(gè)網(wǎng)絡(luò)庫(kù)(也就是3.4之后的asyncio)如何實(shí)現(xiàn)的進(jìn)行一些分析。在了解了tulip的實(shí)現(xiàn)方式的基礎(chǔ)之上,希望能夠把流程阻塞的功能在tulip的框架之上實(shí)現(xiàn),從而可以制作一個(gè)...

    JessYanCoding 評(píng)論0 收藏0
  • tulip】 - 多進(jìn)程的版本

    摘要:前面的網(wǎng)絡(luò)編程的例子使用多進(jìn)程也是可以實(shí)現(xiàn)的其中之后會(huì)創(chuàng)建一個(gè)子進(jìn)程。從效率上來(lái)說(shuō),具有多線程一樣的問(wèn)題,而且內(nèi)存占用會(huì)更高,切換成本也更高。多線程和多進(jìn)程的版本從代碼可讀性上來(lái)說(shuō)還是非常不錯(cuò)的,很好懂,從上至下平鋪直敘的。 前面的網(wǎng)絡(luò)編程的例子使用多進(jìn)程也是可以實(shí)現(xiàn)的: import socket import os def main(): listen_sock = s...

    ACb0y 評(píng)論0 收藏0
  • tulip】 - 多線程的版本

    摘要:最重要的是每個(gè)線程,對(duì)應(yīng)了一個(gè)函數(shù)的執(zhí)行。有多個(gè)線程同時(shí)執(zhí)行的時(shí)候,每個(gè)線程的狀態(tài)是由操作系統(tǒng)內(nèi)核負(fù)責(zé)保存在內(nèi)存中的。在多線程的實(shí)現(xiàn)中。并且內(nèi)核的線程在切換多個(gè)線程的時(shí)候,線程切換的開(kāi)銷是比較大。 上次的網(wǎng)絡(luò)編程的例子,改寫成多線程的是這樣: import socket import thread def main(): listen_sock = socket.socke...

    CoderStudy 評(píng)論0 收藏0
  • 比較了Gruvi針對(duì)asyncio,gevent和eventlet的一些設(shè)計(jì)決策和功能

    下表比較了Gruvi針對(duì)asyncio,gevent和eventlet的一些設(shè)計(jì)決策和功能。 * 特征 Gruvi Asyncio Gevent Eventlet IO library(依賴包) libuv stdlib libev stdlib /?libevent IO abstractionTransports/Protocols Transports/ProtocolsGre...

    ls0609 評(píng)論0 收藏0
  • 測(cè)試用例

    下表比較了Gruvi針對(duì)asyncio,gevent和eventlet的一些設(shè)計(jì)決策和功能。 * 特征 Gruvi Asyncio Gevent Eventlet IO library(依賴包) libuv stdlib libev stdlib /?libevent IO abstractionTransports/Protocols Transports/ProtocolsGre...

    WrBug 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<