C ++ select()函数如何在Unix操作系统中运行?

时间:2010-10-01 09:53:29

标签: c++ linux network-programming

我使用select()函数来实现服务器,但现在我必须自己实现它(作为项目的一部分)。

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

有人可以帮我实现这个功能吗?任何来源,文章?谁能解释一下这个功能中发生了什么?

3 个答案:

答案 0 :(得分:3)

select是一个操作系统原语。它不能使用其他可移植构造实现,例如pthreads。

您可以将其视为pthread_cond_wait的不同专用版本,它接收与条件变量关联的信号。 pthread_cond_wait停止当前线程直到收到信号,然后(可选)验证信号是否与相应的互斥锁相关联,然后获取互斥锁,并继续。 select收到一个信号,确认(或至少保证)其收据,并传递信息。它还处理在调用之前收到的信号。

所以,pthread_cond_wait在实现方面并不是很原始;它的设计在语义上非常安全。无论好坏,这都是pthreads的精神。各种库中提供的原子变量为同步作业的pthread提供了一种不安全的原始实现替代方案,但信令涉及调度和非调度线程,这是非常特定于平台的。 (好吧,第二个想法,我猜你可以用自旋锁来实现select。我对这个想法感到不寒而栗。)

尽管如此,这是一个很好的练习。

答案 1 :(得分:0)

您可以随时查看开源实现的灵感和/或操作理论。

我认为基本前提是调用select()的进程被放在连接到请求中每个套接字的“等待列表”中,然后内核可以检查何时更新状态套接字哪个进程在套接字列表上,并使它们可以运行。

这当然是一个非常高级的描述,虽然只是掩盖了你需要覆盖的许多细节,以实现这一目标。

答案 2 :(得分:0)

如果您正在实施select,那么您(或您的同事)可能正在实施操作系统界面的重要部分。因此,这取决于您实现I / O子系统和调度程序的方式。

如果你没有实现调度程序,那么你需要某种“控制中心”,它使用同步原语(可能是条件变量)来跟踪你感兴趣的文件描述符状态的变化。

在最初检查列出的文件描述符的当前状态之后,从根本上说,select如何工作是它在超时到期之前不会返回,或者它关注的一个描述符更改状态(在某种程度上)它关心的)。这可以完全在调度程序中处理,这样线程就不可用于调度,直到出现所需的条件,或者线程可以阻塞,直到它可能感兴趣的某些更改发生,检查它是否真的感兴趣,然后如果是,则返回,如果不是则再次阻止。在这种方法的极端,一个完全愚蠢(和低效)的实现可以有一个条件变量,每个调用者到select等待,并且每次状态发生变化时由I / O系统广播(正如Potatoswatter指出的那样,你还必须记录状态。)

如果您没有实现I / O子系统,那么实现select的唯一方法是在I / O子系统支持的其他类似原语之上。或者,承担实现I / O的任务:将所有内容包装在您自己的层中,并使select仅通过该层可用。该层的实现取决于底层API,但如果所有其他方法都失败,您可以为每个文件描述符创建一个线程,在该线程中阻止I / O操作,然后在fd可读,可写时通知您的“控制中心” ,或有错误。

首先获得正确的设计,这可能意味着研究其他操作系统如何做到这一点。否则你在接下来的两年里修复竞争条件。