是readdir,还是readdir_r
readdir的原型如下:
struct dirent *readdir(DIR *dirp);
因为内部使用了静态数据,所以readdir被认为不是线程安全的函数,POSIX[i]标准这样描述:
The application shall not modify the structure to which the return value of readdir() points, nor any storage areas pointed to by pointers within the structure. The returned
pointer, and pointers within the structure, might be invalidated or the structure or the storage areas might be overwritten by a subsequent call to readdir() on the same directory stream. They shall not be affected by a call to readdir()
on a different directory stream.
If a file is removed from or added to the directory after the most recent call to opendir() or rewinddir(),whether a subsequent call to readdir() returns
an entry for that file is unspecified.
The readdir() function need not be thread-safe.
因此才有了readdir_r函数的出现,它的原型如下:
int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
readdir_r将返回结果填充到调用者提供的entry缓冲区中,保证了它的线程安全性。
然而,在GNU的官方文档[ii]中,有下面的描述:
In POSIX.1-2008, readdir is not thread-safe. In the GNU C Library implementation, it is safe to call readdir concurrently on different dirstreams, but multiple threads accessing the
same dirstream result in undefined behavior. readdir_r is a fully thread-safe alternative, but suffers from poor portability (see below).
It is recommended that you use readdir, with externallocking if multiple threads access the same dirstream.
Portability Note:
It is recommended to use readdir instead of readdir_r for the following reasons:
On systems which do not define NAME_MAX, it may not be possible to use readdir_r safely because the caller does not specify the length of the buffer for the directory entry.
On some systems,readdir_r cannot read directory entries with very long names. If such a name is encountered, the GNU C Library implementation of readdir_r returns with an error code
of ENAMETOOLONG after the final directory entry has been read. On other systems, readdir_r may return successfully, but the d_name member may not be NUL-terminated or may be truncated.
POSIX-1.2008 does not guarantee that readdir is thread-safe, even when access to the same dirstream is serialized.
But in current implementations(including the GNU C Library), it is safe to call readdir concurrently on different dirstreams, so there is no need to use readdir_r in most multi-threaded programs.
In the rare case that multiple threads need to read from the same dirstream, it is still better to use readdir and external synchronization.
It is expected that future versions of POSIX will obsolete readdir_r and mandate the level of thread safety for readdir which is provided by the GNU C Library and other implementations
today.
尽管POSIX中不保证readdir是线程安全的,但是在目前的实现中(包括GUN C库),在不同的dirstream上(dirp)同时调用readdir能够保证是安全的。因此,多线程程序中其实没必要使用readdir_r,即使在极少场景下,多个线程中需要使用相同的dirstream时,使用readdir以及外部同步手段(加锁),也会是更好的选择。预计在未来版本的POSIX标准中,将会废弃readdir_r。
除了线程安全方面的考虑,没必要使用readdir_r之外,readdir_r还有其他可移植上的缺点,比如某些系统上readdir_r无法处理有很长名字的目录项。
而且,结构体dirent中只有d_name是在POSIX中有明确规定的,它长度还是未指定的(在Linux中,结构体dirent中的d_name,具有明确的数组长度,为256),因此,某些系统中,为了使用readdir_r,必须像下面这样分配entry的内存:
name_max = pathconf(dirpath, _PC_NAME_MAX);
if (name_max == -1) /* Limit not defined, or error */
name_max = 255; /* Take a guess */
len = offsetof(struct dirent, d_name) + name_max + 1;
entryp = malloc(len);
但是这种方式也有问题[iii]。
因此,结论就是:
只要不是多个线程使用相同的dirstream,就尽可能的使用readdir,它其实更简单且更安全。
参考:
http://pubs.opengroup.org/onlinepubs/9699919799/
https://www.gnu.org/software/libc/manual/html_mono/libc.html#Reading_002fClosing-Directory
http://elliotth.blogspot.co.uk/2012/10/how-not-to-use-readdirr3.html
[i] http://pubs.opengroup.org/onlinepubs/9699919799/
[ii] https://www.gnu.org/software/libc/manual/html_mono/libc.html#Reading_002fClosing-Directory
[iii] elliotth's blog: How (not) to usereaddir_r(3):http://elliotth.blogspot.co.uk/2012/10/how-not-to-use-readdirr3.html
是readdir,还是readdir_r的更多相关文章
- C++ readdir、readdir_r函数
readdir, readdir_r - 读一个目录 readdir函数: struct dirent *readdir(DIR *dirp); The data returned by read ...
- Thinkphp拖拽上传文件-使用webuploader插件(自己改动了一些地方)——分片上传
html页面: <!DOCTYPE html> <html class="js cssanimations"> <head> <meta ...
- Linux c readdir是非线程安全,需用readdir_r,要注意用静态变量当做返回值的函数的非线程安全性
readdir函数: struct dirent *readdir(DIR *dirp); The data returned by readdir() may be overwritten by ...
- readdir_r()读取目录内容
readdir()在多线程操作中不安全,Linux提供了readdir_r()实现多线程读取目录内容操作. #include <stdio.h> #include <stdlib.h ...
- PHP之readdir()函数
最近在学习php文件操作的相关知识,记录一下readdir()函数其中的一个要注意的点 1. 在$temp=readdir($handle)函数中 readdir获取的是文件名和$handle中的文件 ...
- 关于readdir返回值中struct dirent.d_type的取值有关问题(转)
关于readdir返回值中struct dirent.d_type的取值问题 原网页链接 http://www.gnu.org/software/libc/manual/html_node/Direc ...
- 目录操作函数opendir、readdir和closedir
首先,明确一个类型DIR的含义: #include <dirent.h> DIR A type representing a directory stream. DIR是在目录项格式 ...
- (转)PHP自定义遍历目录下所有文件dir(),readdir()函数
方法一:使用dir()遍历目录 dir()函数,成功时返回Directory类实例 PHP dir() 语法格式为: dir(directory);//directory为需要显示文件名的目录名称,可 ...
- oendir(),readdir(),closedir() 打开/读取/关闭目录
目录操作 当目标是目录而不是文件的时候,ls -l的结果会显示目录下所有子条目的信息,怎么去遍历整个目录呢?答案马上揭晓! 1. 打开目录 功能:opendir()用来打开参数name指定的目录,并返 ...
随机推荐
- jS生成二叉树,二叉树的遍历,查找以及插入
js递归,二叉树的操作 //递归算法n次幂 function foo(n) { if (n == 1) { return 1; } else { return n * foo(n - 1); } } ...
- HDU 4280 Island Transport(dinic+当前弧优化)
Island Transport Description In the vast waters far far away, there are many islands. People are liv ...
- 洛谷P1470 最长前缀
P1470 最长前缀 Longest Prefix 题目描述 在生物学中,一些生物的结构是用包含其要素的大写字母序列来表示的.生物学家对于把长的序列分解成较短的序列(即元素)很感兴趣. 如果一个集合 ...
- PHP--反射的方法
反射,直观理解就是根据到达地找到出发地和来源.比如,一个光秃秃的对象,我们可以仅仅通过这个对象就能知道它所属的类.拥有哪些方法. 反射是指�php运行状态中,扩展分析PHP程序,导出或提出关于类.方法 ...
- 引用CDN内容的方法总结
1.1.1 摘要 CDN相信大家都听说过,甚至使用过相关的技术,也许有些人会回答“没有听说过和使用过该技术”,真的是这样吗? CDN的全称是Content Delivery Network,即内容分发 ...
- Django静态文件以及模板文件的配置 jQuery v1.12.4
1.配置模板的路径 TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os. ...
- gb2312的6763个汉字
0a啊阿埃挨哎唉哀皑癌蔼矮艾碍爱隘鞍氨安俺按暗岸胺案肮昂盎凹敖熬翱袄傲奥懊澳芭捌扒叭吧笆八疤巴拔跋靶把耙坝霸罢爸白柏百摆佰败拜稗斑班搬扳般颁板版扮拌伴瓣半办绊邦帮梆榜膀绑棒磅蚌镑傍谤苞胞包褒剥薄雹保堡 ...
- 【JZOJ3296】【SDOI2013】刺客信条(assassin)
╰( ̄▽ ̄)╭ Description 故事发生在1486 年的意大利,Ezio 原本只是一个文艺复兴时期的贵族,后来因为家族成员受到圣殿骑士的杀害,决心成为一名刺客.最终,凭借着他的努力和出众的天赋 ...
- oracle 处理表的一列
---删除一列和数据一起删除了. ALTER TABLE 表名 DROP COLUMN 列名; ---添加一列 alert table 表名 add column 列名; ---只删除一列的数据 没有 ...
- 【水滴石穿】react-native-aze
说个题外话,早上打开电脑的时候,电脑变成彩色的了,锅是我曾经安装的一个chrome扩展,没有经过我的同意开启了 (也许是昨天迷迷糊糊开启了) 上午运行项目都不成功,还以为被黑客攻击了---然后下午就排 ...