貌似这东西英文的网上一抓一大把,不过绝大部分都是基于2.4.x的内核的,而那么早的操作系统我没下载到。
于是就用手里3.11的ubuntu开始了写文件系统。
过程真是痛苦。。。。
为了不然后人继续为这个题目痛苦,所以有了这篇博客。
作为一个初学者,我的一些理解估计是有问题的,欢迎批评指正。
首先推荐几个地方:
- http://lxr.free-electrons.com/source linux的源码,提供了查找变量函数的定义使用,以及不同版本之间的对比。
- https://github.com/mkatiyar/testfs 一哥们写的vfs的源码,估计版本是2.4.x
- http://www.geocities.ws/ravikiran_uvs/articles/rkfs-old.html 一个非常简单的vfs源码,也是2.4.x的源码
- http://lxr.free-electrons.com/source/Documentation/filesystems/vfs.txt 官方文档
- 还有我在写vfs时参考的一本书《linux操作系统实验教程》罗 宇,等.电子工业出版社
我的环境:
Oracle VM VirtureBox---Linux 3.11(ubuntu)
准备工作:
了解super_block, super_operations, inode, inode_operations, file_operations, dentry_operations
详见推荐[4],以及可参考的中文版 http://blog.csdn.net/ruixj/article/details/4940217注意磁盘上结构的组织
程序的组织流程:
//super.c
static int testfs_fill_super(struct super_block*sb, void *data, int silent)
{
...
extern int register_filesystem(struct file_system_type * testfs_type);
...
}
//super.c
static struct file_system_type testfs_type = {
.owner = THIS_MODULE,
.name = "testfs",
.mount = testfs_mount,
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV,
};
//super.c
struct dentry *testfs_mount(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data)
{
return mount_bdev(fs_type, flags, dev_name, data, testfs_fill_super);
}
//super.c
static int testfs_fill_super(struct super_block*sb, void *data, int silent)
{
...
sb->s_op= &testfs_sops;
root = testfs_iget(sb,TESTFS_ROOT_INODE(ts));
...
}
//super.c
static const struct super_operations testfs_sops = {
.alloc_inode = testfs_alloc_inode,
.write_inode = testfs_write_inode,
.destroy_inode = testfs_destroy_inode,
.put_super = testfs_put_super,
};
//inode.c
struct inode *testfs_iget(struct super_block *sb, unsigned int ino){
...
if (S_ISREG(inode->i_mode)) {
inode->i_op = &testfs_file_inode_operations;
inode->i_fop = &testfs_file_operations;
} else if (S_ISDIR(inode->i_mode)) {
inode->i_op = &testfs_dir_inode_operations;
inode->i_fop = &testfs_dir_operations;
} else if (S_ISLNK(inode->i_mode)) {
inode->i_op = &testfs_symlink_inode_operations;
}
...
}
//dir.c
const struct file_operations testfs_dir_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
.iterate = testfs_iterate,
};
//namei.c
const struct inode_operations testfs_dir_inode_operations = {
.create = testfs_create,
.lookup = testfs_lookup,
.unlink = testfs_unlink,
.mkdir = testfs_mkdir,
.rmdir = testfs_rmdir,
.symlink = testfs_symlink,
.setattr = testfs_setattr,
.permission = testfs_permission,
};
//file.c
const struct inode_operations testfs_file_inode_operations = {
.setattr = testfs_setattr,
.permission = testfs_permission,
};
const struct file_operations testfs_file_operations = {
.read = do_sync_read,
.write = do_sync_write,
.aio_read = generic_file_aio_read,
.aio_write = generic_file_aio_write,
.open = generic_file_open,
};
设备创建与删除
文件的挂载(当作设备)
#dd if=/dev/zero of=/tmpfile bs=1k count=200
#losetup /dev/loop0 /tmpfile
#losetup –d /dev/loop0
格式化设备(C实现)
1. 取得分区大小并打,开设备
2. 为各种数据开辟缓冲区
3. 处理超级块与根节点
2. 为各种数据开辟缓冲区
3. 处理超级块与根节点
a) 分配空闲索引节点;
b) 写入.与..两个目录项
4. 将缓冲内容写入文件
附效果图纪念~