linux创建根⽬录代码,Linux⽂件系统之⽬录的建⽴⼀:前⾔
在⽤户空间中,建⽴⽬录所⽤的API为mkdir().它在内核中的系统调⽤⼊⼝是sys_mkdir().今天跟踪⼀下
函数来分析linux⽂件系统中⽬录的建⽴过程.
⼆:sys_mkdir()
Sys_mkdir()对应的代码如下:
asmlinkage long sys_mkdir(const char __user * pathname, int mode)
{
int error = 0;
char * tmp;
//把⽤户空间的值copy到内核空间
tmp = getname(pathname);
error = PTR_ERR(tmp);
if (!IS_ERR(tmp)) {
struct dentry *dentry;
struct nameidata nd;
//先查到它的⽗⽬录,看⽗⽬录是否存在
error = path_lookup(tmp, LOOKUP_PARENT, &nd);
if (error)
goto out;
//寻⼦结点的dentry. 如果没有,则新建之
dentry = lookup_create(&nd, 1);
error = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
if (!IS_POSIXACL(nd.dentry->d_inode))
mode &= ~current->fs->umask;
//与具体的⽂件系统相关的部份
error = vfs_mkdir(nd.dentry->d_inode, dentry, mode);
//减少dentry的引⽤计数
dput(dentry);
}
up(&nd.dentry->d_inode->i_sem);
//释放临时内存
out:
putname(tmp);
}
return error;
}
这个函数⾥⾯有⼏个重要的⼦函数. path_lookup()在前⼀篇⽂章中已经分析过了.如果不太了解,请参阅相关的部份. lookup_create()的代码如下:
{
struct dentry *dentry;
//防⽌并发操作,获得信号量
down(&nd->dentry->d_inode->i_sem);
dentry = ERR_PTR(-EEXIST);
//如果之前的查过程失败
if (nd->last_type != LAST_NORM)
goto fail;
//去掉LOOKUP_PARENT标志
nd->flags &= ~LOOKUP_PARENT;
//在缓存中寻相应的dentry.如果没有。则新建之
dentry = lookup_hash(&nd->last, nd->dentry);
//创建或者查失败
if (IS_ERR(dentry))
goto fail;
//如果不是建⽴⼀个⽬录⽽且⽂件名字不是以0结尾
//出错退出
if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
preparedstatement原理goto enoent;
return dentry;
enoent:
dput(dentry);
dentry = ERR_PTR(-ENOENT);
javascript教程资料fail:
return dentry;
}
static struct dentry * __lookup_hash(struct qstr *name, struct dentry * base, struct nameidata *nd) {
struct dentry * dentry;
struct inode *inode;
int err;
inode = base->d_inode;
//检查是否有相关的权限
err = permission(inode, MAY_EXEC, nd);
dentry = ERR_PTR(err);
if (err)
goto out;
/*
* See if the low-level filesystem might want
* to use its own hash..
*/
//如果⾃定义了hash计算
if (base->d_op && base->d_op->d_hash) {
err = base->d_op->d_hash(base, name);
dentry = ERR_PTR(err);
if (err < 0)
goto out;
}
//从缓存中寻
dentry = cached_lookup(base, name, nd);
if (!dentry) {
/
/如果缓存中没有相关项。则新建之
struct dentry *new = d_alloc(base, name);
dentry = ERR_PTR(-ENOMEM);
if (!new)
goto out;
//到具体的⽂件系统中查
dentry = inode->i_op->lookup(inode, new, nd);
if (!dentry)
else
dput(new);
}
out:
return dentry;
}
值得注意的是:经过上述的操作,返回的dentry有可能是原本就存在的.对这种情况是怎么排除的呢?继续看sys_mkdir()的另⼀个⼦函数:int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
//对异常情况的排除和权限的检查
int error = may_create(dir, dentry, NULL);
if (error)
return error;
//如果⽗结点不允许mkdir操作
if (!dir->i_op || !dir->i_op->mkdir)
dede手机模板带会员中心
return -EPERM;
mode &= (S_IRWXUGO|S_ISVTX);
error = security_inode_mkdir(dir, dentry, mode);
if (error)
return error;
linux建立文件系统的命令DQUOT_INIT(dir);
//调⽤⽗结点的mkdir操作
error = dir->i_op->mkdir(dir, dentry, mode);
sql数据库开发实例if (!error) {
//如果成功,通告与之关联的进程
inode_dir_notify(dir, DN_CREATE);
security_inode_post_mkdir(dir,dentry, mode);
}
return error;
}
在这⾥看到,最终会调⽤⽗进程的i_op.mkdir操作.另外,对于上⾯说的相应结点已经存在的情况是在may_create()中检测的:
static inline int may_create(struct inode *dir, struct dentry *child,
struct nameidata *nd)
//如果欲建结点的inode已经存在
//对于⼀个新建的dentry.其d_inode指向为空.
if (child->d_inode)
return -EEXIST;
//判断⽗⽬录是否已经失效
if (IS_DEADDIR(dir))
java从入门到精通精粹版
return -ENOENT;
//权限检查
return permission(dir,MAY_WRITE | MAY_EXEC, nd);
}
Mkdir的⼤体架构就如此了.下⾯讨论⼀下rootfs和ext2中的⽬录创建.
三:rootfs的⽬录创建
在前⼀篇⽂章分析到.挂载rootfs时,对⽂件系统根⽬录的inode.i_op赋值如下:static 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,
};
对应的mkdir操作⼊⼝是ramfs_mkdir():
static int ramfs_mkdir(struct inode * dir, struct dentry * dentry, int mode) {
//创建结点
int retval = ramfs_mknod(dir, dentry, mode | S_IFDIR, 0);
//如果创建成功,更新i_nlink计数
if (!retval)
dir->i_nlink++;
return retval;

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。