目次
1. select 関数の概要
ndfs
fd_set タイプ
readfds
readfds と同様に、writefds は書き込みイベント (バッファーにスペースがあるかどうか) を待機するコレクションです。書き込みイベントを気にしない場合は、値 NULL を渡すことができます。
カーネルが対応するファイル記述子を待機し、例外
カーネル内の時間選択ブロックを設定します。非ブロッキングに設定したい場合は、NULL に設定します。 select を 5 秒間ブロックする場合は、struct timeval time={5,0}
アプリケーション プロセス
4.Select服务器
5.Select的缺陷
ホームページ 運用・保守 Linuxの運用と保守 Linux が select を使用する理由は何ですか?

Linux が select を使用する理由は何ですか?

May 19, 2023 pm 03:07 PM
linux select

select 関数を使用すると、開発者は複数のファイル バッファを同時に待機できるため、IO 待機時間が短縮され、プロセスの IO 効率が向上します。 select() 関数は、プログラムが複数のファイル記述子を監視し、監視されている 1 つ以上のファイル記述子が「準備完了」になるのを待機できるようにする IO 多重化関数です。いわゆる「準備完了」状態とは、ファイルを指します。記述子はブロックされなくなり、読み取り可能、書き込み可能、​​例外を含む特定の種類の IO 操作に使用できるようになりました。

#includeヘッダー ファイルには、コンピューターで呼び出すことができる select 関数が含まれています。この関数は、ファイル記述子の変更 (読み取り、書き込み、または例外) を監視するために使用されます。

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);
ログイン後にコピー

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 の設定はどの読み取りイベントが有効になるかをアプリケーション プロセスに指示するためのものです

Linux が select を使用する理由は何ですか?

##writefds

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

配列 Linux が select を使用する理由は何ですか?

を設定して、プログラムが待機する必要があるファイル記述子を保存します。

selected が呼び出されたときに、readfds と writefds が次のようになることを確認します。

4.Select服务器

如果是一个select服务器进程,则服务器进程会不断的接收有新链接,每个链接对应一个文件描述符,如果想要我们的服务器能够同时等待多个链接的数据的到来,我们监听套接字listen_sock读取新链接的时候,我们需要将新链接的文件描述符保存到read_arrys数组中,下次轮询检测的就会将新链接的文件描述符设置进readfds中,如果有链接关闭,则将相对应的文件描述符从read_arrys数组中拿走。

一张图看懂select服务器:

Linux が 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,&#39;\0&#39;,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]=&#39;\0&#39;;
                    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();                                                                                                   
}
ログイン後にコピー

测试:

Linux が select を使用する理由は何ですか?

Linux が select を使用する理由は何ですか?

5.Select的缺陷

  • 由于fd_set的上限是1024,所以select能等待的读事件的文件描述符和写事件的文件描述是有上限的,如果作为一个大型服务器,能够同时链接的客户端是远远不够的。

  • 每次应用进程调用一次select之前,都需要重新设定writefds和readfds,如果进行轮询调用select,这对影响cpu效率。

  • 内核每一次等待文件描述符 都会重新扫描所有readfds或者writefds中的所有文件描述符,如果有较多的文件描述符,则会影响效率。

以上がLinux が select を使用する理由は何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

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

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

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

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

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

LinuxターミナルでPythonバージョンを表示するときに発生する権限の問題を解決する方法は? LinuxターミナルでPythonバージョンを表示するときに発生する権限の問題を解決する方法は? Apr 01, 2025 pm 05:09 PM

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

Docker環境にPECLを使用して拡張機能をインストールするときにエラーが発生するのはなぜですか?それを解決する方法は? Docker環境にPECLを使用して拡張機能をインストールするときにエラーが発生するのはなぜですか?それを解決する方法は? Apr 01, 2025 pm 03:06 PM

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

ランプアーキテクチャの下でnode.jsまたはPythonサービスを効率的に統合する方法は? ランプアーキテクチャの下でnode.jsまたはPythonサービスを効率的に統合する方法は? Apr 01, 2025 pm 02:48 PM

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

APSChedulerタイミングタスクをMACOSのサービスとして構成する方法は? APSChedulerタイミングタスクをMACOSのサービスとして構成する方法は? Apr 01, 2025 pm 06:09 PM

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

マルチスレッドをC言語で実装する4つの方法 マルチスレッドをC言語で実装する4つの方法 Apr 03, 2025 pm 03:00 PM

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

PythonインタープリターはLinuxシステムで削除できますか? PythonインタープリターはLinuxシステムで削除できますか? Apr 02, 2025 am 07:00 AM

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

web.xmlを開く方法 web.xmlを開く方法 Apr 03, 2025 am 06:51 AM

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

See all articles