5

$ unname -a

Linux crowsnest 2.6.32-28-generic #55-Ubuntu SMP Mon Jan 10 23:42:43 UTC 2011 x86_64 GNU/Linux

$ 人读目录:

描述

readdir() 函数返回一个指向 dirent 结构的指针,该结构表示 dirp 指向的目录流中的下一个目录条目...

..[剪辑]...

readdir_r() 函数是 readdir() 的可重入版本...

...[剪辑]...

返回值

成功时, readdir() 返回一个指向不同结构的指针。(此结构可能是静态分配的;不要尝试释放(3)它。)如果到达目录流的末尾,则返回 NULL 并且不更改 errno。如果发生错误,则返回 NULL 并适当设置 errno。

readdir_r() 函数在成功时返回 0。出错时,它返回一个正的错误号。如果到达目录流的末尾,readdir_r() 返回 0,并在 *result 中返回 NULL。

我对这意味着什么感到困惑,我对该函数的应用是收集一个动态分配的指向结构的指针数组,其中包含有关目录条目的数据,我想知道我是否可以动态分配不同的结构并设置指向它们的指针. 但是这条线接缝说结果永远不应该被free调用,所以我想知道我是否应该分配一个单独的dirent struct,它将成为列表的一部分并将其memcpy到返回的结果上。

我也对上述手册页中的“可能”术语感到困惑。这是否意味着有时它是静态分配的,有时不是。

我(模糊地)熟悉静态变量在 C 中的含义,但不确定所有规则和可能的陷阱。因为我想传递目录中的不同结构,所以我宁愿动态分配它。这是 readdir_r 的用途吗?还是将双指针设置为指向另一个静态分配的 dirent 结构?

而且我不完全确定在这种情况下对于 readdir_r 的重入意味着什么。我对 renetrant 的理解仅来自方案协程,我不确定这将如何应用于读取 unix 目录。

4

3 回答 3

7

该结构可能是静态分配的,可能是线程本地的,也可能是动态分配的。这取决于实施。但无论如何,释放它不是你的,这就是为什么你不能释放它。

readdir_r不为你分配任何东西,你给它一个,分配你喜欢的任何东西,它会填充它。因此,与调用和复制 dir 数据dirent相比,它确实为你节省了一些精力。不过,这readdir不是.readdir_rreaddir

“可重入”实际上是指该函数可以在之前的调用返回之前再次调用。一般来说,这可能意味着来自不同的线程(这是大多数人所说的“线程安全”),来自第一次调用期间发生的信号的处理程序,或者由于递归。但是 C 标准没有线程的概念,所以它提到“可重入”仅表示后两者。Posix 将“线程安全”定义为要求这种形式的重入此外,大多数人所说的线程安全的意思。

在 Posix 中,每个需要线程安全的函数都需要是可重入的,并且readdir_r需要是线程安全的。我认为较弱意义上的重入与 无关readdir_r,因为它不会调用任何可能导致递归的用户代码,并且它不是异步信号安全的,因此也不能从信号处理程序中调用它。

请注意,因为当某些人(Java 程序员)说“线程安全”时,他们的意思是该函数可以由不同线程同时在相同参数上调用,并且将使用锁来正常工作。Posix API 并不意味着线程安全,它们只是意味着可以同时对不同的数据调用该函数。函数使用的任何全局数据都受到锁或其他方式的保护,但参数不必如此。

于 2011-08-23T09:32:09.213 回答
6

第一个问题

这意味着 readdir 可能有这样的东西:

struct dirent *
readdir(DIR *dirp)
{
    static struct dirent;
    /* Do stuff. */

    return &dirent;
}

显然,释放它是非法的(因为你没有通过 获得它malloc)。

该标准并不强迫任何人这样做。一个实现可以使用它自己的机制(也许malloc以后单独使用free)。

第二个问题

“可重入”意味着当我们在内部readdir_r时,可以安全地再次调用该函数(例如从信号处理程序)。例如,readdir不可重入。假设发生这种情况:

  • 你打电话readdir(dir);,它开始修改dirent
  • 在它完成之前,它被中断并且其他人调用它(来自异步上下文)
  • 它的版本修改dirent,返回并且异步上下文继续进行
  • 您的版本返回。包含什么dirent

可重入函数是天赐之物,它们总是可以安全调用。

于 2011-08-23T09:27:59.267 回答
6

这里的规则非常简单——您可以自由地制作数据readdir()返回的副本,但是您不拥有将数据放入的缓冲区,因此您无法执行建议您执行的操作。(即,将数据复制到您自己的缓冲区;不要将指针存储在 readdir 拥有的缓冲区内。)

so I'm wondering if I should allocate a seperate dirent struct which will be part of the list and memcpy it over the returned result- 这正是你应该做的。

I'm also confused by the terminology of "may" in the above man page. does this mean that somtimes it's statically allocated, and sometimes it's not.- 这意味着您不能指望如何管理它,但它会为您管理。细节可能因一个系统而异。

可重入意味着线程安全。readdir() 使用静态条目,使多个线程使用起来不安全,就好像它们各自控制多调用进程一样。readdir_r() 将使用调用者提供的分配空间,让多个线程独立运行。

于 2011-08-23T09:31:12.613 回答