【Linux網絡-多路轉接select】

代碼:https://gitee.com/nanyi-c/linux/tree/master/day50

一、I/O多路轉接之select

1.初始select

系統提供select函數來實現多路復用輸入/輸出模型

  • select系統調用是用來讓我們的程序監視多個文件描述符的狀態變化的
  • 程序會停在select這里等待,直到被監視的文件描述符有一個或多個發生了狀態改變

2.select函數原型

select 是一個在 Unix 和類 Unix 操作系統中的系統調用,用于監控多個文件描述符,等待其中一個或多個文件描述符變得“就緒”。就緒可以意味著可讀、可寫或者發生異常

在這里插入圖片描述

參數說明

參數描述
nfds這是你監控的文件描述符集(readfds、writefds、exceptfds)中最高文件描述符的編號加1。簡單來說,它是監控的文件描述符范圍的上限
readfds輸入輸出型參數,只關心讀事件
writefds輸入輸出型參數,只關心寫事件
exceptfds輸入輸出型參數,只關心異常事件
timeout輸入輸出型參數,設置為 NULLselect 將無限期阻塞,直到至少有一個文件描述符就緒。如果 timeout 設置為非 NULL 值,它將在指定的秒數和微秒數后超時

在這里插入圖片描述

以下是 timeval 結構體的定義:

timeval結構用于描述一段時間長度,如果在這個時間內,需要監視的描述符沒有事件發生則發生函數返回,返回值為0

struct timeval {long    tv_sec;         /* seconds */long    tv_usec;        /* microseconds */
};

select 調用的返回值和含義如下:

  • 返回值大于0:表示就緒的文件描述符數量。輸入輸出型參數
  • 返回0:表示超時發生,沒有文件描述符就緒。
  • 返回-1:表示出錯,并且設置 errno 來指示錯誤類型。

錯誤值可能為:

  • EBADF 文件描述詞為無效的或該文件已關閉

  • EINTR 此調用被信號所中斷

  • EINVAL 參數n為負值

  • ENOMEM 核心內存不足

常見的程序片段如下:
fs_set readset;
FD_SET (fd, &readset);
select(fd+1, &readset, NULL, NULL, NULL) ;
if(FD_ISSET (fd, readse) ([....}

1.select要正常工作,需要借助一個輔助數組,來保存所有合法fd

2.每次使用都要重置

3.就緒了,循環檢測處理所有事件

關于fd_set結構

在Linux系統中,fd_set 是一個數據結構,用于表示一組文件描述符的集合。它通常與 select 系統調用一起使用,以便同時監控多個文件描述符的狀態(是否可讀、可寫或有異常發生)。

fd_set 是一個固定大小的位掩碼,其中每一位代表一個文件描述符。在內部,它通常是一個長整型數組,數組中的每個元素代表一定范圍內的文件描述符。由于 fd_set 的大小是固定的,所以它有一個最大文件描述符的限制,這個限制在 Linux 系統中通常是 FD_SETSIZE(通常定義為 1024)。

在這里插入圖片描述

常見宏操作

  • FD_ZERO(fd_set *set):將 fd_set 清零,即初始化 fd_set,使其不包含任何文件描述符。
  • FD_SET(int fd, fd_set *set):將指定的文件描述符 fd 添加到 fd_set 集合中。
  • FD_CLR(int fd, fd_set *set):從 fd_set 集合中移除指定的文件描述符 fd
  • FD_ISSET(int fd, fd_set *set):檢查指定的文件描述符 fd 是否在 fd_set 集合中。這個宏在 select 調用后使用,以確定哪些文件描述符已經就緒。

3.理解select執行過程

理解 select 模型的關鍵在于理解 fd_set,為說明方便,取 fd_set 長度為 1 字節,fd_set 中的每一 bit 可以對應一個文件描述符 fd,則 1 字節長的 fd_set 最大可以對應 8 個 fd。

  • 執行 fd_set set; FD_ZERO(&set); 則 set 用位表示是 0000,0000。
  • 若 fd=5,執行 FD_SET(fd,&set); 后 set 變為 0001,0000(第 5 位置為 1)。
  • 若再加入 fd=2,fd=1,則 set 變為 0001,0011。
  • 執行 select(6,&set,0,0,0) 阻塞等待。
  • 若 fd=1,fd=2 上都發生可讀事件,則 select 返回,此時 set 變為 0000,0011

注意 :沒有事件發生的 fd=5 被清空。

4.socket就緒條件

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

二、SelectServer.hpp

1.基礎框架

在這里插入圖片描述

2.設計Loop

在這里插入圖片描述

測試

每隔3s輪詢一次

在這里插入圖片描述

如果設置為nullptr,那么就永久阻塞式等待,直到有新鏈接

在這里插入圖片描述

無論哪種方式我們建立鏈接時,服務器會瘋狂輸出,這是因為我們還沒有對收到新鏈接后怎么做

如果事件就緒,但是不處理,select會一直通知我,直到我處理了

在這里插入圖片描述

我們重新設置一下

在這里插入圖片描述

此時便不會瘋狂輸出,還會顯示剩余時間

在這里插入圖片描述

時間就緒后就可以處理事件了,在rfds內

因為rfds是輸入輸出型參數,這里已經返回了哪些事已經就緒的

在這里插入圖片描述

處理事件

首先我們要判斷我們的文件描述符是不是就緒的,如果是,就可以建立連接了

在這里插入圖片描述

測試

在這里插入圖片描述

已經獲得了一個新的sockfd

接下來我們可以讀取嗎?絕對不能讀!讀取的時候,條件不一定滿足(建立連接–》不發請求,(底層沒有數據)讀的時候被阻塞,單進程絕對掛掉)

誰最清楚底層fd的數據是否就緒了呢??通過select!

想辦法把新的fd添加給select,由select統一進行監管。

select 為什么等待的fd會越來越多??

只要將新的fd,添加到fd_array中即可

初始化數組,并且把0號位給listen套接字

在這里插入圖片描述

重新設計Loop,并且找到最大的文件fd,使用for循環可以處理多個文件描述符,進行動態更新和確定最大文件描述符

在這里插入圖片描述

添加一個debug函數便于我們調試以及查看信息

在這里插入圖片描述

HandlerEvent函數負責檢測哪些文件描述符就緒,并根據它們是監聽套接字還是普通套接字來調用相應的處理函數。

處理新鏈接,并把新鏈接的fd添加到fd_array中

在這里插入圖片描述

處理普通fd就緒 進行IO

在這里插入圖片描述

測試

在這里插入圖片描述

三、select總結

小結:

  • select要正常工作,需要借助一個輔助數組,來保存所有合法fd
  • 每次使用都要重置
  • 就緒了,循環檢測處理所有事件

缺點

  • 每次調用 select,都需手動設置 fd 集合,從接口使用角度來說也非常不便。
  • 每次調用 select,都需要把 fd 集合從用戶態拷貝到內核態,這個開銷在 fd 很多時會很大。
  • 同時每次調用 select 都需要在內核遍歷傳遞進來的所有 fd,這個開銷在 fd 很多時也很大。
  • select 可監控的文件描述符數量太少。

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

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

相關文章

2025 年中國家電零售與創新趨勢解析:以舊換新國補激活需求,AI 技術滲透至研發、供應鏈、營銷

一、產業環境:政策驅動與技術變革下的挑戰與機遇 在全球經濟波動與國內消費轉型的雙重背景下,中國家電產業正經歷前所未有的變革。2024 年,家電行業面臨的 “三座大山”—— 短期消費信心低迷、中期房地產降溫、長期人口下行壓力 —— 持續施…

SpringBoot分布式項目中MyBatis實戰技巧:從配置到性能優化

引言 在分布式系統架構中,SpringBoot與MyBatis的組合已成為企業級開發的黃金搭檔。但在實際項目中,開發者常面臨多數據源管理、SQL性能優化、分布式事務等挑戰。本文將從實戰角度出發,分享7個關鍵技巧和避坑指南。 一、多數據源動態切換實戰…

【大模型基礎_毛玉仁】4.1 參數高效微調簡介

目錄 4 參數高效微調4.1 參數高效微調簡介4.1.1 下游任務適配1)上下文學習(In-context learning)2)指令微調(Instruction Tuning) 4.1.2 參數高效微調4.1.3 參數高效微調的優勢 4 參數高效微調 大語言模型…

Postman使用02、斷點、fiddler弱網測試

腳本操作 一、腳本導出 1.導出json腳本 2.打包json文件 3.下載的文件 二 .導入腳本 1.選擇文件 2.點擊導入 3.導入的接口 三.多接口運行 1.集合右鍵,點擊run ,運行多個接口 2.編輯環境,集合,執行次數等 3.運行多個接口 四.運行…

深挖增長內核:好產品驅動增長的全方位解析

年前在老板的帶領下深入學習了《增長黑客》,并思考了在CPS站外引流的落地方案,最近剛好在做京東聯盟的京粉推客增長體系建設,再次回顧一下增長黑客方法以及記錄一下思考。 好產品才是增長的根本。增長黑客理念風靡,“啊哈時刻” 概…

新手小白 react-useEffect 使用場景

useEffect 是 React 中的一個非常重要的 Hook,用于處理組件的副作用(side effects)。它通常在以下幾種場景中使用: 1. 數據獲取 當組件加載時,需要從外部 API 獲取數據,或者從本地存儲中讀取數據。示例&a…

MySQL 調優:查詢慢除了索引還能因為什么?

文章目錄 情況一:連接數過小情況二:Buffer Pool 太小 MySQL 查詢慢除了索引還能因為什么?MySQL 查詢慢,我們一般也會想到是因為索引,但除了索引還有哪些原因會導致數據庫查詢變慢呢? 以下以 MySQL 中一條 S…

【操作系統】進程三種狀態?進程間狀態的切換?掛起態?

進程狀態 進程的五種(三種)狀態: 新建(New):進程剛被創建,尚未加入到就緒隊列;就緒(Ready):進程已獲得除CPU外的所有資源,等待被調度執…

計算機控制系統的最小拍控制器設計及仿真分析

1題目 開環傳遞函數 G(s) 2/(s(0.5s1)) ,采樣周期 T0.5 秒,設計單位速度輸入下的最小拍控制器 1.1 方法1 根據課本中的步驟,最小拍控制器的設計步驟如下: 1. 確定對象的離散傳遞函數G(z),并確定其零極點。 2. 確定…

哈希--哈希桶

哈希桶是哈希表(散列表)中的一個概念,是哈希表數組中的每個元素 ,用于存儲鍵值對數據。它有以下特點和相關要點: 結構與原理:哈希表底層常由數組構成,數組的每個元素即哈希桶。通過哈希函數計算…

Linux多線程詳解

Linux多線程詳解 一、Linux多線程概念1.1 什么是線程1.2 進程和線程1.3 進程的多個線程共享1.4 進程和線程的關系 二、Linux線程控制2.1 POSIX線程庫2.2 線程創建2.3 獲取線程ID pthread_self2.4 線程等待pthread_join2.5 線程終止2.6 線程棧 && pthread_t2.7 線程的局…

Midscene.js自然語言驅動的網頁自動化全指南

一、概述 網頁自動化在數據抓取、UI 測試和業務流程優化中發揮著重要作用。然而,傳統工具如 Selenium 和 Puppeteer 要求用戶具備編程技能,編寫復雜的選擇器和腳本維護成本高昂。Midscene.js 通過自然語言接口革新了這一領域,用戶只需描述任…

winstart.wsf 病毒清理大作戰

0x00 背景 發現感染了winstart.wsf 病毒如何清理。 0x01 現象 遍歷Users下每個目錄以及C:\和C:\Windows\Temp 2個目錄寫入病毒文件。 C:\Users\Administrator\AppData\Local\Temp\winstart.wsf C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Start Menu\Program…

多路轉接Poll

在之前我們講過select是最古老的多路轉接方案,古老就意味著他不是很方便使用,他需要用戶手動保存fd_set這個位圖結構,來表示讀寫事件的關注與否或者就緒性。 而且由于fd_set的大小是固定的,這就意味著他能管理的套接字文件描述符是…

多層感知機的簡潔實現

《動手學深度學習》-4.3-筆記 import torch from torch import nn from d2l import torch as d2l 導入必要的庫和模塊 net nn.Sequential(nn.Flatten(),nn.Linear(784, 256),nn.ReLU(),nn.Linear(256, 10))def init_weights(m):if type(m) nn.Linear:nn.init.normal_(m.we…

【GoLang】調用llm時提示詞prompt的介紹以及使用方式

介紹 提示詞是一種與大模型交互的對話格式,它以 JSON 格式定義了一個消息列表(messages),包含了系統消息和用戶消息。 我們向AI提問時,其實發給AI的都是提示詞,別看我們只是簡單輸入了一句話,…

內核編程十二:打印task_struct中的數據

在Linux內核中,current 是一個宏,用于獲取當前正在執行的進程的 task_struct 結構體指針。current 宏返回一個指向當前正在運行的進程的 task_struct 結構體的指針。通過這個指針,內核代碼可以訪問和修改當前進程的各種屬性和狀態。 打印單個…

區間端點(java)(貪心問題————區間問題)

deepseek給了一種超級簡單的做法 我是真的想不到 貪心的思路是 局部最優——>全局最優 這種我是真的沒有想到,這樣的好處就是后面便利的時候可以通過foreach循環直接便利qu的子元素也就是對應的某一個區間, 將一個二維數組變成一維數組,每一個一維…

Qt事件處理(處理鼠標事件、鍵盤事件、定時器事件、窗口移動和大小變化事件)

事件處理 事件是應用程序內部或者外部產生的事情或者動作的統稱。 在 Qt 中,事件是用一個對象來管理一個事件的。所有的事件對象都繼承自抽象類 QEvent 。事件包括鼠標事件、鍵盤事件等,發出自 Qt 或操作系統本身。 處理事件一般通過重寫相關的 Event 函…

Apache Hive:基于Hadoop的分布式數據倉庫

Apache Hive 是一個基于 Apache Hadoop 構建的開源分布式數據倉庫系統,支持使用 SQL 執行 PB 級大規模數據分析與查詢。 主要功能 Apache Hive 提供的主要功能如下。 HiveServer2 HiveServer2 服務用于支持接收客戶端連接和查詢請求。 HiveServer2 支持多客戶端…