首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >读取许多真正的文件描述符

读取许多真正的文件描述符
EN

Stack Overflow用户
提问于 2015-04-25 14:00:46
回答 2查看 261关注 0票数 1

在Linux (Ubuntu)应用程序上工作。我需要以一种非阻塞的方式阅读许多文件。不幸的是,epoll不支持真正的文件描述符(文件描述符来自文件),它确实支持网络套接字的文件描述符。select确实在实际的文件描述符上工作,但是它有两个缺点: 1)它速度慢,线性地遍历所有设置的文件描述符;2)它是有限的,它通常不允许超过1024个文件描述符。

我可以更改每个文件描述符为非阻塞,并使用非阻塞“读”轮询,但这是非常昂贵的,特别是当有大量的文件描述符。

这里有什么选择?

谢谢。

更新1这里的用例是创建某种类型的文件服务器,许多客户端请求文件,以非阻塞的方式为它们服务。由于网络端实现(不是标准TCP/IP堆栈),无法使用sendfile()。

EN

回答 2

Stack Overflow用户

发布于 2015-04-25 14:33:06

您可以使用多个select调用与线程或分叉相结合。这将减少每个FD_ISSET集的select调用数。

也许您可以提供更多关于用例的详细信息。听起来,您正在使用select来监视文件更改,这并不像常规文件所期望的那样工作。也许你只是在找flock

票数 0
EN

Stack Overflow用户

发布于 2015-04-26 03:54:09

您可以在Linux上使用异步IO。相关AIO手册 (全部在第3节中)似乎有相当多的信息。我认为aio_read()可能是对您最有用的。

下面是一些代码,我相信您应该能够适应您的使用:

代码语言:javascript
复制
...

#define _GNU_SOURCE
#include <aio.h>
#include <unistd.h>

typedef struct {
    struct aiocb *aio;
    connection_data *conn;
} cb_data;

void callback (union sigval u) {
    // recover file related data prior to freeing
    cb_data data = u.sival_ptr;
    int fd = data->aio->aio_fildes;
    uint8_t *buffer = data->aio->aio_buf;
    size_t len = data->aio->aio_nbytes;
    free (data->aio);

    // recover connection data pointer then free
    connection_data *conn = data->conn;
    free (data);

    ...

    // finish handling request

    ...

    return;
}

...

int main (int argc, char **argv) {
    // initial setup

    ...

    // setup aio for optimal performance
    struct aioinit ainit = { 0 };
    // online background threads
    ainit.aio_threads = sysconf (_SC_NPROCESSORS_ONLN) * 4;
    // use defaults if using few core system
    ainit.aio_threads = (ainit.aio_threads > 20 ? ainit.aio_threads : 20)
    // set num to the maximum number of likely simultaneous requests
    ainit.aio_num = 4096;
    ainit.aio_idle_time = 5;

    aio_init (&ainit);

    ...

    // handle incoming requests
    int exit = 0;
    while (!exit) {

        ...

        // the [asynchronous] fun begins
        struct aiocb *cb = calloc (1, sizeof (struct aiocb));
        if (!cb)
            // handle OOM error
        cb->aio_fildes = file_fd;
        cb->aio_offset = 0; // assuming you want to send the entire file
        cb->aio_buf = malloc (file_len);
        if (!cb->aio_buf)
            // handle OOM error
        cb->aio_nbytes = file_len;
        // execute the callback in a separate thread
        cb->aio_sigevent.sigev_notify = SIGEV_THREAD;

        cb_data *data = malloc (sizeof (cb_data));
        if (!data)
            // handle OOM error
        data->aio = cb; // so we can free() later
        // whatever you need to finish handling the request
        data->conn = connection_data;
        cb->aio_sigevent.sigev_value.sival_ptr = data;  // passed to callback
        cb->aio_sigevent.sigev_notify_function = callback;

        if ((err = aio_read (cb)))  // and you're done!
            // handle aio error

        // move on to next connection
    }

    ...

    return 0;
}

这将使您不再需要等待主线程中读取的文件。当然,您可以使用AIO创建更多的性能系统,但是这些系统很可能更复杂,这应该适用于一个基本的用例。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29866132

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档