《网络编程实战》学习笔记 Day9
创始人
2024-05-18 23:09:18
0

系列文章目录

这是本周期内系列打卡文章的所有文章的目录

  • 《Go 并发数据结构和算法实践》学习笔记 Day 1
  • 《Go 并发数据结构和算法实践》学习笔记 Day 2
  • 《说透芯片》学习笔记 Day 3
  • 《深入浅出计算机组成原理》学习笔记 Day 4
  • 《编程高手必学的内存知识》学习笔记 Day 5
  • NUMA内存知识 学习笔记 Day6
  • 《C++并发编程》 学习笔记 Day7
  • 《职场求生攻略》学习笔记 Day8

文章目录

  • 系列文章目录
  • 前言
  • 一、select I/O多路复用模型是什么?(What)
  • 二、select 内核是如何实现的?(Why)
  • 三、如何使用select,demo实验show me the code?(How)
  • 总结


前言

提示:这里可以添加本文要记录的大概内容:

学习内容:https://time.geekbang.org/column/article/138948
与知识建立主客体之间的联系:
其实我之前对高性能网络编程接触的少,除了计算机网络基础课TCP协议(三次握手、四次分手)、应用程序对Socket编程+多线程编程的实践理解外,没有真实需求推动,深究的就更少了。八股文背了,可能当时有些概念,过后又忘了。

但随着中间件的设计,团队有时在高并发改造场景,会谈到“poll”类比该I/O多路复用模型。这次真发现了这个网络编程实践专栏高性能篇,将阻塞/非阻塞/异步、I/O多路复用(select、poll、epoll)、多进程/多线程编程模型,三个维度循序渐进的组合起来,一步步揭开、对比、明晰,初看3篇文章概念+实践,和后续目录安排,方觉大快朵颐。


提示:以下是本篇文章正文内容,下面案例可供参考

一、select I/O多路复用模型是什么?(What)

问题场景:
I/O多路复用最初设计解决的场景是:标准输入、套接字等都看做I/O的一路。多路复用的意思是在任何一路有“事件”发生的情况下,通知应用程序去处理相应的I/O事件。而在没有I/O事件触发时,应用程序进程是挂起(阻塞,时间片调度执行其他进程),还是继续做其他事情(在剩余的时间片内)这就是I/O阻塞、非阻塞的维度了。

select之所以大名鼎鼎,可能跟golang通过协程实现高效的I/O多路复用有关。其关键字:select的使用和传播,让该I/O多路复用大名鼎鼎。

从专栏几篇文章看下来,要理解I/O多路复用,除了有开发者应用进程的视角,得理解到要从操作系统内核这个角度看(在序列图中,表示出这个实体)。从而,对比select、poll、epoll多种I/O多路复用模型。

使用select函数,通知内核挂起进程,当一个或多个I/O事件发生后,控制权返还给应用程序,由应用程序进行I/O事件的处理。

草图
在这里插入图片描述

二、select 内核是如何实现的?(Why)

select 函数调用传递给内核的数据结构,概念上是:文件描述符的集合 fd_set
在实现上,是通过INT型的bit位表示集合中的元素,因而也受实现的限制,select支持的I/O多路复用有1024的限制。


int select(int maxfd, fd_set *readset, fd_set *writeset, fd_set *exceptset, const struct timeval *timeout);返回:若有就绪描述符则为其数目,若超时则为0,若出错则为-1

在这里插入图片描述
这块我没翻内核源码,之后补上 TODO。

集合数据结构fd_set *readset, fd_set *writeset, fd_set *exceptset传递给内核,其实也暗示了内核的实现,内核根据I/O事件给读文件描述符、写文件描述符、异常文件描述符集合填充数据。

三、如何使用select,demo实验show me the code?(How)

demo:
详见:https://gitee.com/jahentao/experiments/pulls/1/files

调用select函数,传参。
操作宏:

  • FD_ISSET对向量进行检测,判断出对应套接字的元素 a[fd]是 0 还是 1

根据readmask返会的文件描述符判断那一路I/O可读,进而返回控制权处理。


int main(int argc, char **argv) {if (argc != 2) {error(1, 0, "usage: select01 ");}int socket_fd = tcp_client(argv[1], SERV_PORT);char recv_line[MAXLINE], send_line[MAXLINE];int n;fd_set readmask;fd_set allreads;FD_ZERO(&allreads);FD_SET(0, &allreads);FD_SET(socket_fd, &allreads);for (;;) {readmask = allreads;int rc = select(socket_fd + 1, &readmask, NULL, NULL, NULL);if (rc <= 0) {error(1, errno, "select failed");}if (FD_ISSET(socket_fd, &readmask)) {n = read(socket_fd, recv_line, MAXLINE);if (n < 0) {error(1, errno, "read error");} else if (n == 0) {error(1, 0, "server terminated \n");}recv_line[n] = 0;fputs(recv_line, stdout);fputs("\n", stdout);}if (FD_ISSET(STDIN_FILENO, &readmask)) {if (fgets(send_line, MAXLINE, stdin) != NULL) {int i = strlen(send_line);if (send_line[i - 1] == '\n') {send_line[i - 1] = 0;}printf("now sending %s\n", send_line);size_t rt = write(socket_fd, send_line, strlen(send_line));if (rt < 0) {error(1, errno, "write failed ");}printf("send bytes: %zu \n", rt);}}}}

我想进一步在GEM5/QEMU仿真中,进行I/O多路复用实验的性能工程对比,TODO。


总结

提示:这里对文章进行总结:

今天的学习,我了解了select 函数的使用。select 函数提供了最基本的 I/O 多路复用方法,在使用 select 时,我们需要建立两个重要的认识:

  • 描述符基数是当前最大描述符 +1;
  • 每次 select 调用完成之后,记得要重置待测试集合。

内容来源:
极客时间:20 | 大名⿍⿍的select:看我如何同时感知多个I/O事件

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
【PdgCntEditor】解... 一、问题背景 大部分的图书对应的PDF,目录中的页码并非PDF中直接索引的页码...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
修复 爱普生 EPSON L4... L4151 L4153 L4156 L4158 L4163 L4165 L4166 L4168 L4...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...