声明:本文为原创
#####请转贴时保留以下内容######
作者:GTT
请提出宝贵意见Mail:mtloveft@hotmail.com
Linux Version:2.6.33
提示:本文是关于file system 实现的介绍!
这篇文章主要介绍在vfs里创建的第一个目录
上一篇mount之后就有了根目录,那第一个子目录什么时候创建的呢?
同样,kernel在初始化过程中,会创建几个目录。先看下面的代码。
/* * Create a simple rootfs that is similar to the default initramfs */ static int __init default_rootfs(void) { int err;
err = sys_mkdir("/dev", 0755); if (err < 0) goto out;
err = sys_mknod((const char __user *) "/dev/console", S_IFCHR | S_IRUSR | S_IWUSR, new_encode_dev(MKDEV(5, 1))); if (err < 0) goto out;
err = sys_mkdir("/root", 0700); if (err < 0) goto out;
return 0;
out: printk(KERN_WARNING "Failed to create a rootfs\n"); return err; }
|
系统调用 sys_mkdir将创建一个目录。所以系统第一个子目录就是/dev, 之后创建了/dev/console, /root,
为什么创建这些,这些为装载initrd作准备。
下面来介绍第一个子目录的创建。
看看mkdir 的syscall的定义
SYSCALL_DEFINE2(mkdir, const char __user *, pathname, int, mode) { return sys_mkdirat(AT_FDCWD, pathname, mode);//current working directory
}
|
两个参数,一个是目录名,一个是mode,关于稍后介绍,其实也就是访问权限等
之后调用sys_mkdirat系统调用
定义如下
SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, int, mode) { int error = 0; char * tmp; struct dentry *dentry; struct nameidata nd;
error = user_path_parent(dfd, pathname, &nd, &tmp); if (error) goto out_err;
dentry = lookup_create(&nd, 1); error = PTR_ERR(dentry); if (IS_ERR(dentry)) goto out_unlock;
if (!IS_POSIXACL(nd.path.dentry->d_inode)) mode &= ~current_umask(); error = mnt_want_write(nd.path.mnt); if (error) goto out_dput; error = security_path_mkdir(&nd.path, dentry, mode); if (error) goto out_drop_write; error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode); out_drop_write: mnt_drop_write(nd.path.mnt); out_dput: dput(dentry); out_unlock: mutex_unlock(&nd.path.dentry->d_inode->i_mutex); path_put(&nd.path); putname(tmp); out_err: return error; }
|
以上顺次调用了user_path_parent, lookup_create, mnt_want_write, vfs_mkdir。
在以下两篇文章里特意先介绍了user_path_parent
而真正的创建是由方法lookup_create来完成的。调用这个方法时
会传入两个参数:lookup_create(&nd, 1);其中参数nd便是前面文章里提到的变量,
参数1表明要建立一个新目录。
lookup_create的代码如下
/** * lookup_create - lookup a dentry, creating it if it doesn't exist * @nd: nameidata info * @is_dir: directory flag * * Simple function to lookup and return a dentry and create it * if it doesn't exist. Is SMP-safe. * * Returns with nd->path.dentry->d_inode->i_mutex locked. */ struct dentry *lookup_create(struct nameidata *nd, int is_dir) { struct dentry *dentry = ERR_PTR(-EEXIST);
mutex_lock_nested(&nd->path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); /* * Yucky last component or no last component at all? * (foo/., foo/.., /////) */ if (nd->last_type != LAST_NORM) goto fail; nd->flags &= ~LOOKUP_PARENT; nd->flags |= LOOKUP_CREATE | LOOKUP_EXCL; nd->intent.open.flags = O_EXCL;
/* Do the final lookup. */ dentry = lookup_hash(nd); if (IS_ERR(dentry)) goto fail;
if (dentry->d_inode) goto eexist; /* * Special case - lookup gave negative, but... we had foo/bar/ * From the vfs_mknod() POV we just have a negative dentry - * all is fine. Let's be bastards - you had / on the end, you've * been asking for (non-existent) directory. -ENOENT for you. */ if (unlikely(!is_dir && nd->last.name[nd->last.len])) { dput(dentry); dentry = ERR_PTR(-ENOENT); } return dentry; eexist: dput(dentry); dentry = ERR_PTR(-EEXIST); fail: return dentry; }
|
mnt_want_write是对文件系统的写权限访问,文件系统是否准备就绪等。代码就先不贴出来了,以后有一篇专门介绍文件系统权限检查的,可以参考。
vfs_mkdir的代码就很简单了
int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) { int error = may_create(dir, dentry);
if (error) return error; if (!dir->i_op->mkdir) return -EPERM;
mode &= (S_IRWXUGO|S_ISVTX); error = security_inode_mkdir(dir, dentry, mode); if (error) return error;
vfs_dq_init(dir); error = dir->i_op->mkdir(dir, dentry, mode); if (!error) fsnotify_mkdir(dir, dentry); return error; }
|
may_create是对文件系统的权限访问,文件系统
是否可以写,是否可以建子文件夹等等。代码就先不贴出来了,以后有一篇专门介绍文件系统权限检查的,可以参考。
dir->i_op->mkdir就是实际文件系统的创建方法了。
rootfs里dir->i_op注册为&ramfs_dir_inode_operations所以看看
它的定义
static const struct inode_operations ramfs_dir_inode_operations = { .create = ramfs_create, .lookup = simple_lookup, .link = simple_link, .unlink = simple_unlink, .symlink = ramfs_symlink, .mkdir = ramfs_mkdir, .rmdir = simple_rmdir, .mknod = ramfs_mknod, .rename = simple_rename, };
|
所以就直接执行ramfs_create了
执行后的数据结构如下
阅读(1684) | 评论(0) | 转发(0) |