Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/28.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何使用C++;select()函数在Unix OSs中工作吗?_C++_Linux_Network Programming - Fatal编程技术网

C++ 如何使用C++;select()函数在Unix OSs中工作吗?

C++ 如何使用C++;select()函数在Unix OSs中工作吗?,c++,linux,network-programming,C++,Linux,Network Programming,我曾使用select()函数来实现服务器,但现在我必须自己实现它(作为项目的一部分) 有人能帮我实现这个功能吗?有消息来源、文章吗?有人能解释一下这个函数中发生了什么吗 您可以随时查看开源实现以获得灵感和/或操作理论 我相信基本前提是调用select()的进程被放在与请求中的每个套接字相连的“等待列表”上,然后内核可以随时检查套接字的状态,以更新该套接字列表中的进程,并使其可运行 当然,这是一个非常高层次的描述,尽管它只是掩盖了许多您需要涵盖的细节,以便正确地进行描述。select是一个操作系统

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


有人能帮我实现这个功能吗?有消息来源、文章吗?有人能解释一下这个函数中发生了什么吗

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

我相信基本前提是调用
select()
的进程被放在与请求中的每个套接字相连的“等待列表”上,然后内核可以随时检查套接字的状态,以更新该套接字列表中的进程,并使其可运行


当然,这是一个非常高层次的描述,尽管它只是掩盖了许多您需要涵盖的细节,以便正确地进行描述。

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

您可以将其视为
pthread\u cond\u wait
的另一个专用版本,它接收与条件变量相关的信号
pthread_cond_wait
暂停当前线程,直到收到信号,然后(可选)验证信号是否与适当的互斥体关联,然后获取互斥体,并继续执行<代码>选择接收信号,确认(或至少保证)其接收,并传递信息。它还处理在调用之前接收到的信号

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


不过,这是一个很好的尝试。

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

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

在最初检查列出的文件描述符的当前状态后,基本上,
select
的工作原理是,它在超时过期之前不会返回,或者它关心的某个描述符更改了状态(以它关心的方式)。这可以完全在调度程序中处理,以便线程在出现所需条件之前无法进行调度,或者线程可以阻塞,直到发生它可能感兴趣的更改,检查它是否真的感兴趣,然后返回(如果感兴趣),或者再次阻塞(如果不感兴趣)。在这种方法的极端情况下,一个完全愚蠢(且效率低下)的实现可能只有一个条件变量,每个调用
select
的调用方都会等待,并且每次状态发生变化时,I/O系统都会广播该条件变量(正如Potatoswatter指出的,您还必须记录状态)

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


首先要做好设计,这可能意味着要研究其他操作系统是如何做到这一点的。否则,您将在接下来的两年内修复比赛条件。

是否实施?你真的想制作自己版本的select()还是只想使用它?是的……我想自己实现它。(事实上我不得不):“pthread_cond_wait在实现方面并不是很原始”。不过,这真是太接近了:@Steve:这比“不计划此线程”要大得多。即使伪代码也是用高级结构编写的,或者至少是可用级别的结构。哦,我明白了。我是从C程序员的角度来看“原语”的——如果某个操作只能由操作系统实现,那么它就是操作系统原语。我猜你是从内核程序员的角度来理解它的——如果它不调用任何其他函数,那么它就是一个原语。@Steve Jessop:这是一个原语,因为只有操作系统才能真正实现它。它与操作系统内部有着内在的联系……试图使用condvars实现select是一个常见的陷阱。如果没有人在等待一个条件变量,那么给它发信号什么都不做,也无法判断是否有人收到了信号。你不会花2年的时间来修正比赛。基本要素是实现变量条件的作业队列。添加作业需要以独占方式访问队列,
select
的全部要点是写入是非阻塞的。这就是为什么在等待之前必须检查当前状态(并且原子地启动等待,这就是condvar的作用)。非阻塞I/O不应与获取锁混淆——非阻塞I/O操作可以在保护某些结构的锁上短暂阻塞,只要在实际数据离开/到达之前不阻塞(尽管您必须更加小心)
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);