当前位置:网站首页>Multiplexer select
Multiplexer select
2022-06-24 21:44:00 【Programming rookie】
- understand 5 Kind of IO Basic concepts of the model , The key is IO Multiplex .
- master select Programming model , Can achieve select Version of TCP The server .
- master poll Programming model , Can achieve poll Version of TCP The server .
- master epoll Programming model , Can achieve epoll Version of TCP The server .
- understand epoll Of LT Patterns and ET Pattern .
- understand select and epoll Compare the advantages and disadvantages of .
Five kinds IO Model
When we want to read and write data , The buffer may not have data , So we may have to wait , Wait until the data is ready , Then perform read / write operations .
IO = wait for + Copy .
read IO = Wait for the read event to be ready + Copy data from the kernel to the user's receive buffer .
Write IO = Wait for the write event to be ready + Copy data from user space to the kernel's send buffer .
- senior IO, Is efficient IO. actually , Only the data copy process is right IO Contribute , The process of waiting is right IO There is no contribution .
- Efficient IO The essence is , Try to reduce the proportion of etc !!
Little chestnut :
Fishing is divided into two steps : wait for + fishing .
- Zhang San : Zhangsan goes fishing , He watched the fish drift , Until the fish bite .
- Li Si : Lisi is holding a fishing rod in his left hand , Hold it in your right hand 《effectiveC++》, He read for a while , Just take a look at the fish drift to see if there is any fish on the hook , Then read a book . Lisi cycle this process .
- Wang Wu : Wang Wu hung a bell on the top of the fishing rod , Then I kept looking at my cell phone . As long as the bell rings , Wang wucai finished .
- Zhao Liu : Zhao Liu is a small local tyrant , Pulling a truck of fishing rods , Probably 100 about . Zhao liuzai 100 A fishing rod hovers around , As long as one of the fishing rods moves , Go fishing . Zhao Liu polled and tested the fishing rod .
- Panax notoginseng : Tianqi is a real rich man , He wants to eat fish , Let his driver Xiao Li go fishing . Tianqi went straight away , When Xiao Liu catches a lot of fish , Just call Tianqi .
front 4 Ways of planting , Waiting for your own way to fish , It's called synchronization IO.
Tianqi's fishing method , Tianqi is just IO The initiator of the , Xiao Liu did the act of fishing , This is called asynchronous IO.
select,poll,epoll Only responsible for IO Waiting in the middle .
Blocking IO
- Zhang San's fishing method is blocking IO Model .
- If the kernel does not prepare the data , Then the system calls will always be blocked . All sockets , The default is blocking .

Non blocking IO
- Li Si uses non blocking IO Model .
- If the kernel has not prepared the data yet , The system call will still return directly , And back to EWOULDBLOCK Error code .
- Non blocking IO It often requires programmers to repeatedly try to read and write file descriptors in a circular way , This process is called polling . This is right CPU It's a big waste , Generally, it is only used in specific scenes .

Signal driven IO
- Wang Wu uses signal drive IO.
- encounter IO When , The process continues . When the kernel data is ready , The system notifies the process ( Sending signal SIGIO,29 Sign no. ) To copy data .
- The way of system notification is generally signal .
- When the operating system receives data , Will send... To the target process SIGIO,SIGIO By default, the execution action of is ignored . So we need to establish signal Processing function of .

Multiplex
- Zhao Liu uses multi-channel transfer , Also called multiplexing .
- I call it blocking IO Advanced version of (doge).
- The core of multiplexing is IO Multiplexing can wait for the ready status of multiple file descriptors at the same time .
- Multiplexing is only responsible for one thing , Is waiting for !!

asynchronous IO
- Tianqi uses asynchronous IO.
- When the kernel sends data copy complete when , Inform the process .( Signal driving is waiting for completion , Just notify the process .) And the process is always running .

Summary :
- whatever IO In the process , Both involve two steps . The first is the wait for , The second is Copy . And in the actual application scenario , The waiting time is often much longer than the copy time . Give Way IO More efficient , The core method is to minimize the waiting time .
senior IO Important concepts
Synchronous communication vs asynchronous communication
- In a word , stay IO Kind of , Own participation IO It's called synchronization IO.
- What you don't need to participate in is asynchronous IO.
- The synchronization here is completely different from that of multithreading !! Therefore, when searching for synchronization, you must clearly state the background .
Blocking vs Non blocking
Blocking waiting is before the call returns the result , Thread will be suspended ;
Nonblocking is the immediate return of the call , Does not affect thread execution .
Non blocking IO
The default wait mode for file descriptors is blocking wait . But we can manually set it to non blocking wait . We use fcntl function .
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, … /* arg */ );
- The first parameter fd Represents the file descriptor you want to set .
- cmd It means that you have to pay attention to this fd Actions performed ,cmd Different , The following variable parameters are different .
- fcntl Functions have many functions , Here are the modifications fd Is a non blocking method .
/********* Change the standard input to non blocking ********/
1 #include <stdio.h>
2 #include <fcntl.h>
3 #include <unistd.h>
4 #include <errno.h>
5 #include <stdlib.h>
6 void SetNoBlock(int fd){
7 int fl = fcntl(fd, F_GETFL);
8 if(fl < 0){
9 printf("fcntl error\n");
10 exit(1);
11 }
12
13 fcntl(fd, F_SETFL, fl | O_NONBLOCK);
14
15 }
16
17 int main(){
18 SetNoBlock(0);
19 char ch = '\0';
20 for(;;){
21 sleep(1);
22 ssize_t s = read(0, &ch, sizeof(ch)); // There is a research pole BUG!! hold ssize_t Change to size_t after , There will be errors ! I suspect that it is because of forced conversion !
23
24 if(s > 0){
25 printf("%c\n", ch);
26 }
27 else if(s < 0 && errno == EAGAIN){
28 printf("read conditon not ok\n");
29 }
30
31 else{
32 printf("read error\n");
33 exit(2);
34 }
35
36 printf("................\n");
37 }
38 }
Multiplexer select
- select The function of is a word , etc. .
- select You can wait for multiple file descriptors at the same time , This is equivalent to parallel , It improves the efficiency of single process server .
Function introduction :
- nfds Is the largest file descriptor you want to relate to +1.
- The first 2,3,4 Parameters correspond to read events , A collection of write events and exception events .
- The last parameter is a timeval The parameters of type .
fd_set:
- fd_set Is a bitmap . It is both an input parameter and an output parameter .
- As input parameter , Indicates that the process tells the operating system which file descriptors to relate . The subscript of each bit of the bitmap represents the file descriptor , And everyone's content (0 perhaps 1) Represents whether you care about the file descriptor .
- As an output parameter , Indicates that the operating system tells the process which file descriptors are ready . The subscript of each bit of the bitmap represents the file descriptor , The content of each bit indicates whether it is ready .
- The bits set in the output bitmap must be in the bits you care about . It's impossible that you don't care 3 File descriptor No , And back 3 Number is ready !
- And because it's a bitmap , So the system also has a series of interfaces to use it :
void FD_CLR(int fd, fd_set *set); // Used to clear descriptive phrases set Middle correlation fd Bit
int FD_ISSET(int fd, fd_set *set); // Used to test descriptive phrases set Middle correlation fd Whether or not the bit is true
void FD_SET(int fd, fd_set *set); // Used to set the description phrase set Middle correlation fd Bit
void FD_ZERO(fd_set *set); // Used to clear descriptive phrases set The whole part of
timeval:
- timeval It's a structure , Used to describe a period of time .select Block waiting during this time .

- Be careful !!!timeout Is an input parameter , It's also an output parameter !
- Input means you want to select The waiting time for blocking . and timeout It will be cleared during output !
timeout The value of :
- Specific time values : Show that you want to select The waiting time for blocking , After that time ,select Timeout returns . There are file descriptors ready during this time ,select And will return to .
- NULL: Show that you want to select Block waiting . Until a file descriptor is ready .
- 0: Indicates non blocking wait . Only the state of the descriptor set is detected , Then immediately return to , Don't wait for external events to happen .
Return value :
- Integer numbers greater than zero : Indicates the number of ready file descriptors .
- be equal to 0: Overtime , No file descriptor is ready .
- Less than 0:select error ! For example, a file descriptor has been closed , And you are still waiting .
socket Ready conditions
Read ready
- socket The kernel , The number of bytes in the receive buffer , Greater than or equal to the low water mark SO_RCVLOWAT( It is not a receive buffer as long as there is data , Just read it right away , Instead, a low water mark is set , In order to ensure the efficiency of reading ). At this time, the file descriptor can be read without blocking , And the return value is greater than 0;
- socket TCP In communication , Close the connection end to end , It's time to socket read , Then return to 0;
- Monitoring socket There are new connection requests on , This request is reported to the operating system as a read event ;
- socket There is an unhandled error on ;
Write ready
- socket The kernel , The number of bytes available in the send buffer ( The size of the free location of the send buffer ), Greater than or equal to the low water mark SO_SNDLOWAT, You can write without blocking , And the return value is greater than 0;
- socket Write operations for are turned off (close perhaps shutdown). For a write that is turned off socket Write operation , Will trigger SIGPIPE The signal ;
- socket Use non blocking connect After a successful or unsuccessful connection ;
- socket There are unread errors on ;
select Also consider the upper layer agreement
- because select Yes, as long as the read characters are redundant, the watermark will be returned , So you are in the application layer ( such as http The server ) When reading , Maybe only a part of it is read http package , Then you need to do it yourself in your code . such as ,http When the package is incomplete , Put it in storage , Continue to put the file descriptor in select Waiting in the , Until you read a complete http message , Redelivery to select To wait for the write event to be ready .
select Code
- Our idea is to make the receiving connection read and wait , And processing data (recv) The time of reading waits for all to be handed over to select To deal with it . This is efficient , It can also realize the parallel processing of multiple requests by a single process .
/************ sock.hpp **************/
#pragma once
2
3 #include <iostream>
4 #include <string>
5 #include <unistd.h>
6 #include <sys/types.h>
7 #include <sys/socket.h>
8 #include <netinet/in.h>
9 #include <cstring>
10 #define LOGBACK 5
11 using namespace std;
12 class Sock{
// This class is used to encapsulate socket
13 public:
14 static int Socket(){
// Create socket
15 int sockfd = socket(AF_INET, SOCK_STREAM, 0);
16 if(sockfd < 0){
17 cerr << "socket error "<< endl;
18 exit(1);
19 }
20 return sockfd;
21 }
22 static void Bind(int sockfd, int port){
// binding
23 struct sockaddr_in local;
24 local.sin_family = AF_INET;
25 local.sin_port = htons(port);
26 local.sin_addr.s_addr = htonl(INADDR_ANY);
27 int ret = bind(sockfd, (struct sockaddr*)&local, sizeof(local));
28 if(ret < 0){
29 cerr << "bind error" << endl;
30 exit(2);
31 }
32 }
33 static void Listen(int sockfd){
// monitor
34 int ret = listen(sockfd, LOGBACK);
35 if(ret < 0){
36 cerr << "listen error" << endl;
37 exit(3);
38 }
39 }
40 static int Accept(int sockfd){
// receive
41 struct sockaddr_in peer;
42 socklen_t len = sizeof(peer);
43 int sock = accept(sockfd, (struct sockaddr*)&peer, &len);
44 if(sock < 0){
45 cerr << "accept error" << endl;
46 return -1; // accept wrong, Server continues to run
47 }
48 return sock;
49 }
50 static void Setsockopt(int lsock){
// Port multiplexing
51 int opt = 1;
52 setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
53 }
54 };
/*************** SelectServer.hpp *******************/
1 #pragma once
2 #include "sock.hpp"
3
4 #define NUM (sizeof(fd_set)*8)
5 #define EMPTY -1
6
7 class SelectServer{
8 private:
9 int port;
10 int lsock;
11 int fd_array[NUM]; // maintain fd_set Concerned file descriptor in
12 public:
13 SelectServer(int _port = 8080)
14 :port(_port),lsock(-1){
15 for(auto& e : fd_array){
16 e = EMPTY;
17 }
18 }
19
20 void Init(){
21 // Port multiplexing , be based on tcp After your server hangs up , Used to restart immediately .
22 Sock::Setsockopt(lsock);
23 lsock = Sock::Socket();
24
25 fd_array[0] = lsock; // Put the listening socket into the array
26
27 Sock::Bind(lsock, port);
28 Sock::Listen(lsock);
29 }
30 void Start(){
31 int fds = -1;
32 int maxfd = -1;
33 fd_set rfds;
34 struct timeval timeout = {
5, 0}; // Set the wait time
35 for(;;){
36 FD_ZERO(&rfds); // If you do not reset every time , There will be bug!!, Because there is no clear file descriptor ( such as 4)
37 timeout.tv_sec = 5; // It has been closed by you , But you're still telling the system to use it !!
38 timeout.tv_usec = 0;
39 for(int i = 0; i < NUM; ++i){
40 if(fd_array[i] != EMPTY){
// fd_array[i] It's worth it ;
41 FD_SET(fd_array[i], &rfds);
42 if(fd_array[i] > maxfd){
43 maxfd = fd_array[i]; // maintain maxfd
44 }
45 }
46 }
47 ArrayPrint();
48 cout << "select begin ..." << endl;
49 fds = select(maxfd + 1, &rfds, nullptr, nullptr, &timeout);
50 if(fds < 0){
51 cerr << "select error" << endl;
52 exit(4);
53 }
54 else if(fds == 0){
55 cout << "timeout..." << endl;
56 continue;
57 }
58 else{
59 HandleEvents(&rfds); // The parameter type here can also be const fd_set&
60 }
61 }
62 }
63 ~SelectServer(){
64 if(lsock > 0){
65 close(lsock);
66 }
67 }
68
69 private:
70 void ArrayPrint(){
71 cout << "fd_array : ";
72 for(int i = 0; i < NUM; ++i){
73 if(fd_array[i] != EMPTY){
74 cout << fd_array[i] << " ";
75 }
76 }
77 cout << endl;
78 }
79 void AddFdToArray(int fd){
80 for(int i = 0; i < NUM; ++i){
81 if(fd_array[i] == EMPTY){
82 fd_array[i] = fd;
83 break;
84 }
85 }
86 }
87
88 void DeleteFdFromArray(int fd){
89 for(int i = 0; i < NUM; ++i){
90 if(fd_array[i] == fd){
91 fd_array[i] = EMPTY;
92 break;
93 }
94 }
95 }
96 void HandleEvents(fd_set* p_rfds){
97 for(int i = 0; i < NUM; ++i){
98 if(fd_array[i] == EMPTY){
99 continue;
100 }
101 else{
// The file descriptor is in the range we are waiting for ;
102 if(FD_ISSET(fd_array[i], p_rfds)){
// If the file descriptor is ready
103 if(fd_array[i] == lsock){
// Socket received Connect
104 int sock = Sock::Accept(lsock);
105 cout << "get a new link..." << endl;
106 AddFdToArray(sock);
107 }
108 else{
// Socket received data
109 char buf[10240] = {
0};
110 ssize_t ss = recv(fd_array[i], buf, sizeof(buf) - 1, 0);
111 if(ss > 0){
112 cout << "client # " << buf << endl;
113 }
114 else if(ss == 0){
// Client exit
115 cout << "client quit...." << endl;
116 close(fd_array[i]);
117 DeleteFdFromArray(fd_array[i]);
118 }
119 else{
120 cout << "recv error" << endl;
121 exit(5);
122 }
123 }
124 }
125 else{
126 // File descriptor not ready , continue select;
127 // donothing
128 }
129 }
130 }
131 }
132 };
/*************** SelectServer.cc ******************/
1 #include "SelectServer.hpp"
2
3 void Usage(char* arg){
4 cout << "Usage: \n\r" << "arg port\n" ;
5 }
6 int main(int argc, char *argv[]){
7 if(argc != 2){
8 Usage(argv[0]);
9 exit(50);
10 }
11
12 SelectServer* ss = new SelectServer(atoi(argv[1]));
13 ss->Init();
14 ss->Start();
15
16 delete ss;
17 }
- select The best part is to use an array to maintain the file descriptors we care about . Transfer the operation on bit to the operation on array .
- Every time select Before ,rfds All have to be reset , Otherwise, it will affect the results .
select Advantages and disadvantages
advantage :
- Efficient .
shortcoming :
- fd_set There is an upper limit on the length , That means select There is a limit to the number of file descriptors that can be listened to .
- Because a lot of f Polling detection , As the file descriptor grows , Efficiency will fall .
- Every time you need to put fd_set Copy to kernel , Then copy from the kernel to the user , This is a waste of efficiency .
- select Too few supported file descriptors .
边栏推荐
- 虚拟机CentOS7中无图形界面安装Oracle(保姆级安装)
- memcached全面剖析–2. 理解memcached的內存存儲
- The virtual currency evaporated $2trillion in seven months, and the "musks" ended the dream of 150000 people becoming rich
- Rewrite, maplocal and maplocal operations of Charles
- memcached全面剖析–2. 理解memcached的内存存储
- Big factories go out to sea and lose "posture"
- Volcano成Spark默认batch调度器
- memcached全面剖析–3. memcached的删除机制和发展方向
- TCP Jprobe utilization problem location
- MySQL optimizes query speed
猜你喜欢

Remove the screen recording reminder (seven cattle cloud demo)

福建省发改委福州市营商办莅临育润大健康事业部指导视察工作

AntDB数据库在线培训开课啦!更灵活、更专业、更丰富

Blender's simple skills - array, rotation, array and curve

自己总结的wireshark抓包技巧

2022国际女性工程师日:戴森设计大奖彰显女性设计实力

Capture the whole process of accessing web pages through Wireshark

升哲科技 AI 智能防溺水服务上线

基于C语言实现的足球信息查询系统 课程报告+项目源码+演示PPT+项目截图

Page replacement of virtual memory paging mechanism
随机推荐
[cloud native learning notes] deploy applications through yaml files
Concepts of kubernetes components
HCIA assessment
XTransfer技术新人进阶秘诀:不可错过的宝藏Mentor
Oauth2.0 introduction
多线程收尾
Football information query system based on C language course report + project source code + demo ppt+ project screenshot
leetcode1720_2021-10-14
Kernel Debugging Tricks
网络层 && IP
Different WordPress pages display different gadgets
Pattern recognition - 1 Bayesian decision theory_ P1
关于Unity中的transform.InverseTransformPoint, transform.InverseTransofrmDirection
Implementing DNS requester with C language
Capture the whole process of accessing web pages through Wireshark
The most important thing at present
Memcached comprehensive analysis – 3 Deletion mechanism and development direction of memcached
使用Adb连接设备时提示设备无权限
Handwritten RPC the next day -- review of some knowledge
Tdengine can read and write through dataX