温馨提示×

debian里copendir怎么实现

小樊
38
2026-09-25 06:29:48
栏目: 智能运维

在 Debian(以及一般 Linux/glibc) 里,opendir / closedir / readdir 并不是系统调用,而是 glibc 的库函数,底层最终调用的是 open + getdents64 等系统调用。

下面从“如何使用”和“如何自己实现一个简化版 opendir”两个角度说明。


一、标准用法(直接用 glibc 的 opendir)

#include <dirent.h>
#include <stdio.h>

int main(void) {
    DIR *dir = opendir(".");
    if (!dir) {
        perror("opendir");
        return 1;
    }

    struct dirent *entry;
    while ((entry = readdir(dir)) != NULL) {
        printf("%s\n", entry->d_name);
    }

    closedir(dir);
    return 0;
}

编译:

gcc test.c -o test

二、opendir 在 Debian/glibc 中的实现原理

1. 关键系统调用

函数 说明
open() 打开目录(O_RDONLY
getdents64() 读取目录项
close() 关闭目录

⚠️ 目录不能用 read(),必须用 getdents64


2. glibc 中的核心结构(简化)

struct __dirstream {
    int fd;                  // 目录文件描述符
    char *buf;               // 缓冲区
    size_t buf_size;
    off_t offset;
    struct dirent *ptr;
};

DIR * 实际上就是 struct __dirstream *


三、自己实现一个简化版 opendir(教学用)

1. mydir.h

#ifndef MYDIR_H
#define MYDIR_H

#include <sys/types.h>
#include <dirent.h>

typedef struct {
    int fd;
    char buf[4096];
    size_t pos;
    size_t end;
    struct dirent ent;
} MYDIR;

MYDIR *my_opendir(const char *path);
struct dirent *my_readdir(MYDIR *dir);
void my_closedir(MYDIR *dir);

#endif

2. mydir.c

#include "mydir.h"
#include <fcntl.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>

MYDIR *my_opendir(const char *path) {
    int fd = open(path, O_RDONLY | O_DIRECTORY);
    if (fd < 0)
        return NULL;

    MYDIR *dir = calloc(1, sizeof(MYDIR));
    dir->fd = fd;
    return dir;
}

struct dirent *my_readdir(MYDIR *dir) {
    if (dir->pos >= dir->end) {
        dir->end = syscall(SYS_getdents64, dir->fd, dir->buf, sizeof(dir->buf));
        dir->pos = 0;
        if (dir->end <= 0)
            return NULL;
    }

    struct dirent *d = (struct dirent *)(dir->buf + dir->pos);
    dir->pos += d->d_reclen;
    return d;
}

void my_closedir(MYDIR *dir) {
    close(dir->fd);
    free(dir);
}

3. 使用示例

MYDIR *dir = my_opendir(".");
struct dirent *e;
while ((e = my_readdir(dir)))
    printf("%s\n", e->d_name);
my_closedir(dir);

四、在 Debian 上查看真实实现

dpkg -S opendir

源码位置(glibc):

sysdeps/unix/sysv/linux/opendir.c
sysdeps/unix/sysv/linux/getdents64.c

查看 man:

man 3 opendir
man 2 getdents64

五、总结

  • ✅ Debian 中 opendir 是 glibc 封装
  • ✅ 底层使用 open + getdents64
  • ✅ 自己实现 opendir 本质是“管理 fd + 缓冲区”

如果你是:

  • 写应用:直接用 opendir
  • 写教学/内核/沙箱:可以自己用 getdents64

如果你愿意,我可以:

  • 给你 完全可运行的 demo
  • 对比 opendir vs getdents64
  • 讲 为什么目录不能用 read()

0 踩