


Apakah sebab mengapa Linux menggunakan pilih?
Menggunakan fungsi pilih membolehkan pembangun menunggu berbilang penimbal fail pada masa yang sama, dengan itu mengurangkan masa menunggu IO dan meningkatkan kecekapan IO proses. Fungsi select() ialah fungsi pemultipleksan IO yang membolehkan program memantau berbilang deskriptor fail dan menunggu satu atau lebih deskriptor fail yang dipantau menjadi "sedia" yang dipanggil keadaan "bersedia" ialah Merujuk kepada: fail deskriptor tidak lagi disekat dan boleh digunakan untuk jenis operasi IO tertentu, termasuk boleh dibaca, boleh ditulis dan pengecualian.
#include
1. Pengenalan untuk memilih fungsi
Fungsi pilih ialah fungsi pemultipleksan IO adalah untuk menunggu acara dalam deskriptor fail siap. , pilih boleh membolehkan kami menunggu beberapa penimbal fail pada masa yang sama, mengurangkan masa menunggu IO dan meningkatkan kecekapan IO proses.
Fungsi select() membenarkan program memantau berbilang deskriptor fail dan menunggu satu atau lebih deskriptor fail yang dipantau menjadi "sedia". Keadaan yang dipanggil "sedia" bermaksud bahawa deskriptor fail tidak lagi disekat dan boleh digunakan untuk jenis operasi IO tertentu, termasuk boleh dibaca, boleh ditulis dan pengecualian
2 untuk memilih parameter fungsi
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
ndfs
Nilai maksimum deskriptor fail menunggu +1, contohnya: proses permohonan mahu menunggu Untuk acara daripada deskriptor fail 3, 5 dan 8,
nfds=max(3,5,8)+1;
jenis set_fd ialah
jenis readfds dan writefds, exceptfds adalah kedua-duanya fd_set, jadi apakah fd_set taip?
Jenis fd_set pada asasnya ialah bitmap Kedudukan bitmap menunjukkan deskriptor fail yang sepadan dan kandungannya menunjukkan sama ada deskriptor fail adalah sah Deskriptor fail di lokasi adalah sah, 0 bermakna deskriptor fail di lokasi tidak sah.
Jika deskriptor fail 2 dan 3 ditetapkan dalam peta bit, peta bit mewakili 1100.
Had atas fd_set ialah 1024 deskriptor fail.
readfds
readfds ialah set deskriptor fail menunggu acara baca Jika Jika anda tidak mengambil berat tentang acara baca (terdapat data dalam penimbal), anda boleh lulus nilai NULL.
Kedua-dua proses aplikasi dan kernel boleh menetapkan readfds Proses permohonan menetapkan readfds untuk memberitahu kernel untuk menunggu acara baca deskriptor fail dalam readfds kernel tetapan readfds ialah untuk memberitahu proses permohonan yang mana acara bacaan berkuat kuasa
writefds
Sama seperti readfds, writefds ialah koleksi menunggu acara tulis (sama ada ruang dalam penimbal Jika anda tidak mengambil berat tentang acara tulis, anda boleh melepasi nilai NULL).exceptfds
Jikapengecualian berlaku semasa kernel sedang menunggu deskriptor fail yang sepadan, maka menetapkan deskriptor fail yang gagal menjadi exceptfds , jika anda tidak mengambil berat tentang peristiwa ralat, anda boleh melepasi nilai NULL.
masa tamat
Tetapkan masa apabila pilih blok dalam kernel Jika anda ingin menetapkannya kepada bukan sekatan, tetapkannya kepada NULL. Jika anda ingin memilih untuk menyekat selama 5 saat, anda akan menciptamasa struct timeval={5,0};
di mana jenis struktur struct timeval ialah:struct timeval { long tv_sec; /* seconds */ long tv_usec; /* microseconds */ };
Nilai pulangan
- Jika tiada deskriptor fail sedia, kembalikan 0; -1;
- Jika peristiwa berlaku dalam readfds dalam tamat masa, baki masa tamat masa dikembalikan.
3.pilih aliran kerja
Kedua-dua proses permohonan dan kernel
perlu membacafds dan writefds untuk mendapatkan maklumat. Antaranya, kernel perlu mengetahui deskriptor fail mana yang perlu menunggu dari readfds dan writefds, dan proses permohonan perlu mengetahui peristiwa deskriptor fail yang sedia dari readfds dan writefds >Sekiranya kita ingin terus meninjau dan menunggu deskriptor fail, proses permohonan perlu sentiasa menetapkan semula readfds dan writefds, kerana setiap kali pilih dipanggil, kernel akan mengubah suai readfds dan writefds, jadi kita perlu aplikasi Tetapkan tatasusunan
dalam untuk menyimpan deskriptor fail yang perlu ditunggu oleh program Pastikan apabila pilih dipanggil, readfds dan writefds akan menjadi seperti berikut. :
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中的所有文件描述符,如果有较多的文件描述符,则会影响效率。
Atas ialah kandungan terperinci Apakah sebab mengapa Linux menggunakan pilih?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas



Penyelesaian kepada Isu Kebenaran Semasa Melihat Versi Python di Terminal Linux Apabila anda cuba melihat versi Python di Terminal Linux, masukkan Python ...

Bitget adalah pertukaran cryptocurrency yang menyediakan pelbagai perkhidmatan perdagangan termasuk perdagangan tempat, perdagangan kontrak dan derivatif. Ditubuhkan pada tahun 2018, pertukaran itu beribu pejabat di Singapura dan komited untuk menyediakan pengguna dengan platform perdagangan yang selamat dan boleh dipercayai. Bitget menawarkan pelbagai pasangan perdagangan, termasuk BTC/USDT, ETH/USDT dan XRP/USDT. Di samping itu, pertukaran mempunyai reputasi untuk keselamatan dan kecairan dan menawarkan pelbagai ciri seperti jenis pesanan premium, perdagangan leverage dan sokongan pelanggan 24/7.

Bagaimana untuk menetapkan keizinan UnixSocket secara automatik selepas sistem dimulakan semula. Setiap kali sistem dimulakan semula, kita perlu melaksanakan perintah berikut untuk mengubahsuai keizinan UnixSocket: sudo ...

Gate.io adalah pertukaran cryptocurrency yang popular yang boleh digunakan pengguna dengan memuat turun pakej pemasangannya dan memasangnya pada peranti mereka. Langkah -langkah untuk mendapatkan pakej pemasangan adalah seperti berikut: Lawati laman web rasmi Gate.io, klik "Muat turun", pilih sistem operasi yang sepadan (Windows, Mac atau Linux), dan muat turun pakej pemasangan ke komputer anda. Adalah disyorkan untuk mematikan perisian antivirus atau firewall sementara semasa pemasangan untuk memastikan pemasangan yang lancar. Selepas selesai, pengguna perlu membuat akaun Gate.io untuk mula menggunakannya.

Ouyi Okx, pertukaran aset digital terkemuka di dunia, kini telah melancarkan pakej pemasangan rasmi untuk menyediakan pengalaman perdagangan yang selamat dan mudah. Pakej pemasangan OKX OUYI tidak perlu diakses melalui penyemak imbas. Proses pemasangan adalah mudah dan mudah difahami.

Punca dan penyelesaian untuk kesilapan Apabila menggunakan PECL untuk memasang sambungan dalam persekitaran Docker Apabila menggunakan persekitaran Docker, kami sering menemui beberapa sakit kepala ...

Ramai pemaju laman web menghadapi masalah mengintegrasikan perkhidmatan node.js atau python di bawah seni bina lampu: lampu sedia ada (Linux Apache MySQL PHP) Laman web seni bina memerlukan ...

Menggunakan Python di Terminal Linux ...
