$ uname -a
Linux crowsnest 2.6.32-28-generic #55-Ubuntu SMP Mon Jan 10 23:42:43 UTC 2011 x86_64 GNU/Linux
$ man readdir:
描述
readdir()函数返回一个指向dirent结构的指针,该结构表示由dirp指向的目录stream中的下一个目录条目。
- 使用select()和pipe
- 有人可以在Solaris中解释这个'dirent'结构的定义吗?
- 在卸载的文件上执行mmap()后避免崩溃
- 在线程中select()系统调用?
- 如何编写一个Makefile来编译一个简单的C程序
.. [剪断] …
readdir_r()函数是readdir()的一个可重入版本。
… [剪断] …
返回值
readdir()成功时返回一个指向dirent结构的指针。 (这个结构可能是静态分配的;不要试图释放(3))如果到达目录stream的末尾,则返回NULL,并且errno不会被改变。 如果发生错误,则返回NULL,并适当地设置errno。
readdir_r()函数成功返回0。 出错时,它返回一个肯定的错误号码。 如果到达目录stream的末尾,则readdir_r()返回0,并在* result中返回NULL。
我对这意味着什么感到困惑,我的这个函数的应用是收集一个dynamic分配的指针数组指针与数据有关的目录条目,我想知道我是否可以dynamic分配dirent结构并设置指针。 但这条线接缝说,结果永远不应该被免费调用,所以我想知道是否应该分配一个单独的dirent结构,这将是列表的一部分,memcpy它返回的结果。
在上面的手册页中,我也被“可能”的术语弄糊涂了。 这是否意味着它是静态分配的,有时不是。
我熟悉(含糊地)C中静态variables的意思,但不清楚所有的规则和可能的陷阱。 因为我想通过在目录周围的dirent结构,我宁愿它被dynamic分配。 这是readdir_r是什么? 或者将双指针设置为指向另一个静态分配的dirent结构?
而且我不完全确定readdir_r在这种情况下的重入意味着什么。 我对renetrant的理解只来自于计划协程,我不知道如何适用于读取unix目录。
这里的规则非常简单 – 您可以自由地创建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()将使用调用者提供的分配空间,让多个线程独立工作。
结构可能是静态分配的,它可能是线程本地的,可能是动态分配的。 这取决于实施。 但不管怎么样,这不是你的自由,这就是为什么你不能释放它。
readdir_r
没有为你分配任何东西,你给它一个dirent
,然后分配给它,所以它比你调用readdir
和复制dir数据节省了一些工作量。 这不是readdir_r
的主要目的,但实际上它是从不同线程同时进行调用的能力,而readdir
则无法做到这一点。
实际上,“可重入”的意思是在先前的调用返回之前,可以再次调用该函数。 一般来说,这可能意味着一个不同的线程(这是大多数人所说的“线程安全”),从第一次调用期间发生的信号的处理程序,或由于递归。 但是C标准没有线程的概念,所以只提到后两者的意思。 Posix定义了“线程安全”来要求这种形式的重入,此外,大多数人认为是线程安全的。
在Posix中,要求线程安全的每个函数都必须是可重入的,并且readdir_r
必须是线程安全的。 我认为在较弱意义上的重入与readdir_r
无关,因为它不调用任何可能导致递归的用户代码,也不是异步信号安全的,所以它不能从信号处理程序中调用。
要小心,因为当有些人(Java程序员)说“线程安全”时,它们表示这个函数可以被同一个参数上的不同线程同时调用 ,并且会使用锁来正确工作。 Posix API并不是线程安全的,它只是意味着可以同时调用不同的数据。 该函数使用的任何全局数据都受锁或其他方式的保护,但参数不一定是。
这意味着readdir可能有这样的东西:
struct dirent * readdir(DIR *dirp) { static struct dirent; /* Do stuff. */ return &dirent; }
很明显,它是非法的( 因为你没有通过malloc
获得它 )。
标准并不强迫任何人这样做。 一个实现可以使用自己的机制(也许是malloc
,后来free
)。
“可重入”意味着,当我们在readdir_r
, 可以再次安全地调用函数 (例如从信号处理程序中)。 例如, readdir
不可重入。 假设发生这种情况:
readdir(dir);
并开始修改dirent
dirent
,返回和异步上下文 dirent
包含什么? 可重入函数是天赐之物,它们总是可以安全地调用。