[Linux][網絡][高級IO][IO多路轉接][select][poll]詳細講解

目錄

  • 1.IO多路轉接之select
    • 1.初識select
    • 2.select()
    • 3.關于fd_set結構
    • 4.關于timeval結構
    • 5.理解select執行過程
    • 6.select就緒條件
    • 7.select特點
    • 8.select優點(任何一個多路轉接方案,都具備)
    • 9.select缺點
    • 10.select的一般編寫代碼的模式
    • 11.思考 && 問題
  • 2.IO多路轉接之poll
    • 1.poll()
    • 2.pollfd結構
    • 3.poll就緒條件
    • 4.poll的優點
    • 5.poll缺點


1.IO多路轉接之select

1.初識select

  • select系統調用是用來讓程序監視多個文件描述符的狀態變化的
  • 程序會停在select這里等待,直到被監視的文件描述符有一個或多個發生了狀態改變
  • 總結:
    • 幫用戶進行一次等待多個文件描述符
    • 當哪些文件描述符就緒了,select就要通知用戶,對應就緒的sock有哪些,然后用戶再調用recv/read等接口進行數據讀取

2.select()

  • 原型:int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

  • 參數:

    • nfds:要監視的最大的文件描述符+1
    • readfds,writefds,exceptfds:均為輸入輸出型參數,分別對應于需要檢測的可讀/可寫/異常文件描述符的集合
      • 輸入時:用戶告訴內核,你要幫我關心哪些fd的哪一種事件
        • bit位的位置表示文件描述符值,bit位的內容表示是否關心(1/0)
      • 輸出時:內核告訴用戶,我所關心的fd中,哪些fd上的哪類事件已經就緒了
        • bit位的位置表示文件描述符值,bit位的內容表示是否就緒(1/0)
      • 用戶和內核都會修改同一個位圖結構,這些參數用一次之后,一定要進行重新設定
    • timeout:用來設置select()的等待時間,其取值
      • nullptr:阻塞等待
      • 0:非阻塞等待
      • 特定時間值:如果在指定的時間段里沒有事件發生,select()將超時返回
      • 如果等待時間內,有fd就緒,會怎樣呢?
        • 呈現輸出型,存放距離下一次timeout剩余多長時間
  • 返回值

    • 執行成功則返回文件描述詞狀態已改變的個數
    • 如果返回0代表在描述詞狀態改變前已超過timeout時間,沒有返回
    • 當有錯誤發生時則返回-1,錯誤原因存于errno,此時參數readfds,writefds, exceptfds和timeout的值變成不可預測
  • 錯誤碼可能值

    • EBADF:文件描述詞為無效的或該文件已關閉
    • EINTR:此調用被信號所中斷
    • EINVAL:參數n為負值
    • ENOMEM:核心內存不足

3.關于fd_set結構

/* The fd_set member is required to be an array of longs.  */
typedef long int __fd_mask;typedef struct{/* XPG4.2 requires this member name.  Otherwise avoid the namefrom the global namespace.  */
#ifdef __USE_XOPEN__fd_mask fds_bits[__FD_SETSIZE / __NFDBITS];
# define __FDS_BITS(set) ((set)->fds_bits)
#else__fd_mask __fds_bits[__FD_SETSIZE / __NFDBITS];
# define __FDS_BITS(set) ((set)->__fds_bits)
#endif} fd_set;
  • 其實這個結構就是一個整數數組,更嚴格的說,是一個**“位圖”,使用位圖中對應的bit位來表示要監視的文件描述符**
  • 提供了一組操作fd_set的接口, 來比較方便的操作位圖
    void FD_CLR(int fd, fd_set *set); // 用來清除描述詞組set中相關fd的bit位
    int FD_ISSET(int fd, fd_set *set); // 用來測試描述詞組set中相關fd的but位是否為真
    void FD_SET(int fd, fd_set *set); // 用來設置描述詞組set中相關fd的bit位
    void FD_ZERO(fd_set *set); // 用來清除描述詞組set的全部bit位
    

4.關于timeval結構

  • timeval結構用于描述一段時間長度,如果在這個時間內,需要監視的文件描述符沒有事件發生則函數返回,返回值為0
    struct timeval
    {__time_t tv_sec;    /* Seconds. */__suseconds_t tv_usec;  /* Microseconds. */
    };
    

5.理解select執行過程

  • 理解select模型的關鍵在于理解fd_set,為說明方便,取fd_set長度為1字節
  • fd_set中的每一bit可以對應一個文件描述符fd,則1字節長的fd_set最大可以對應8個fd.
    1. 執行fd_set set; FD_ZERO(&set);
      • 則set用位表示是0000,0000
    2. 若fd=5,執行FD_SET(fd, &set);
      • set變為0001,0000(第5個bit位置為1)
    3. 若再加入fd=2,fd=1
      • 則set變為0001,0011
    4. 執行**select(6, &set, nullptr, nullptr, nullptr)**阻塞等待
    5. 若fd=1,fd=2上都發生可讀事件,則select返回
      • 此時set變為0000,0011
      • **注意:**沒有事件發生的fd=5被清空

6.select就緒條件

  • 讀就緒
    • socket內核中,接收緩沖區中的字節數,大于等于低水位標記SO_RCVLOWAT
      • 此時可以無阻塞的讀該文件描述符,并且返回值大于0
    • socket TCP通信中,對端關閉連接,此時對該socket讀,則返回0
    • 監聽的socket上有新的連接請求
    • socket上有未處理的錯誤
  • 寫就緒
    • socket內核中,發送緩沖區中的可用字節數(發送緩沖區的空閑位置大小),大于等于低水位標記SO_SNDLOWAT
      • 此時可以無阻塞的寫,并且返回值大于0
    • socket的寫操作被關閉(close或者shutdown),對一個寫操作被關閉的socket進行寫操作,會觸發SIGPIPE信號
    • socket使用非阻塞connect連接成功或失敗之后
    • socket上有未讀取的錯誤

7.select特點

  • 可監控的文件描述符個數取決與sizeof(fd_set)的值
    • 我虛擬機上sizeof(fd_set)=128,每bit表示一個文件描述符,則支持的最大文件描述符是128*8=1024
  • 將fd加入select監控集的同時,還要再使用一個第三方數組用來保存所有的合法fd
    1. 用于在select返回后,array作為源數據和fd_set進行FD_ISSET判斷
    2. select返回后會把以前加入的但并無事件發生的fd清空,則每次開始select前都要重新從array取得fd并逐一加入(FD_ZERO最先),掃描array的同時取得fd最大值maxfd,用于select的第一個參數

8.select優點(任何一個多路轉接方案,都具備)

  • 效率高
  • 應用場景:有大量的鏈接,但是只有少量是活躍的,節省資源

9.select缺點

  • 為了維護第三方數組,select服務器會充滿大量遍歷,OS底層幫用戶關心fd的時候,也要遍歷
  • 每一次都要對select輸出參數進行重新設定
  • 能夠同時管理的fd的個數是有上限的 <-- fd_set大小是被固定了的
  • 因為幾乎每一個參數都是輸入輸出型的,select一定會頻繁地進行用戶到內核,內核到用戶的參數數據拷貝
  • 編碼比較復雜

10.select的一般編寫代碼的模式

while(true)
{// 1.遍歷數組,更新出最大值// 2.遍歷數組,添加所有需要關心的fd到fd_set位圖中// 3.調用select進行事件檢測// 4.遍歷數組,找到就緒的事件,根據就緒的事件,完成對應的動作// a.Accepter b.recver
}

11.思考 && 問題

  • 如何看待_listensock?
    • 獲取新連接,依然把它看成IO,如果沒有連接到來,就阻塞
  • 參數影響編碼模式
    1. nfds:隨著獲取的sock越來越多,添加到select的sock越來越多,注定了nfds每一次都可能要變化,需要對它動態計算
    2. readfds/writefds/exceptfds:都是輸入輸出型參數,輸入輸出不一定是一樣的,所以注定每次都要對其進行重新添加
    3. timeout:輸入輸出型參數,每一次都要進行重置,前提是需要的話
      • 1,2 --> 注定必須自己將合法的fd單獨全部保存起來,以支持:a.更新最大fd b.更新位圖結構

2.IO多路轉接之poll

1.poll()

  • 原型:int poll(struct pollfd *fds, nfds_t nfds, int timeout);
  • 參數:
    • fds:是一個poll()監聽的結構的數組,每一個元素中,包含了三部分內容:文件描述符,監聽的事件集合,返回的事件集合
    • nfds:表示fds數組的長度
    • **timeout:
      • 表示poll()的超時時間,單位是毫秒
      • 設置為0,表示非阻塞等待
      • 設置為-1,表示阻塞等待
  • 返回值
    • 執行成功則返回文件描述詞狀態已改變的個數
    • 如果返回0代表在描述詞狀態改變前已超過timeout時間,沒有返回
    • 當有錯誤發生時則返回-1,錯誤原因存于errno

2.pollfd結構

struct pollfd
{int fd;        /* File descriptor to poll.  */short int events;  /* Types of events poller cares about.  */short int revents; /* Types of events that actually occurred. */
};
  • events****和revents的取值
事件描述是否可作為輸入是否可作為輸出
POLLIN數據(包括普通數據和優先數據)可讀
POLLRDNORM普通數據可讀
POLLRDBAND優先級帶數據可讀(Linux不支持)
POLLPRI高優先級數據可讀,比如TCP帶外數據
POLLOUT數據(包括普通數據和優先數據)可寫
POLLWRNORM普通數據可寫
POLLRDHUPTCP****連接被對方關閉,或者對方關閉了寫操作,它由GNU引入
POLLERR錯誤
POLLHUP掛起,比如管道的寫端被關閉后,讀端描述符上將收到POLLHUP事件
POLLNVAL文件描述符沒有打開

3.poll就緒條件

  • 同select

4.poll的優點

  • 效率高
  • 應用場景:有大量的鏈接,但是只有少量是活躍的,節省資源
  • 輸入輸出參數是分離的,不需要進行大量的重置
  • 沒有可以管理的fd最大數量限制

5.poll缺點

  • poll依舊需要不少的遍歷,在用戶層檢測事件就緒、內核檢測fd就緒,都需要大量遍歷
    • 且用戶還是需要自己維護第三方數組
  • poll需要內核到用戶的拷貝 – 少不了的
  • poll的代碼結構依然比較復雜 – 比select容易

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/12441.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/12441.shtml
英文地址,請注明出處:http://en.pswp.cn/web/12441.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【PB案例學習筆記】-02 目錄瀏覽器

寫在前面 這是PB案例學習筆記系列文章的第二篇&#xff0c;該系列文章適合具有一定PB基礎的讀者&#xff0c; 通過一個個由淺入深的編程實戰案例學習&#xff0c;提高編程技巧&#xff0c;以保證小伙伴們能應付公司的各種開發需求。 文章中設計到的源碼&#xff0c;小凡都上…

基于Django實現的(bert)深度學習文本相似度檢測系統設計

基于Django實現的&#xff08;bert&#xff09;深度學習文本相似度檢測系統設計 開發語言:Python 數據庫&#xff1a;MySQL所用到的知識&#xff1a;Django框架工具&#xff1a;pycharm、Navicat、Maven 系統功能實現 登錄頁面 注冊頁面&#xff1a;用戶賬號&#xff0c;密碼…

05-14 周二 PyTorch動態量化和靜態量化理解

05-14 周二 PyTorch動態量化和靜態量化理解 時間版本修改人描述2024年5月14日10:44:30V0.1宋全恒新建文檔2024年5月14日16:28:16V1.0宋全恒填充了PyTorch對于兩種量化方式的內容 簡介 Pytorch動態量化 設計神經網絡時&#xff0c;可以進行許多權衡。在模型開發和訓練期間&…

Dilworth定理:最少的下降序列個數就等于整個序列最長上升子序列的長度

概念如下&#xff1a; 狄爾沃斯定理_百度百科 (baidu.com) 本質就是找要求序列中最長的單調的子序列&#xff08;不一定連續&#xff09;的長度。 模板如下&#xff1a; 時間復雜度為O&#xff08;N^2&#xff09; #include<iostream>using namespace std;int dp[100…

RK3568平臺開發系列講解(SPI篇)SPI數據的傳輸

??返回專欄總目錄 文章目錄 一、數據結構1.1、spi_transfer 結構體1.2、spi_message二、數據發送程序分析沉淀、分享、成長,讓自己和他人都能有所收獲!?? ?? 參考資料: spi_transferspi_message一、數據結構 spi 數據傳輸主要使用了 spi_message 和 spi_transfer 結構…

二叉樹的前序遍歷(leetcode)

144. 二叉樹的前序遍歷 - 力扣&#xff08;LeetCode&#xff09; 給你二叉樹的根節點 root &#xff0c;返回它節點值的 前序 遍歷。 這道題的啟發性真的很強 &#xff0c;這里必須傳入i的指針進去&#xff0c;下一次棧幀i&#xff0c;但回到了上一層i又變回到了原來的i&#…

docker network ls(用于列出 Docker 主機上的所有網絡)

docker network ls 是一個 Docker 命令&#xff0c;用于列出 Docker 主機上的所有網絡。Docker 允許你創建自定義的網絡&#xff0c;以便更好地控制容器之間的通信。 當你運行 docker network ls 命令時&#xff0c;你可能會看到如下類似的輸出&#xff08;輸出可能會根據你的…

每日一題12:Pandas:數據重塑-融合

一、每日一題 解答&#xff1a; import pandas as pddef meltTable(report: pd.DataFrame) -> pd.DataFrame:reshaped_report report.melt(id_varsproduct, var_namequarter, value_namesales)return reshaped_report 題源&#xff1a;Leetcode 二、總結 melt()函數是Pa…

Nginx生產環境最佳實踐之配置灰度環境

你好呀&#xff0c;我是趙興晨&#xff0c;文科程序員。 下面的內容可以說是干貨滿滿建議先收藏再慢慢細品。 今天&#xff0c;我想與大家深入探討一個我們日常工作中不可或缺的話題——灰度環境。你是否在工作中使用過灰度環境&#xff1f;如果是&#xff0c;你的使用體驗如…

AI圖像生成-基本步驟

模型板塊 1、新建采樣器&#xff1a;新建節點-》采樣器-》K采樣器 2、拖動模型節點后放開&#xff0c;選擇checkpoint加載器&#xff08;簡易&#xff09;&#xff0c;模型新建成功 提示詞板塊 1、拖動正面條件節點后放開&#xff0c;選擇CLIP文本編碼器&#xff0c;模型新建…

mysql 一次刪除多個備份表

show tables時&#xff0c;發現備份的表有點多&#xff0c;想要一個sql就刪除 總不能drop table xx ; 寫多次吧。 方式一 1.生成刪除某個數據庫下所有的表SQL -- 查詢構建批量刪除表語句&#xff08;根據數據庫名稱&#xff09; select concat(drop table , TABLE_NAME, ;)…

代碼隨想錄算法訓練營第39天|● 62.不同路徑 ● 63. 不同路徑 II

62. 不同路徑 遞歸棧很酷 但超時 class Solution:def uniquePaths(self, m: int, n: int) -> int:if m1 or n1:return 1return self.uniquePaths(m-1,n)self.uniquePaths(m,n-1) 逐行dp class Solution:def uniquePaths(self, m: int, n: int) -> int:dp[1]*nfor j in…

FSMC的NOR Flash/PSRAM 控制器功能介紹(STM32F4)

目錄 概述 1 FSMC支持的類型 1.1 信號類型概述 1.2 FSMC的應用 2 外部存儲器接口信號 2.1 I/O NOR Flash 2.2 PSRAM/SRAM 3 支持的存儲器和事務 4 通用時序規則 5 NOR Flash/PSRAM 控制器異步事務 5.1 模式 1 - SRAM/PSRAM (CRAM) 5.2 模式 A - SRAM/PSRAM (CRAM…

Golang | Leetcode Golang題解之第90題子集II

題目&#xff1a; 題解&#xff1a; func subsetsWithDup(nums []int) (ans [][]int) {sort.Ints(nums)n : len(nums) outer:for mask : 0; mask < 1<<n; mask {t : []int{}for i, v : range nums {if mask>>i&1 > 0 {if i > 0 && mask>&…

[HUBUCTF 2022 新生賽]ezsql

測試無結果 掃描目錄&#xff0c;得到源碼 找到注入點 思路&#xff1a;更新資料的時候可以同時更新所有密碼 我們需要知道密碼的字段名 爆庫 nicknameasdf&age111,description(select database())#&descriptionaaa&token31ad6e5a2534a91ed634aca0b27c14a9 爆表…

運維別卷系列 - 云原生監控平臺 之 08.prometheus grafana 實踐

文章目錄 [toc]部署 Grafana準備配置文件grafana.iniprovisioning/datasources/prometheus.yamlprovisioning/dashboards/dashboards.yamlprovisioning/dashboards/views 創建 svc創建 deployment Grafana 是一個圖形化界面&#xff0c;配置 Prometheus 作為數據源&#xff0c;…

網絡庫-POCO介紹

1.簡介 POCO C Libraries 提供一套 C 的類庫用以開發基于網絡的可移植的應用程序&#xff0c;它提供了許多模塊&#xff0c;包括網絡編程、文件系統訪問、線程和并發、數據庫訪問、XML處理、配置管理、日志記錄等功能。Poco庫的設計目標是易于使用、高度可定制和可擴展。 包含…

Postman的簡介,安裝,注冊。

一、安裝 1.Chrome應用商品搜索Postman安裝。(翻墻) 2.客戶端安裝官網地址:https://www.postman.com/downloads/ 3.Postman的注冊和登錄。 4.Postman的界面介紹 Home主頁 workspaces 工作空間 Collections 集合&#xff0c;項目集合。 Apis api文檔 EnViromments …

Oracle如何加密解密sha256

在Oracle數據庫中&#xff0c;您可以使用內建的加密函數或者通過PL/SQL擴展來實現SHA-256加密。但請注意&#xff0c;SHA-256是一個哈希算法&#xff0c;它主要用于生成數據的哈希值&#xff0c;而不是用于加密和解密數據。哈希算法是單向的&#xff0c;即它只能從原始數據生成…

基于MSWA相繼加權平均的交通流量分配算法matlab仿真

目錄 1.程序功能描述 2.測試軟件版本以及運行結果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 基于MSWA相繼加權平均的交通流量分配算法matlab仿真.如圖所示交通網絡中&#xff0c;包含6個節點、11各路段、9個OD對。經枚舉可得每個OD對間存在3條無折返有效路…