Linux が select を使用する理由は何ですか?
select 関数を使用すると、開発者は複数のファイル バッファを同時に待機できるため、IO 待機時間が短縮され、プロセスの IO 効率が向上します。 select() 関数は、プログラムが複数のファイル記述子を監視し、監視されている 1 つ以上のファイル記述子が「準備完了」になるのを待機できるようにする IO 多重化関数です。いわゆる「準備完了」状態とは、ファイルを指します。記述子はブロックされなくなり、読み取り可能、書き込み可能、例外を含む特定の種類の IO 操作に使用できるようになりました。
#include
1. select 関数の概要
select 関数は IO 多重化関数であり、その主な機能はファイル記述子のイベントの準備が完了するのを待つことです。 , select を使用すると、複数のファイル バッファーを同時に待機できるようになり、IO 待機時間が短縮され、プロセスの IO 効率が向上します。
select() 関数を使用すると、プログラムは複数のファイル記述子を監視し、監視されている 1 つ以上のファイル記述子が「準備完了」になるまで待機できます。いわゆる「準備完了」状態とは、ファイル記述子がブロッキング状態ではなくなり、読み取り可能、書き込み可能、例外の発生など、特定のタイプの IO 操作に使用できることを意味します
#2. 関数パラメータの選択の概要 int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
ログイン後にコピー
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
ndfs
待機中のファイル記述子の最大値は 1 です。たとえば、アプリケーション プロセスは次のようにします。ファイルを待ちます。記述子 3、5、および 8 のイベントの場合、nfds=max(3,5,8)+1;
fd_set タイプ
readfds および writefds は、fds タイプを除いてすべて fd_set です。 fd_set タイプですか?fd_set タイプは本質的にビットマップ です。ビットマップの位置は対応するファイル記述子を示し、内容はファイル記述子が有効かどうかを示します。1 はファイル記述子を表しますその場所のファイル記述子は有効です。0 はその場所のファイル記述子が無効であることを意味します。
- ファイル記述子 2 と 3 がビットマップに設定されている場合、ビットマップは 1100 を表します。
- fd_set の上限は 1024 ファイル記述子です。
readfds
- readfds は、読み取りイベント
を待機しているファイル記述子の コレクションです。 if 読み取りイベントを気にしない場合 (バッファーにデータがある場合)、NULL 値を渡すことができます。
- アプリケーション プロセスとカーネルの両方で readfds を設定できます。アプリケーション プロセスは、readfds でファイル記述子の読み取りイベントを待つようにカーネルに通知するために、readfds を設定します。そして
カーネル readfds の設定はどの読み取りイベントが有効になるかをアプリケーション プロセスに指示するためのものです
readfds と同様に、writefds は書き込みイベント (バッファーにスペースがあるかどうか) を待機するコレクションです。書き込みイベントを気にしない場合は、値 NULL を渡すことができます。
excelfdsカーネルが対応するファイル記述子を待機し、例外
が発生した場合、失敗したファイル記述子をExceptfdsに設定します。 、エラー イベントを気にしない場合は、値 NULL を渡すことができます。 timeout
カーネル内の時間選択ブロックを設定します。非ブロッキングに設定したい場合は、NULL に設定します。 select を 5 秒間ブロックする場合は、struct timeval time={5,0}
;struct timeval の構造タイプは次のとおりです:
struct timeval { long tv_sec; /* seconds */ long tv_usec; /* microseconds */ };
戻り値
ファイル記述子の準備ができていない場合は 0 を返します。
- #呼び出しが失敗した場合は - を返します。 1;
- readfds でタイムアウト中にイベントが発生した場合、タイムアウトの残り時間が返されます。
- 3.ワークフローの選択
アプリケーション プロセス
とkernel の両方で readfds と writefds が必要ですその中で、カーネルは、どのファイル記述子が readfds と writefds から待機する必要があるかを知る必要があり、アプリケーション プロセスは、どのファイル記述子イベントが readfds と writefds から準備ができているかを知る必要があります。 ファイル記述子を継続的にポーリングして待機する場合、アプリケーション プロセスは常に readfds と writefds をリセットする必要があります。これは、select が呼び出されるたびに、カーネルが readfds と writefds を変更するため、 Application
Medium配列
selected が呼び出されたときに、readfds と writefds が次のようになることを確認します。
4.Select服务器
如果是一个select服务器进程,则服务器进程会不断的接收有新链接,每个链接对应一个文件描述符,如果想要我们的服务器能够同时等待多个链接的数据的到来,我们监听套接字listen_sock读取新链接的时候,我们需要将新链接的文件描述符保存到read_arrys数组中,下次轮询检测的就会将新链接的文件描述符设置进readfds中,如果有链接关闭,则将相对应的文件描述符从read_arrys数组中拿走。
一张图看懂select服务器:
简易版的select服务器:
server.hpp文件:
#pragma once #include<iostream> #include<sys/socket.h> #include<sys/types.h> #include<netinet/in.h> #include<string.h> using std::cout; using std::endl; #define BACKLOG 5 namespace sjp{ class server{ public: static int Socket(){ int sock=socket(AF_INET,SOCK_STREAM,0); if(sock>0) return sock; if(sock<0) exit(-1); W> } static bool Bind(int sockfd,short int port){ struct sockaddr_in lock; memset(&lock,'\0',sizeof(lock)); lock.sin_family=AF_INET; lock.sin_port=htons(port); lock.sin_addr.s_addr=INADDR_ANY; if(bind(sockfd,(struct sockaddr*)&lock,(socklen_t)sizeof(lock))<0){ exit(-2); } return true; } static bool Listen(int sockfd){ if(listen(sockfd,BACKLOG)<0){ exit(-3); } return true; } }; }
select_server.hpp文件
#pragma once #include<vector> #include"server.hpp" #include<unistd.h> #include<time.h> namespace Select{ class select_server{ private: int listen_sock;//监听套接字 int port; public: select_server(int _port):port(_port){} //初始化select_server服务器 void InitServer(){ listen_sock=sjp::server::Socket(); sjp::server::Bind(listen_sock,port); sjp::server::Listen(listen_sock); } void Run(){ std::vector<int> readfds_arry(1024,-1);//readfds_arry保存读事件的文件描述符 readfds_arry[0]=listen_sock;//将监听套接字保存进readfds_arry数组中 fd_set readfds; while(1){ FD_ZERO(&readfds); int nfds=0; //将read_arry数组中的文件描述符设置进程readfds_arry位图中 for(int i=0;i<1024;i++) { if(readfds_arry[i]!=-1){ FD_SET(readfds_arry[i],&readfds); if(nfds<readfds_arry[i]){ nfds=readfds_arry[i]; } } } //调用select对readfds中的文件描述符进行等待数据 switch(select(nfds+1,&readfds,NULL,NULL,NULL)){ case 0: //没有一个文件描述符的读事件就绪 cout<<"select timeout"<<endl; break; case -1: //select失败 cout<<"select error"<<endl; default: { //有读事件发生 Soluation(readfds_arry,readfds); break; } } } } void Soluation(std::vector<int>& readfds_arry,fd_set readfds){ W> for(int i=0;i<readfds_arry.size();i++){ if(FD_ISSET(readfds_arry[i],&readfds)) { if(readfds_arry[i]==listen_sock){ //有新链接到来 struct sockaddr peer; socklen_t len; int newfd=accept(listen_sock,&peer,&len); cout<<newfd<<endl; //将新链接设置进readfds_arry数组中 AddfdsArry(readfds_arry,newfd); } else{ //其他事件就绪 char str[1024]; int sz=recv(readfds_arry[i],&str,sizeof(str),MSG_DONTWAIT); switch(sz){ case -1: //读取失败 cout<<readfds_arry[i]<<": recv error"<<endl; break; case 0: //对端关闭 readfds_arry[i]=-1; cout<<"peer close"<<endl; break; default: str[sz]='\0'; cout<<str<<endl; break; } } } } } void AddfdsArry(std::vector<int>& fds_arry,int fd){ W> for(int i=0;i<fds_arry.size();i++){ if(fds_arry[i]==-1){ fds_arry[i]=fd; break; } } } }; }
select_server.cc文件
#include"select_server.hpp" int main(int argv,char* argc[]){ if(argv!=2){ cout<<"./selectserver port"<<endl; exit(-4); } int port=atoi(argc[1]);//端口号 Select::select_server* sl=new Select::select_server(port); sl->InitServer(); sl->Run(); }
测试:
5.Select的缺陷
由于fd_set的上限是1024,所以select能等待的读事件的文件描述符和写事件的文件描述是有上限的,如果作为一个大型服务器,能够同时链接的客户端是远远不够的。
每次应用进程调用一次select之前,都需要重新设定writefds和readfds,如果进行轮询调用select,这对影响cpu效率。
内核每一次等待文件描述符 都会重新扫描所有readfds或者writefds中的所有文件描述符,如果有较多的文件描述符,则会影响效率。
以上がLinux が select を使用する理由は何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









LinuxターミナルでPythonバージョンを表示する際の許可の問題の解決策PythonターミナルでPythonバージョンを表示しようとするとき、Pythonを入力してください...

エラーの原因とソリューションPECLを使用してDocker環境に拡張機能をインストールする場合、Docker環境を使用するときに、いくつかの頭痛に遭遇します...

多くのウェブサイト開発者は、ランプアーキテクチャの下でnode.jsまたはPythonサービスを統合する問題に直面しています:既存のランプ(Linux Apache MySQL PHP)アーキテクチャWebサイトのニーズ...

nginと同様に、APSChedulerタイミングタスクをサービスとして構成する場合、APSChedulerタイミングタスクをMACOSプラットフォームでサービスとして構成します...

言語のマルチスレッドは、プログラムの効率を大幅に改善できます。 C言語でマルチスレッドを実装する4つの主な方法があります。独立したプロセスを作成します。独立して実行される複数のプロセスを作成します。各プロセスには独自のメモリスペースがあります。擬似マルチスレッド:同じメモリ空間を共有して交互に実行するプロセスで複数の実行ストリームを作成します。マルチスレッドライブラリ:pthreadsなどのマルチスレッドライブラリを使用して、スレッドを作成および管理し、リッチスレッド操作機能を提供します。 Coroutine:タスクを小さなサブタスクに分割し、順番に実行する軽量のマルチスレッド実装。

Linux Systemsに付属するPythonインタープリターを削除する問題に関して、多くのLinuxディストリビューションは、インストール時にPythonインタープリターをプリインストールし、パッケージマネージャーを使用しません...

web.xmlファイルを開くには、次の方法を使用できます。テキストエディター(メモ帳やテキストエディットなど)を使用して、統合開発環境(EclipseやNetBeansなど)を使用してコマンドを編集できます(Windows:Notepad web.xml; Mac/Linux:Open -A Textedit Web.xml)
