嵌入式linux:readdir()有时会因EFAULT而失败

嵌入式linux:readdir()有时会因EFAULT而失败,linux,readdir,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 *en

我在嵌入式应用程序中遇到了一些
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结构本身可能会被破坏。我在别处没有看到堆损坏的任何证据。

来自
man 2 readdir
页面:

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

这意味着您的结构已损坏

我想我找到了问题所在。opendir/readdir的uClibc实现在目录上执行stat(),然后执行statbuf.st_blksize大小的堆栈alloca()。我的NFS目录是用rsize=512KB装载的,这导致readdir()尝试在堆栈上分配512KB来保存凹痕。我的嵌入式设置在堆栈之间没有太多的空间,所以在某个点上碰到了内存中下面的某个内容并导致了EFAULT


如果我将NFS装载选项更改为rsize=4096,它工作正常。

AFAICT,这不是来自
readdir()
的有效返回。在调用
readdir()
之前,您的(非独立)代码是否真的重置了
errno
?在通话之前或之后,是否还有其他设置?还有,您正在使用哪个libc?是的,我在每次调用时都显式重置errno。将uClibc用于ARM。您的程序是多线程的吗?我不完全确定,但看起来一些旧版本的uClibc(可能使用linuxthreads)没有将
errno
线程设置为本地。请参阅,它是多线程的。我不确定uClibc的确切版本,但我相信它是合理的最新版本。这也是我的想法,但我无法想象是什么腐蚀了它,或者为什么其他一切看起来都很好。我会再挖一些。