SELECT是如何实现的?

翻译自:http://www.quora.com/Network-Programming/How-is-select-implemented

我会以Linux为例,因为那是我熟悉的。我没有BSD或其他unix系统的经验,但我假定这些系统原理上类似。

每一个Socket(实际上可以是能够注册到select()上的任意fd - file descriptor)都有一个waiters的列表,他们(waiter)在等待socket上的活动(在linux上是 struct wait_queue_head_t)。这个Socket上无论什么时候有感兴趣的事件发生(到达新数据,缓冲区有可写的空闲空间,或者某种错误),这个Socket会遍历列表通知等待活动的每一个线程。

select()系统调用遍历用户传入的描述符列表。对于每一个fd,调用fd的poll()方法(这个方法和应用层的poll()系统调用是两回事),这将会添加调用者(当前线程)到fd的等待队列,返回适用于当前fd的事件(读,写,异常)。

如果任何fd匹配用户传入的条件,select()在更新用户传入的fd_sets后,立即返回。

如果没有匹配的fd,select()会一直休眠,一直到用户指定的最大超时时间。

如果在超时时间间隔内,注册到select()上的任一fd有感兴趣的事件发生,fd会通知这个fd的等待队列。这会唤醒调用select()时休眠的用户线程,这时就会重复上面的循环,看看哪一个fd准备好返回给用户。

select()会记录它添加的所有的等待队列,在返回以前,确保从所有的fd移除。

summary:每一次select()调用需要 3 次遍历,第一次是对每个fd分别调用poll,第二次是遍历生成返回给用户的fd_sets,第三次是应用层面遍历进行业务逻辑处理。


英文原文:

I'll answer for Linux, since that's what I know. I have no experience with any of the BSDs or other unixes, but I would assume they work broadly similarly.

Every socket (really, every file descriptor that can be select()ed on) has a list of waiters that are currently waiting for activity on that socket (struct wait_queue_head_t in Linux terminology). Whenever something interesting happens on that socket (new data is available, buffer space is free for writing, or some kind of error), that socket will walk its list and notify everyone waiting on it.

select() works by looping over the list of file descriptors that the user passed in. For every file descriptor, it calls that fd's poll() method, which will add the caller to that fd's wait queue, and return which events (readable, writeable, exception) currently apply to that fd.

If any file descriptor matches the condition that the user was looking for, select() will simply return immediately, after updating the appropriate fd_sets that the user passed.

If not, however, select() will go to sleep, for up to the maximum timeout the user specified.

If, during that interval, an interesting event happens to any file descriptor that select() is waiting on, that fd will notify its wait queue. That will cause the thread sleeping inside select() to wake up, at which point it will repeat the above loop and see which of the fd's are now ready to be returned to the user.

select() also keeps track of all of the wait queues it has been added to, and before returning (successfully or otherwise), must go through and ensure it's been removed from all of them.

转载于:https://my.oschina.net/astute/blog/92433

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值