处理大量的FILE指针

时间:2017-01-27 21:59:55

标签: c multithreading mingw-w64

TLDR

是否有一种干净的方法可以通过整个程序处理1到65535个文件,而无需分配全局变量,其中大部分可能永远不会使用,也不使用链接列表(Windows上的mingw-w64)

长篇故事

我有一个tcp-server,它从很多客户端(最多65535)分配数据,并将它们保存在数据库中。 “数据库”是一个目录/文件结构,如下所示:data \%ADDR%\%ADDR% - %DATATYPE% - %UTCTIME%.wwss其中%ADDR%是地址,%DATATYPE%是数据类型和%UTCTIME%是第一个数据包到达此套接字时的utc时间(以秒为单位)。因此,每次接受新连接时,都应按指定的方式创建此文件。

如何正确处理65535 FILE句柄?首先想到的是:全局变量。

FILE * PV_WWSS_FileHandles[0x10000]
//...
void tcpaccepted(uint16_t u16addr, uint16_t u16dataType, int64_t s64utc) {
    char cPath[MAX_PATH];
    snprintf(cPath, MAX_PATH, "c:\\%05u\\%05u-%04x-%I64d.wwss", u16addr, u16addr, u16dataType, s64utc);
    PV_WWSS_FileHandles[u16addr] = fopen(cPath, "wb+");
}

这似乎很懒惰,因为所有地址可能永远不会同时连接,因此它会分配从未使用过的内存。

第二个想法:创建一个存储句柄的链表。这里的坏处是,它可能是非常密集的,因为我想在多线程环境中执行此操作,并且当f.e. 400个线程同时接收新数据,他们都必须通过整个列表才能找到FILE句柄。

1 个答案:

答案 0 :(得分:1)

你真的应该看看其他人的代码。想到了Apache。我们假设您可以在计算机上打开2 ^ 16个文件句柄。这是一个调整问题。

现在......首先考虑文件句柄是什么。它通常是C标准库的构造...它保持打开文件的数组(文件句柄是该数组的索引)。如果你想在这些句柄上保留其他信息,你可能也想要保留一个数组。

如果您担心自己占用的资源,请考虑每个开放式网络文件句柄会导致操作系统保留4k或8k(可配置)缓冲区x2(进出)以及文件句柄结构。在操作系统级别,这很容易就是一块GB的内存。

当你做相当于select()的操作时,如果你的操作系统是智能的,那么你将获得文件句柄---所以你可以用它来索引你的数组"做什么&#34 ;对于该文件句柄。如果你的select()不聪明,你就必须检查每个打开的文件句柄......这会使任何表演的尝试都笑了。

我说"看看其他人的解决方案。"我是认真的。原始的apache每个进程使用一个文件句柄(有效)。当select()愚蠢时,这是一个很好的策略。糟糕的是,愚蠢的操作系统会唤醒太多的进程 - 但那是大约1999年。现在apache默认使用它的混合MPM模型......这是多线程和多任务处理。它为每个进程(线程)提供一定数量的客户端,并具有多个进程。这样可以使每个进程的文件数更加合理。

如果你再回过头来,为了简单起见,还有inetd方法。每个连接一个(比如说)ftp进程。世界上最大的ftp服务器(ftp.freebsd.org)以这种方式运行多年。

不要将文件句柄存储在文件中(愚蠢)。不要将文件句柄存储在链接列表中(您最常用的代码路由会杀死您)。利用文件句柄是小整数并使用数组的事实。 realloc()可以在这里提供帮助。

嘿......我在评论中看到其他FreeBSD用户已经插入...无论如何......如果您要在一个过程中尝试保持那么多东西,请查看FreeBSD和kqueue()。