帶衝突檢測的載波監聽多路訪問的原理 協程原理小記

2021-10-11 02:33:56 字數 1542 閱讀 7684

從執行緒模型說起

協程的優勢

協程最大好處應該是能夠以同步的形式實現高效的非同步呼叫,這對非cpu密集型服務非常便利。通常情況下,實現高效i/o的辦法是非同步非阻塞通訊,典型如redis。但非同步操作和人類思維方式相左,不太友好。協程之所以有上述效果,本質上是因為它代替程式設計師在底層實現了非同步。

c語言函式呼叫過程

協程看上去神奇,但不過是基本知識的靈活運用。

c語言的函式呼叫棧大家耳熟能詳,這裡簡單說明下。圖1是32位機器的c語言函式呼叫棧,64位與此原理相同。在呼叫者棧中,首先將被調函式需要的引數今次放到棧中,然後執行call指令,該指令將它的緊跟call的下一條指令(也就是返回位址)放到棧中,同時跳轉到被調函式執行。引數和返回位址如圖右側的caller frame中所示。在被調函式棧中,被調函式從呼叫者的棧中取出引數,進行計算,將結果放到eax暫存器裡,呼叫ret返回。ret指令會將呼叫棧中儲存的返回位址放到pc(指令暫存器)中,然後cpu按呼叫者原路線執行。

協程實現原理

複雜的cpu就按上面說的呼叫套路機械地執行一條條的指令。常見的緩衝區溢位就與此有關:如果緩衝區將返回位址或棧楨的其它重要內容覆蓋了,函式返回時程式會崩潰;進一步,一些別有用心的人會覆蓋返回位址,將pc值改為他們期望的值,進而控制cpu執行流程,這就是緩衝區攻擊的原理。

水可載舟,亦可覆舟,如果建立多個函式棧,並能在各個棧之間切換執行,這就是協程!實際中,除了儲存了系統棧中的呼叫棧,還在堆上申請記憶體,做為協程執行時的棧空間。因為切換過程需要訪問暫存器,所以切換**是都是用彙編寫的。

到此好像「都挺好」的:建立了一系列協程,執行流在各個協程間切換執行。回憶一下,協程是為了「以同步的形式實現非同步呼叫」。假設乙個協程呼叫了read這個系統呼叫,如果是阻塞呼叫,那整個執行緒會被該呼叫阻塞,所有協程都不能執行;如果是非阻塞的,那應該迴圈等待read返回資料還是轉而執行其它協程?如果執行其它的,那怎麼使當前協程讓出cpu?這其實需要hook系統呼叫,同時用多路復用監聽事件,如定義read函式hook系統的read,首先將fd設定為非阻塞,並加到epoll中監聽可讀事件,然後呼叫協程切換流程讓出cpu,待epoll返回fd可讀事件時再執行該協程,這樣我們就能以同步形式實現非同步呼叫。

總之,協程的原理可以概括為兩點:1. 以棧楨結構為基礎的協程棧,2. hook系統呼叫。當然,這裡只是最簡單地記錄下協程的原理,具體實現還有很多任務作要做,但對於理解其原理應該足夠,畢竟不需要每個人都去實現乙個協程庫。

上面的原理適用於libco,對於bthread還有一項功能叫work stealing,就是當執行緒上任務不均勻時,比較閒的執行緒去偷取其它執行緒的協程任務來執行,這對於耗時不等的後台任務可能比較有用。

寫在最後

不免要感慨:

1. 看似高深的技術,其實是基於非常基礎的知識。

2. 有了brpc,還需要其它rpc嗎?

3. 有了go,還要堅持c++嗎?

多路訪問網路中的挑戰

多路訪問網路中的挑戰 在多路訪問網路中,相同的共享介質上連線有兩台以上裝置。乙太網 lan 就是一種廣播多路訪問網路。因為該網路中的所有裝置會看到所有廣播幀,所以它屬於廣播網路。ospf 定義了五種網路型別 l 點對點 www.2cto.com l 廣播多路訪問 l 非廣播多路訪問 nbma l 點...

廣播多路訪問鏈路上的OSPF

於 按照上圖中給出的引數,在此廣播多路訪問鏈路上的各個裝置上開啟ospf程序。在此我也只拿r1作為例子說一下開啟ospf程序的配置 1 router config router ospf 1 router config router router id 1.1.1.1 router config r...

關乙太網的衝突檢測

可以把衝突域比做乙個雙向單車道上的交通規則!而全雙工則是乙個雙車道。有了自己專有的行駛車道,你可以開自己的賓士任意飛速行駛還要什麼交通規則?這種情況下還使用csma cd的規則那不是吃多了?全雙工模式下兩個節點間的傳送和接收鏈路實際是分開的,所以幀是不可能衝突的。由於消除了衝突,所以全雙工連線將關閉...