readdir函数解析

函数原型:

struct dirent *readdir(DIR *dirp);

首先纠正一个很多人都错误理解的事实,readdir不是系统调用,它是glibc的封装函数,而且readdir系统调用是存在的,原型如下:

int readdir(unsigend int fd, struct old_linux_dirent *dirp, unsigned int count);

glibc的readdir所调用的系统调用不是readdir而是getdents系统调用。此处说明一下为什么采用封装getdents而不是readdir系统调用,最重要的一个理由是readdir系统调用每次只会读入一个目录项,而getdents会一下子读入尽可能多的目录项至缓冲。我先分析readdir系统调用的实现,具体的代码如下:

复制代码

 1 SYSCALL_DEFINE3(old_readdir, unsigned int, fd,
 2                 struct old_linux_dirent __user *, dirent, unsigned int, count)
 3 {
 4         int error;
 5         struct fd f = fdget(fd);
 6         struct readdir_callback buf = {
 7                 .ctx.actor = fillonedir,
 8                 .dirent = dirent
 9         };
10 
11         if (!f.file)
12                 return -EBADF;
13 
14         error = iterate_dir(f.file, &buf.ctx);
15         if (buf.result)
16                 error = buf.result;
17 
18         fdput(f);
19         return error;
20 }

复制代码

6-9行:设置目录项填充函数为fillonedir,filonedir的具体实现不分析,只需知道每次只填充一个目录项即可(作为替代,将会分析更加复杂的filldir函数)

14行:iterate_dir是vfs的封装函数,该函数调用具体的文件系统的iterate函数填充目录

    注: 3.11之前并不使用iterate作为读目录的函数而是使用readdir函数

总结:readdir系统调用忽略了count参数并且每次只读一个目录项

接下来分析glibc的readdir函数实现,这个过程可能比较复杂,有兴趣的可以看看,首先给出readdir的实现:

复制代码

 1 DIRENT_TYPE *
 2 __READDIR (DIR *dirp)
 3 {
 4   DIRENT_TYPE *dp;
 5   int saved_errno = errno;
 6 
 7 #ifndef NOT_IN_libc
 8   __libc_lock_lock (dirp->lock);
 9 #endif
10 
11   do
12     {
13       size_t reclen;
14 
15       if (dirp->offset >= dirp->size) 
16         {
17           /* We've emptied out our buffer.  Refill it.  */
18 
19           size_t maxread;
20           ssize_t bytes;
21 
22 #ifndef _DIRENT_HAVE_D_RECLEN
23           /* Fixed-size struct; must read one at a time (see below).  */
24           maxread = sizeof *dp;
25 #else
26           maxread = dirp->allocation;
  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值