fd_set

select与epoll

三世轮回 提交于 2020-02-25 04:24:28
select 监听一组句柄fd_set,第一次调用的时候循环所有句柄对应的驱动函数xx_poll,socket的话就是sock_poll。 循环遍历完毕之后会如果发现有可用的(活跃状态的)fd,则返回,返回的时候会返回活跃的fd个数,同时会 把不活跃的fd在fd_set移除。如果循环fd_set一遍以后发现没有活跃的fd。假设此时socket在非阻塞模式下, 那么select会重复遍历这些fd_set直到超过了我们设置的时间限制,可是在阻塞模式下呢,怎么处理? 阻塞模式下我们没有必要设置超时限制,因为如果第一遍变量fd_set发现没有活跃的fd那么,这条进程会被 挂起的。进程怎么被激活呢,实际上进程是被挂在了n个fd的等待队列里,只要一个fd准备就绪那么进程就 会被唤醒,网卡接收了数据包发送一个中断给内核,内核处理这个中断,唤醒进程,这里是涉及到软中断的 ,有兴趣可以看看。select被唤醒之后,并不知道是哪一个fd把自己唤醒的,所以还要来一个遍历,过程跟 上面说的是一样的。select阻塞到返回经历的内核和用户空间的拷贝,先把fd_set从用户空间拷贝给内核空 间,内核空间处理完毕之后把活动的fd再copy回来。其实后者还好,但是前者当fd_set百万级别的时候,就 费劲了。个中细节我并非完全了解,可是单看这个设计模式就觉着有效率问题了,感觉真的很傻,copy不说,

select模型的原理、优点、缺点

时光怂恿深爱的人放手 提交于 2020-02-25 00:34:53
关于I/O多路复用: I/O多路复用(又被称为“事件驱动”),首先要理解的是,操作系统为你提供了一个功能,当你的某个socket可读或者可写的时候,它可以给你一 个通知。这样当配合非阻塞的socket使用时,只有当系统通知我哪个描述符可读了,我才去执行read操作,可以保证每次read都能读到有效数据而不 做纯返回-1和EAGAIN的无用功。写操作类似。操作系统的这个功能通过select/poll/epoll之类的系统调用来实现,这些函数都可以同时 监视多个描述符的读写就绪状况,这样,**多个描述符的I/O操作都能在一个线程内并发交替地顺序完成,这就叫I/O多路复用,这里的“复用”指的是复用 同一个线程。 I/O复用之select 1、介绍: select系统调用的目的是:在一段指定时间内,监听用户感兴趣的文件描述符上的可读、可写和异常事件。poll和select应该被归类为这样的系统 调用,它们可以阻塞地同时探测一组支持非阻塞的IO设备,直至某一个设备触发了事件或者超过了指定的等待时间——也就是说它们的职责不是做IO,而是帮助 调用者寻找当前就绪的设备。 下面是select的原理图: 2 、select系统调用API如下: #include <sys/time.h> #include <sys/types.h> #include <unistd.h> int select(int

I/O多路复用模型之select(一)

淺唱寂寞╮ 提交于 2020-02-23 15:18:45
原理: select函数会等待,直到描述符句柄中有可用资源(可读、可写、异常)时返回,返回值是可用资源(可读/可写/异常等)描述符的个数(>0),0代表超时,-1代表错误。具体到内核大致是:当应用程序调用select() 函数, 内核就会相应调用 poll_wait(), 把当前进程添加到相应设备的等待队列上,然后将该应用程序进程设置为睡眠状态。直到该设备上的数据可以获取,然后调用wake_up()唤醒该应用程序进程。select每次轮训都会遍历所有描述符句柄。 函数接口: int select(int max_fd,fd_set * readfds,fd_set * writefds,fd_set * exceptfds,struct timeval * timeout); max_fd :fd+1 readfds :可读描述符句柄 writefds :可写描述符句柄 exceptfds:异常描述符句柄 timeout :超时时间 select函数的参数将告诉内核: (1)我们所关心的对应描述符句柄 (2)对于每个描述符我们所关心的条件,是否可读,是否可写或是否异常 (3)希望等待多长时间,struct timeval * timeout struct timeval{ long tv_sec; /*秒 */ long tv_usec; /*微秒 */ } timeout ==

I/O多路复用

半城伤御伤魂 提交于 2020-02-21 05:44:51
I/O多路复用是这样一种机制:通过一个进程去监视多个文件描述符,一旦其中某个描述符就绪(通常是读就绪或者写就绪),就去通知程序进行相应的读或写操作,如果始终没有描述符就绪,则一直阻塞直到超时。 目前支持I/O多路复用的常见系统调用有select、poll和epoll。注意,这三者本质上还是属于同步I/O。 一、select select函数监视的文件描述符有三类,分别是readset、writeset和exceptset。调用该函数后,函数就处于阻塞状态,直到有描述符就绪(有数据可读、可写、异常),或者超时,这时函数返回后,就可以通过遍历数据结构fd_set来找到已就绪的文件描述符。函数原型如下: //若有就绪描述符则返回其数目,若超时则返回0,若出错则返回-1 int select( int maxfdpl, fd_set *readset, fd_set *writeset, fd_set *exceptset, const struct timeval *timeout); 在连接的文件描述符数量不大时,select函数性能是可以的,但是一旦描述符数量过大,而实际活跃的描述符数量又极少时,性能就有问题了。所以select函数一般有以下几个缺点: 每次调用select都需要把所有的fd从用户态拷贝到内核态,当fd很多时开销比较大;

IO 多路转接 select

痴心易碎 提交于 2020-02-19 00:52:40
TCP状态时序图: 1.主动发起连接请求端: CLOSE --发送SYN--SEND_SYN --接受 ACK、SYN --SEND_SYN--发送 ACK --ESTABLISHED(数据通信状态) 2.主动关闭连接请求端; ESTABLISHED(数据通信状态) --发送FIN --FIN_WAIT_1 --接受 ACK --FIN_WAIT_2(半关闭) --接受对端发送 FIN --FIN_WAIT_2(半关闭) --回发 ACK --TIME_WAIT(只有主动关闭连接方会经历该状态) -- 等 2MLS时长(大约40s) --CLOSE 3.被动接受连接请求端: CLOSE -- LISTEN --接收 SYN -- LISTEN --发送 ACK SYN --SYN_RCVD --接收ACK --ESTABLISHED 4.被动关闭连接请求端: ESTABLISHED -- 接收 FIN --ESTABLISHED --发送ACK --CLOSE_WAIT (说明对端【主动关闭连接请求端】处于半关闭状态) --发送 FIN--LASK_ACK --接收ACK--CLOSE 重点记忆: ESTABLISHED 、FIN_WAIT_2 <->CLOSE_WAIT 、TIME_WAIT(2MLS) 2MLS时长: 一定出现在 主动关闭连接请求端 ---TIME_WAIT

Linux网络编程-IO复用技术

爷,独闯天下 提交于 2020-02-18 22:25:16
IO复用是Linux中的IO模型之一,IO复用就是进程预先告诉内核需要监视的IO条件,使得内核一旦发现进程指定的一个或多个IO条件就绪,就通过进程进程处理,从而不会在单个IO上阻塞了。Linux中,提供了select、poll、epoll三种接口函数来实现IO复用。 1、select函数 #include <sys/select.h> #include <sys/time.h> int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); // 返回:若有就绪描述符则为其个数,超时为0,出错-1 nfds参数指定了被监听文件描述符的个数,通常设置为监听的所有描述符最大值加1,因为文件描述符是从0开始的。readfs、writefds和exceptfds分别对应可读、可写和异常等事件文件描述符集合,当调用select时,通过这3个参数传入自己感兴趣的文件描述符,select函数返回后,内核通过修改他们来通知应用程序那些文件描述符已经就绪。 fd_set结构体包含一个整形数组,该数组中每一个元素的每一位标记一个文件描述符,fd_set容纳的文件描述符数量由FD_SETSIZE指定,这就限制了select能同时处理的文件描述符最大个数

select函数

倾然丶 夕夏残阳落幕 提交于 2020-01-29 02:55:29
select函数 select()函数允许进程指示内核等待多个事件中的任何一个发生,并只在有一个或多个事件发生 或经历一段指定时间后才唤醒它 #include <sys/select.h> #include <sys/time.h> // 返回值:若有就绪描述符,则返回就绪描述符数目;若超时则返回0,出错返回-1 int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, const struct timeval *timeout); select的参数: maxfdp1: 指定待测试的描述符个数,它的值是待测试的最大描述符加1 readset、writeset、exceptset: 指定让内核测试读、写、异常条件的描述符 异常条件: 某个套接字的带外数据到达 某个已置为分组模式的伪终端存在可以从其主端读取的控制状态信息 fd_set *: select使用的描述符集 系统提供了4个宏对描述符集进行操作: #include <sys/select.h> #include <sys/time.h> void FD_SET(int fd, fd_set *fdset); // 设置文件描述符集fdset中对应于文件描述符fd的位(设置为1) void FD_CLR(int fd, fd

select 与 I/O多路转接

徘徊边缘 提交于 2019-12-23 06:43:44
参考博客:http://blog.sina.com.cn/s/blog_607072980102uxcw.html I/0多路转接 : 描述符表示某个I/O。构造一张有关描述符的数据表,调用select函数,返回准备就绪的描述符,如果没有描述符准备好,则一直阻塞,超时返回0。 int select( int maxfdp1, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, sturct timeval *tvptr); 返回:准备就绪的描述符,若超时则为0,若出错则为-1 maxfdp1为最大描述符值,设置为一个常数; readfds、writefds、exceptfds是指向描述符集的指针,表示我们关心的可读、可写和处异常条件的描述符; tvptr表示愿意等待的时间(秒、微秒),tvptr=NULL在捕捉到信号前永远等待。 描述符集 fd_set rset; //描述符集 int fd; //描述符集的位,表示一个描述符 FD_ZERO(fd_set *fdset); //清空fdset中的所有位 FD_SET(int fd, fd_set *fdset); //在fdset中打开fd所对应的位 FD_CLR(int fd, fd_set *fdset); //在fdset中关闭fd所对应的位 FD_ISSET(int

linux下的select简直太奇葩了:1024限定的不只是监听的个数,还是文件描述符的最大值,注意,是值

落爺英雄遲暮 提交于 2019-12-18 03:01:15
我原来自以为对select就算不熟,基本原理和使用方法也略知一二了,做了一年多的服务器编程,好歹知道linux下的select不支持超过1024个的描述符,好歹知道可以通过内核编译来重设FD_SETSIZE,也敢大言不惭地说select函数的maxfd应该是监测的所有fd值中取最大的+1,甚至连世界上有select * from的语法都知道,结果,今天直接扎扎实实栽在了select上面了:我生生花了近2个小时来跟踪select的奇葩点。很让人痛苦的2个小时啊,那么多关联点,盘根错节揉在一块,每条支脉都显得那么无辜,实在有种拔剑四顾心茫然的感觉。不过,说起来也要感谢select,要不是它,这么让人痛苦的2个小时不知道怎么度过呢!总之,当我通过再三排除最终跟扯大肠一样扯出select的各种纠结时,脑海里不由得浮现出了一句箴言:“一切有为法,如梦幻泡影,如露亦如电,应作如是观”。善哉。 先说一下问题的表象,来源是这样的:我用客户端一次性发起超过2000个连接,等连接全部就绪后,设为非阻塞,将他们FD_SET进readset和writeset,以接收和发送消息。当然,这里我还是有点上面提到的常识的,不是一下子全部FD_SET进去,而是分批次,这里我是设成900,每次FD_ZERO之后我都设一个计数,FD_SET超过900个的socket就停止。因为每个连接做的事情很少,先发一次数据

多路IO复用技术--select模型

扶醉桌前 提交于 2019-12-18 01:56:47
1.功能介绍 1.1 网络通信中,对于套接字(文件描述符)在任意时刻是否有数据可读,我们不知道,只会用while 10毫秒循环收发,select能够解决这个问题,时时监听套接字的读写情况,有收到数据就读取。 2.相关函数说明 2.1 int select ( int n , fd_set * readfds , fd_set * writefds , fd_set * exceptfds , struct timeval * timeout ) ; 说明: select ( ) 用来等待文件描述符状态的改变。参数n代表最大的文件描述符加 1 ,参数readfds、writefds和exceptfds称为文件描述符集,填了readfd代表监听可读事件(收数据),不填代表不监听该事件,其他两个同理,timeout代表超时时间设置,就是个时间,可不设置,填 NULL , struct timeval结构体如下: struct timeval { long tv_sec ; /*秒 */ long tv_usec ; /*微秒 */ } 2.2 字符集相关函数操作 int FD_ZERO ( fd_set * fdset ) ; int FD_CLR ( int fd , fd_set * fdset ) ; int FD_SET ( int fd , fd_set * fdset ) ;