Skip to content

文件系统 API

本文档介绍 NoobKernel 文件系统模块的主要 API。

VFS 接口

#include <fs/vfs.h>

// 打开文件
struct file *vfs_open(struct dentry *dentry, u32 flags);

// 关闭文件
int vfs_close(struct file *file);

// 读取文件
ssize_t vfs_read(struct file *file, void *buf, size_t count);

// 写入文件
ssize_t vfs_write(struct file *file, const void *buf, size_t count);

// 设置文件位置
loff_t vfs_lseek(struct file *file, loff_t offset, int whence);

// 创建文件
int vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode);

// 创建目录
int vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode);

// 删除目录
int vfs_rmdir(struct inode *dir, struct dentry *dentry);

// 删除文件
int vfs_unlink(struct inode *dir, struct dentry *dentry);

// 重命名
int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
               struct inode *new_dir, struct dentry *new_dentry);

// 挂载根文件系统
int vfs_mount_root(struct file_system_type *type, const char *source);

inode 操作

#include <fs/inode.h>

// 分配 inode
struct inode *inode_alloc(struct super_block *sb);

// 释放 inode
void inode_free(struct inode *inode);

// 获取 inode(从缓存或创建)
struct inode *inode_get(struct super_block *sb, ino_t ino);

// 释放 inode 引用
void inode_put(struct inode *inode);

// 标记 inode 为脏
void inode_dirty(struct inode *inode);

// 写入 inode
int inode_write(struct inode *inode);

dentry 操作

#include <fs/dentry.h>

// 分配 dentry
struct dentry *dentry_alloc(struct dentry *parent, struct super_block *sb,
                            const char *name);

// 释放 dentry
void dentry_free(struct dentry *dentry);

// 查找 dentry
struct dentry *dentry_lookup(struct super_block *sb, struct dentry *parent,
                             struct qstr *name);

// 增加 dentry 引用
void dentry_get(struct dentry *dentry);

// 释放 dentry 引用
void dentry_put(struct dentry *dentry);

// 创建根 dentry
struct dentry *dentry_root(struct super_block *sb);

file 操作

#include <fs/file.h>

// 分配 file 结构
struct file *file_alloc(void);

// 释放 file 结构
void file_free(struct file *file);

// 打开文件
struct file *file_open(struct dentry *dentry, u32 flags);

// 关闭文件
int file_close(struct file *file);

// 读取
ssize_t file_read(struct file *file, void *buf, size_t count);

// 写入
ssize_t file_write(struct file *file, const void *buf, size_t count);

// 设置位置
loff_t file_lseek(struct file *file, loff_t offset, int whence);

路径解析

#include <fs/namei.h>

// 路径查找
int vfs_path_lookup(const char *path, struct dentry *base,
                    struct dentry **result);

示例

struct dentry *dentry;
int ret = vfs_path_lookup("/home/user/file.txt", NULL, &dentry);
if (ret < 0) {
    errorf("Path not found");
    return ret;
}

文件描述符表

#include <fs/fd_table.h>

// 分配 fd 表
struct fd_table *fd_table_alloc(void);

// 释放 fd 表
void fd_table_free(struct fd_table *table);

// 分配 fd 号
int fd_alloc(struct fd_table *table);

// 释放 fd 号
void fd_free(struct fd_table *table, int fd);

// 获取文件
struct file *fd_get(struct fd_table *table, int fd);

// 设置文件
int fd_set(struct fd_table *table, int fd, struct file *file);

打开标志

#define O_RDONLY    0x0000
#define O_WRONLY    0x0001
#define O_RDWR      0x0002
#define O_CREAT     0x0040
#define O_TRUNC     0x0200
#define O_APPEND    0x0400

lseek whence

#define SEEK_SET    0   // 从文件开始
#define SEEK_CUR    1   // 从当前位置
#define SEEK_END    2   // 从文件末尾

文件类型和权限

// 文件类型
#define S_IFMT      0170000
#define S_IFREG     0100000  // 普通文件
#define S_IFDIR     0040000  // 目录
#define S_IFCHR     0020000  // 字符设备
#define S_IFBLK     0060000  // 块设备
#define S_IFLNK     0120000  // 符号链接

// 权限位
#define S_ISUID     04000
#define S_ISGID     02000
#define S_ISVTX     01000
#define S_IRWXU     00700
#define S_IRUSR     00400
#define S_IWUSR     00200
#define S_IXUSR     00100
#define S_IRWXG     00070
#define S_IRWXO     00007

使用示例

打开和读取文件

// 解析路径
struct dentry *dentry;
int ret = vfs_path_lookup("/test.txt", NULL, &dentry);
if (ret < 0) {
    return ret;
}

// 打开文件
struct file *file = vfs_open(dentry, O_RDONLY);
if (!file) {
    dentry_put(dentry);
    return -ENOENT;
}

// 读取数据
char buf[1024];
ssize_t n = vfs_read(file, buf, sizeof(buf));
if (n > 0) {
    infof("Read %d bytes", n);
}

// 关闭文件
vfs_close(file);
dentry_put(dentry);

创建文件

// 获取父目录
struct dentry *parent;
vfs_path_lookup("/home", NULL, &parent);

// 创建 dentry
struct dentry *new_dentry = dentry_alloc(parent, parent->d_sb, "newfile.txt");

// 创建文件
int ret = vfs_create(parent->d_inode, new_dentry, S_IFREG | 0644);
if (ret < 0) {
    dentry_free(new_dentry);
    dentry_put(parent);
    return ret;
}

dentry_put(new_dentry);
dentry_put(parent);

写入文件

struct file *file = vfs_open(dentry, O_WRONLY | O_CREAT);
if (!file) {
    return -ENOENT;
}

const char *data = "Hello, World!";
ssize_t n = vfs_write(file, data, strlen(data));

vfs_close(file);

错误码

文件系统相关错误码:

#define ENOENT  3   // 文件不存在
#define EEXIST  4   // 文件已存在
#define EISDIR  21  // 是目录
#define ENOTDIR 20  // 不是目录
#define EACCES  8   // 权限拒绝

最佳实践

检查返回值

struct file *file = vfs_open(dentry, flags);
if (!file) {
    return -ENOENT;
}

释放引用

// 获取引用
dentry_get(dentry);

// 使用 dentry
...

// 释放引用
dentry_put(dentry);

正确处理路径

// 处理绝对路径
if (path[0] == '/') {
    base = current->pwd;  // 从当前目录
} else {
    base = root_dentry;   // 从根目录
}