python - 我无法理解 python 中的轮询/选择

标签 python multithreading sockets polling epoll

我正在使用 UDP 在 python 中进行一些线程异步网络实验。

我想了解轮询和选择 python 模块,我从未在 C/C++ 中使用过它们。

那些是做什么用的?我有点理解选择,但它会在观看资源时阻塞吗?投票的目的是什么?

最佳答案

好的,一次一个问题。

这些是做什么用的?

这是一个简单的套接字服务器框架:

s_sock = socket.socket()
s_sock.bind()
s_sock.listen()

while True:
    c_sock, c_addr = s_sock.accept()
    process_client_sock(c_sock, c_addr)

服务器会循环接受来自客户端的连接,然后调用其处理函数与客户端套接字进行通信。这里有一个问题:process_client_sock 可能需要很长时间,甚至包含一个循环(这是经常发生的情况)

def process_client_sock(c_sock, c_addr):
    while True:
        receive_or_send_data(c_sock)

在这种情况下,服务器无法再接受任何连接。

一个简单的解决方案是使用多进程或多线程,只需创建一个新线程来处理请求,同时主循环继续监听新连接。

s_sock = socket.socket()
s_sock.bind()
s_sock.listen()

while True:
    c_sock, c_addr = s_sock.accept()
    thread = Thread(target=process_client_sock, args=(c_sock, c_addr))
    thread.start()

这当然有效,但考虑到性能还不够好。因为新进程/线程需要额外的 CPU 和内存,服务器不空闲可能会获得数千个连接。

因此selectpoll 系统调用试图解决这个问题。您给 select 一组文件描述符,并告诉它在任何 fd 准备好读/写/或发生异常时通知您。

它(选择)在观看资源时会阻塞吗?

是或否取决于您传递给它的参数。

作为select man page说,它将获得 struct timeval 参数

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

struct timeval {
long    tv_sec;         /* seconds */
long    tv_usec;        /* microseconds */
};

分三种情况:

  1. timeout.tv_sec == 0 和 timeout.tv_usec = 0

    无阻塞,立即返回

  2. 超时 == NULL

    永远阻塞,直到文件描述符准备就绪。

  3. 超时是正常的

    等待一定时间,如果仍然没有可用的文件描述符,则超时返回。

投票的目的是什么?

简单来说:在等待 IO 时,轮询可以释放 CPU 用于其他工作

这是基于一个简单的事实

  1. CPU 比 IO 快得多
  2. 等待IO是浪费时间,因为大部分时间,CPU都会空闲

希望对您有所帮助。

关于python - 我无法理解 python 中的轮询/选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7459408/

相关文章:

python - 为什么在名称前面有双下划线时传递关键字/命名参数会产生错误?

python高效的子串搜索

python - 带有用于自定义作业的附加线程的 CherryPy

c - UDP 套接字设置超时

python - 每次调用 handle() 后,Python 的 SocketServer 中的 TCPServer + BaseRequestHandler 是否关闭套接字?

python - 替换字符串中的特定单词

Python .get 嵌套 Json 值

python - 如何限制函数调用的执行时间?

c++ - QThread 与 std::thread

c++ - 部分udp文件传输