概述:
1 readdir_r函数,是readdir函数的可重入版本,也就是线程安全的。
2 readdir函数使用静态数据,因而不可重入,即不是线程安全的。
readdir_r()就是采用局部变量保存数据:
int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
The readdir_r() function returns 0 on success. On error, it returns apositive error number (listed under ERRORS). If the end of the directory stream is reached, readdir_r() returns 0, and returns NULL in*result.
readdir_r() 函数是 readdir() 函数可重入版本。
1 它从目录流dirp 里读取下一个目录项;
2 通过调用者分配的缓存区 entry返回 ;
3 返回条目的指针被放置于 *result 里,如果目录流到达结尾,那么把*result 设置为 NULL。当目录被实际读取时,readdir_r()函数将标记目录的st_atime字段的更新
注:在Linux stat函数中,用st_atime表示文件数据最近的存取时间(last accessed time);用st_mtime表示文件数据最近的修改时间(last modified time);使用st_ctime表示文件i节点数据最近的修改时间(last i-node's status changed time)。这种方式可以避免返回包含空名称的目录项。为每个实际的读操作缓冲多个目录条目;
与readdir区别参考:https://bbs.csdn.net/topics/390491842
1 readdir()返回的指针可能被统一目录流上 的另一个readdir调用所覆盖,但是不会对另一个目录流上的readdir()调用覆盖。
2 如果opendir或者rewinddir()之后对目录进行删除或者添加文件,readdir()能否访问到新增减文件是未知的。
3 调用fork()时,父进程和子进程如果同时调用readdir()、rewinddir()、seekdir(),结果都是是不可预期的。
4 readdir()使用静态数据,因而不能重入,不能重入的函数也就不是线程安全的。
参考结构:
while(readdir(pDir));
while (!readdir_r(dirp, &entry, &result) && result);
补充说明:
struct dirent {
ino_t d_ino; /* inode number 索引节点号*/
off_t d_off; /* not an offset; see NOTES 在目录文件中的偏移*/
unsigned short d_reclen; /* length of this record 文件名长*/
unsigned char d_type; /*type of file; not supported by all filesystem types 文件类型*/
char d_name[256]; /* filename 文件名,最长255字符*/
};
d_type的值为:
DT_BLK This is a block device.
DT_CHR This is a character device.
DT_DIR This is a directory.
DT_FIFO This is a named pipe (FIFO).
DT_LNK This is a symbolic link.
DT_REG This is a regular file.
DT_SOCK This is a UNIX domain socket.
DT_UNKNOWN The file type is unknown.
返回值:
需要检查错误的时候,应该在调用readdir()前对errno设置为0,如果返回时非零,就会报错。
成功完成后,readdir()将返回指向struct dirent类型对象的指针。当遇到错误时,应返回空指针,并设置errno来指示错误。当遇到目录的末尾时,应返回空指针,并且不更改errno。
如果成功,readdir_r()函数将返回0;否则,将返回一个错误编号来指示错误。
example:
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
static void lookup(const char *arg)
{
DIR *dirp;
struct dirent *dp;
if ((dirp = opendir(".")) == NULL) {
perror("couldn't open '.'");
return;
}
do {
errno = 0;//errno 是记录系统的最后一次错误代码。代码是一个int型的值,在errno.h中定义。
if ((dp = readdir(dirp)) != NULL) {
if (strcmp(dp->d_name, arg) != 0)
continue;
(void) printf("found %s\n", arg);
(void) closedir(dirp);
return;
}
} while (dp != NULL);
if (errno != 0)
perror("error reading directory");
else
(void) printf("failed to find %s\n", arg);
(void) closedir(dirp);
return;
}
int main(int argc, char *argv[])
{
int i;
for (i = 1; i < argc; i++)
lookup(arvg[i]);
return (0);
}
使用建议:
1 readdir()函数应该与opendir()、closedir()和rewinddir()一起使用,以检查目录的内容。
2 readdir_r()函数是线程安全的,应该在用户提供的缓冲区中返回值,而不是使用可能被每次调用覆盖的静态数据区域。
由于readdir()在检测到错误和遇到目录末尾时返回NULL,因此需要告知差异的应用程序必须在调用之前将errno设置为0,并检查是否返回NULL。由于函数在第二种情况下不能更改errno,并且在第一种情况下必须将其设置为非零值,所以在调用返回NULL后的0值errno表示目录结束。
整理所得,欢迎指正!