我正在 Linux 中设计一个 C 程序,其中有两个线程。一个主线程是 event_processor_thread,它执行主函数处理。第二个线程是始终在后台运行的 event_dispatcher 线程,实时写入和读取多个接口(非阻塞异步 I/O)
我在网上做了一些研究,发现实现非阻塞套接字 I/O 的最佳方法可以通过
来完成select()
我选择了后者,因为它更容易,而且我最多有 4 个接口可供读取/写入。
我很清楚使用
readfds
的听/读机制,但我不确定如何使用writefds
!如果我将 event_processor_thread 中的数据放入共享内存,并让该事件调度程序线程从共享内存中读取数据并使用 send()
进行写入,select 会自行将数据发送到套接字吗?这就是为什么我需要在 writefds
中使用 select()
吗?
如果我的问题不清楚,我很抱歉,我基本上想要的是有一个非阻塞 I/O 线程来将事件分派到事件处理器线程或从事件处理器线程分派到外部接口。高度赞赏这方面的任何投入。谢谢!
select的writefds是检查文件描述符是否准备好写入。对于套接字,这意味着与套接字关联的发送缓冲区未满。
假设您平台上的套接字有 8 kb 缓冲区,并且您想要发送 100 kb 数据。
您调用
write
并获得返回值 8192,表明前 8192 个字节已被写入。下一次调用 write 返回 EAGAIN
或 EWOULDBLOCK
指示发送缓冲区已满。
您现在可以使用
select
来查看发送缓冲区何时再次有空间(即何时将一个 tcp/ip 数据包传输到客户端),以便您可以继续写入。同时,您可以监听新连接并等待客户端的输入。
请注意,
select
从不发送任何数据,它只是同时监视多个文件描述符的状态。
不,
select()
不会“照顾写作”。当 writefds 集中包含的一个或多个文件描述符变得可写时,它会通知您。这可能意味着相关的 fd 已经完成了您之前所做的(非阻塞)写入,因此您现在可以执行另一个操作。
select()
告诉您文件描述符何时可写。对于套接字来说,这意味着它可以接受新的出站数据而不会阻塞调用者。如果您调用 send()
或 write()
并且套接字的出站缓冲区已满,您将收到 EAGAIN
或 EWOULDBLOCK
错误,此时您将停止写入该套接字,直到它再次可写。 select()
还可以告诉您在调用非阻塞 connect()
后套接字何时变得可写,表示已成功建立连接并且可以开始将数据写入对等方。