readdir() vs readdir_r()
As a function to read a directory
readdir()
/ readdir_r()
Two functions are provided by the standard library.
If you are using single thread, you can use `readdir ()`
, but
If you use `readdir_r ()`
which is thread-safe for multithreading
It is reasonable to think that it is good.
In conclusion, `readdir_r ()`
should not be used.
In the case of multithreading, it is better to use `readdir () + exclusive control`
.
Let's see why this is the case. First, check the specifications of readdir () and readdir_r ().
POSIX.1-2008 states that the thread safety of `readdir ()`
is not guaranteed.
DESCRIPTION The readdir() function need not be thread-safe.
Reference: readdir, readdir_r --read a directory
2.9.1 Thread-Safety All functions defined by this volume of POSIX.1-2017 shall be thread-safe, except that the following functions1 need not be thread-safe. readdir()
Reference: The Open Group Base Specifications Issue 7, 2018 edition --2.9.1 Thread-Safety
int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
readdir_r()
Reads the next directory entry from the directory stream dirp
The entry is stored and returned in the buffer allocated by the caller pointed to by the entry.
A pointer to the returned entry is stored in * result.
When the end of the directory stream is reached, NULL is stored in * result.
In Linux, the dirent structure is defined as follows.
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 file system types */
char d_name[256]; /* filename */
};
POSIX.1 does not specify the size of the d_name field (* 1) There may be other non-standard fields after d_name in the dirent struct, so If you use readdir_r () in a portable application, pass the buffer to entry It should be assigned as follows:
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);
(* 1) In Solaris, d_name is defined as d_name [1].
However, this above measure is due to the ambiguity of the _PC_NAME_MAX constant definition. It has been pointed out that it will lead to buffer overflow.
In the current POSIX.1 specification (POSIX.1-2008), readdir() is not required to be thread-safe. However, in modern implementations (including the glibc implementation), concurrent calls to readdir() that specify different directory streams are thread-safe. In cases where multiple threads must read from the same directory stream, using readdir() with external synchronization is still preferable to the use of the deprecated readdir_r(3) function. It is expected that a future version of POSIX.1 will require that readdir() be thread- safe when concurrently employed on different directory streams.
Reference: readdir (3) --Linux manual page
Also, readdir_r () and readdir64_r () have been deprecated in glibc 2.24.
- The readdir_r and readdir64_r functions have been deprecated. It is recommended to use readdir and readdir64 instead.
Reference: Adhemerval Zanella --The GNU C Library version 2.24 is now available
From the above, instead of using `readdir_r ()`
even in multithreading,
readdir() +exclusion control
Should be considered for use.
http://mkosaki.blog46.fc2.com/blog-entry-1237.html http://blog.gachapin-sensei.com/archives/618834.html
Recommended Posts