Chinaunix首页 | 论坛 | 博客
  • 博客访问: 629356
  • 博文数量: 120
  • 博客积分: 2284
  • 博客等级: 大尉
  • 技术积分: 1330
  • 用 户 组: 普通用户
  • 注册时间: 2011-01-25 10:49
个人简介

http://guliqun1983.blog.163.com/blog/static/501116852011730535314/

文章分类
文章存档

2013年(23)

2012年(23)

2011年(74)

分类: LINUX

2013-04-24 10:30:40

声明:本文为原创
#####请转贴时保留以下内容######
作者GTT
本文档归属http://oldtown.cublog.cn/.转载请注明出处!
请提出宝贵意见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) |
给主人留下些什么吧!~~