非阻塞套接字接受没有用C自旋锁 [英] Non-blocking socket accept without spinlock in C

查看:180
本文介绍了非阻塞套接字接受没有用C自旋锁的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可能重复:结果
  唤醒线程阻塞在接受()调用

我写这侦听连接(接受它们并将它们传递给工作线程),直到一个自定义的停止信号被送到一个小服务器。

I am writing a small server which listening for connections (accepting them and passing them to worker threads) until a custom stop signal is sent.

如果我使用阻塞套接字,那么我的主要接受环上的自定义停止信号不能突破被发送。不过,我希望避免与非阻塞套接字忙等待/自旋锁循环。

If I use blocking sockets, then my main accept loop cannot break on the custom stop signal being sent. However, I wish to avoid having a busy-wait/spinlock loop with a non-blocking socket.

我要的是我的主要接受循环阻塞,直到建立连接接收或停止发送信号。

What I want is for my main accept loop to block until either a connection is received or the stop signal is sent.

在C是这可能在Linux上?

Is this possible in C on Linux?

非常感谢。

推荐答案

如果我理解正确的话,那么你是开放给使用任何一种信号,不一定是POSIX信号。其实,POSIX信号是一个糟糕的选择,因为检查,如果你在一个循环中收到的一个有不可避免的竞争条件。

If I understand correctly then you are open to using any kind of "signal", not necessarily a POSIX signal. Actually, POSIX signals are a poor choice because checking if you have received one in a loop has unavoidable race conditions.

你所需要使用的,可以通过文件描述符进行监测什么。它可以是:

What you need to use is anything that can be monitored through a file descriptor. It could be:


  • 的管道。您的接受循环监视管道的读结束。要唤醒循环,另一个线程写入到的东西(什么都无所谓)到写入结束。

  • 另一个插座。相若,另一个线程醒来写入到插座的另一端的接受循环。

  • 在您的监察使用inotify的文件系统中的文件。

  • 接收循环何时中断的一些数据的设备。

  • 等...

在实例列表中的存货项通常不实用。它们只是为了说明,它可以是任何类型的对象,只要它是具有可监视文件描述符。最简单,最便宜的,也是最常用的方法是一个管道。

The later entries in the list of examples aren't generally practical. They're just to illustrate that it can be any type of object as long as it is has monitorable file descriptor. The simplest, cheapest, and most popular way is a pipe.

如果您已经在使用非阻塞套接字,那么你肯定已经有了某种轮询循环来检查时,他们已经准备好接受连接。我要你使用调查()来做到这一点承担。

If you are already using nonblocking sockets, then you certainly already have some kind of polling loop to check when they're ready to accept connections. I'm going to assume you're using poll() to do this.

在你开始你的循环,建立一个管道是这样的:

Before you start your loop, set up a pipe like this:

pipe(&pipefd[0]);
read_end = pipefd[0];
write_end = pipefd[1];
fcntl(read_end, F_SETFL, O_NONBLOCK);

的fcntl 是设置管道非阻塞模式的读端。你将要使用的管道在调查为此与你一起插座调用,所以需要对其进行分块。

The fcntl is to set the read end of the pipe to non blocking mode. You're going to be using that end of the pipe in your poll call together with your socket, so it needs to be nonblocking.

然后,只需添加你在接受环监控管瓦块描述符列表中的读端:

Then just add the read end of the pipe to the list of tile descriptors that you monitor in your accept loop:

for (;;) { /* accept loop, loop forever */
    /* Monitor your socket. You should already have this in your code */
    pollfd[0].fd = your_socket;
    pollfd[1].events = POLLIN;

    /* Add a new entry to monitor the read end of the pipe */
    pollfd[1].fd = read_end;
    pollfd[1].events = POLLIN;

    /* Now call poll, as before, but monitor 2 file descriptors instead of just 1 */
    n = poll(&pollfd[0], 2, -1);

    /* Check if your socket is ready to accept.
       This part, you are already doing. */
    if (pollfd[0].revents) {
        newsocket = accept(your_socket, etc....)
        do_somehting_with(new_socket);
    }

    /* New part: check if anyone has written something for you into your pipe */
    if (pollfd[1].revents) {
        break; /* stop the loop */
    }
}

该示例使用调查,但你可能会使用选择(甚至 epoll的)代替。 选择有不同的接口,但这个想法是一样的。

The example uses poll but you might be using select (or even epoll) instead. select has a different interface but the idea is the same.

此技术被称为自管招

这篇关于非阻塞套接字接受没有用C自旋锁的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆