摘要:前面的網(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 = 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) while True: conn_sock, client_addr = listen_sock.accept() pid = os.fork() if pid == 0: # I am child process serve(conn_sock, client_addr) else: # I am parent process conn_sock.close() def serve(conn_sock, client_addr): print("connected from %s:%s" % client_addr) input = conn_sock.recv(8192) while "done" != input.strip(): conn_sock.sendall(input) input = conn_sock.recv(8192) conn_sock.sendall("bye! ") conn_sock.close() main()
其中os.fork()之后會(huì)創(chuàng)建一個(gè)子進(jìn)程。子進(jìn)程默認(rèn)會(huì)繼承所有父進(jìn)程的所有file descriptor(也就包括打開(kāi)的socket),已經(jīng)擁有fork前父進(jìn)程的所有內(nèi)存狀態(tài)。所以子進(jìn)程可以拿著父進(jìn)程打開(kāi)的conn_sock繼續(xù)與客戶端通信。而父進(jìn)程在把conn_sock交給子進(jìn)程之后,就不再需要開(kāi)著這個(gè)socket的fd了,所以就需要關(guān)閉掉。否則,子進(jìn)程調(diào)用conn_sock.close()之后,客戶端的連接其實(shí)還沒(méi)有斷開(kāi),因?yàn)楦高M(jìn)程還拿著fd不放呢。
從調(diào)度的角度來(lái)看,前面說(shuō)的兩個(gè)要素:
狀態(tài)的保存:仍然是保存在棧上。每個(gè)進(jìn)程都有一個(gè)主線程。fork出來(lái)的子進(jìn)程的主線程的棧上保存了對(duì)應(yīng)客戶端的conn_sock。
不同socket之間的調(diào)度:仍然是利用內(nèi)核的scheduler,只是這次調(diào)度的是process。對(duì)于內(nèi)核來(lái)說(shuō)調(diào)度邏輯是差不多的,區(qū)別就是process還要額外更新一下虛擬內(nèi)存的映射表,使得多個(gè)process彼此之間不可見(jiàn)對(duì)方的內(nèi)存。
從效率上來(lái)說(shuō),具有多線程一樣的問(wèn)題,而且內(nèi)存占用會(huì)更高,切換成本也更高。多線程和多進(jìn)程的版本從代碼可讀性上來(lái)說(shuō)還是非常不錯(cuò)的,很好懂,從上至下平鋪直敘的。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/45304.html
摘要:最重要的是每個(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)銷(xiāo)是比較大。 上次的網(wǎng)絡(luò)編程的例子,改寫(xiě)成多線程的是這樣: import socket import thread def main(): listen_sock = socket.socke...
摘要:在了解了的實(shí)現(xiàn)方式的基礎(chǔ)之上,希望能夠把流程阻塞的功能在的框架之上實(shí)現(xiàn),從而可以制作一個(gè)簡(jiǎn)單的類(lèi)似,這樣的集群調(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è)...
摘要:簡(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)提...
摘要:如果你只對(duì)開(kāi)發(fā)者需要了解的事感興趣,請(qǐng)下拉到早該知道的事板塊。在不泄露機(jī)密的情況下,利用支持向量機(jī)來(lái)獲取一個(gè)句子最可能的意思,并且以此來(lái)推斷句子的情感。也就是說(shuō),如果一個(gè)文檔包含個(gè)詞,就會(huì)與支持向量機(jī)進(jìn)行多次對(duì)比。 【編者按】本文最早由 Repustate 發(fā)布,主要介紹將代碼遷移至 Go(lang) 時(shí)的注意事項(xiàng)。文章系國(guó)內(nèi) ITOM 管理平臺(tái) OneAPM 編譯呈現(xiàn),以下為正文。 ...
摘要:我們可以看一下的可見(jiàn)是由內(nèi)部支持的,其實(shí)現(xiàn)原理上就避免了棧進(jìn)棧出的消耗,直接由最內(nèi)層的返回值。另外可以實(shí)現(xiàn)外部直接向最內(nèi)層的傳遞值,比如這段代碼的輸出是這樣傳值的方式,在用循環(huán)重新的模式下是無(wú)法實(shí)現(xiàn)的。這也就是必須使用,而不能使用的原因。 在python 3.3里,generator新增了一個(gè)語(yǔ)法 yield from 這個(gè)yield from的作用是什么?看下面兩段對(duì)比的代碼: d...
閱讀 975·2021-11-22 13:53
閱讀 2607·2021-10-15 09:40
閱讀 1096·2021-10-14 09:42
閱讀 3930·2021-09-22 15:59
閱讀 967·2021-09-02 09:47
閱讀 2544·2019-08-30 15:54
閱讀 1506·2019-08-29 17:14
閱讀 465·2019-08-29 15:15