在下面的例子中,哪一个更好? fread()还是mmap()?

时间:2015-05-25 06:12:28

标签: c linux memory mmap fread

我想通过一个进程读取两个文件,第一个文件大约是2G,第二个文件大约是20M。 它们看起来像这样:

1   1217907
1   1217908
1   1517737
1   2
1   3
1   4
1   5

现在我计划将整个文件读入内存,然后使用strtok_r()获取每个num的值并将它们存储在数据结构数组中。 4个进程几乎可以在同一台计算机上同时读取这两个文件。计算机是64位,物理内存可能是4G甚至更少。我的问题是,哪种方法更有效? fread()mmap()

这是我阅读整个文件程序的关键部分(因为有人想看到它,但我不知道它是否与我的问题有关):

typedef struct My_Edge
{
int first;
int second;
}Edge;

Edge *myEdge;

int Read_Whole_File()
{

fseek(wholeFile, 0, SEEK_END);

long int fileSize=ftell(wholeFile);

char *buffer=malloc(sizeof(char)*fileSize+1);

fseek(wholeFile, 0, SEEK_SET);

fread(buffer, 1, fileSize, wholeFile);

char *string_first;
char *string_second;
char *save_ptr;

int temp_first;
int temp_second;

string_first = strtok_r(buffer, " \t\n", &save_ptr);
int i=0;

int temp_edge_num;
Edge *temp_edge;

while (string_first != NULL)
{
    temp_first = atoi(string_first);

    string_second = strtok_r(NULL," \t\n",&save_ptr);

    temp_second = atoi(string_second);

    if(i>=my_edge_num)
    {
        temp_edge_num = i + EDGE_NUM_ADJUST;

        temp_edge = realloc(myEdge, sizeof(Edge)*temp_edge_num);
        if(temp_edge)
        {
            myEdge = temp_edge;
        }
        my_edge_num = temp_edge_num;

    }

    if((p_id[temp_first]==*partitionID)||(p_id[temp_second]==*partitionID))
    {
        myEdge[i].first=temp_first;
        myEdge[i].second=temp_second;
        i++;
    }

    string_first = strtok_r(NULL, " \t\n", &save_ptr);

}

return 0;
}

现在我正在尝试使用mmap(),但当我使用strtok_r() tp处理由mmap()处理的var时,它有EXC_BAD_ACCESS:

char * buffer;

struct stat fileStat;

fstat(wholeFile, &fileStat);

buffer = mmap(NULL, fileStat.st_size, PROT_READ, MAP_SHARED, wholeFile, 0);

char *string_first;
char *string_second;
char *save_ptr;

int temp_first;
int temp_second;

string_first = strtok_r(buffer, " \t\n", &save_ptr);//EXC_BAD_ACCESS here, the content of buffer is correct.

1 个答案:

答案 0 :(得分:1)

  

我的问题是,哪种方法更有效? fread()或mmap()?

首先,让我们看看fread和mmap如何在linux上运行:
fread
让我们说我们使用ext4文件系统(没有加密), fread使用一些内部缓冲区,如果没有数据,则 它调用readread执行"系统调用" 过了一段时间我们跳到:
FS / read_write.c :: vfs_read 经过更多的工作我们到达 毫米/ filemap.c :: generic_file_read_iter

在这个函数中我们填写inode页面缓存并读取到此 页面缓存数据。

所以我们和" mmap"基本相同。确实

fread案例中我们没有直接的区别 使用页面,我们只是从内核复制部分数据 inode页面缓存到用户空间缓冲区,
mmap我们直接在程序中有页面缓存 记忆空间。当{" inode页面缓存中没有页面" 我们只是阅读它,但在fread导致"页面错误", 然后我们就读了它。

两种变体都使用"提前读取页面"战略。 可能的差异可能在"缓存"政策, 我们可以在" mmap"中控制它mmap的案例和madvise的旗帜。

所以我认为答案是"它们在序列读取速度方面与你的速度几乎相同"。