文件系统 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; // 从根目录
}