嵌入式linux:readdir()有时会失败并使用EFAULT

时间:2013-02-14 10:28:59

标签: linux readdir

我在嵌入式应用中遇到了一些readdir()问题,所以我在应用代码中的方便位置添加了这个自包含测试:

FILE *f;
DIR *d;

f = fopen ("/mnt/mydir/myfile", "r");
printf ("fopen %p\r\n", f);
if (f) fclose(f);

d = opendir ("/mnt/mydir");
printf ("opendir ret %p\r\n", f);
if (d)
{
    struct dirent *entry;
    do
    {
    errno = 0;
    entry = readdir (d);
    printf ("readdir ret %p %s, errno %d %s\r\n", entry, entry ? entry->d_name : "", errno, strerror(errno));
    } while (entry);
    closedir (d);
}

/mnt/mydir是一个NFS挂载(虽然我不确定这是否相关)。在该目录中打开文件的fopen()调用总是成功,并且目录上的opendir()也总是成功。但是,有时(大多数)readdir()会因errno=EFAULT而失败。

我不相信应用程序中的任何其他地方正在使用该目录做任何事情。测试与编写完全一样,所有变量都是本地堆栈范围。

如果我将它作为独立程序运行,它总是成功。

有人可以提供任何可能导致EFAULT的建议吗?我很确定我的DIR指针变量没有被破坏,尽管DIR结构本身可能是我猜的。我没有看到任何其他堆腐败的证据。

2 个答案:

答案 0 :(得分:0)

来自man 2 readdir页面:

       EFAULT Argument points outside the calling process's address space.

这意味着您的结构已损坏

答案 1 :(得分:0)

我想我发现了这个问题。 opendir / readdir的uClibc实现在目录上执行stat(),然后执行大小为statbuf.st_blksize的堆栈alloca()。我的NFS目录以rsize = 512KB挂载,导致readdir()尝试在堆栈上分配512KB来保存凹痕。我的嵌入式设置在堆栈之间没有那么大的空间,所以在某些时候在内存中击中了一些东西并导致了EFAULT。

如果我将我的NFS挂载选项更改为rsize = 4096,则可以正常工作。