本文基于Linux5.10。
mkdir在musl1.2.3中的实现,直接调用了mkdir系统调用
int mkdir(const char *path, mode_t mode)
{
#ifdef SYS_mkdir
return syscall(SYS_mkdir, path, mode);
#else
return syscall(SYS_mkdirat, AT_FDCWD, path, mode);
#endif
}
mkdir系统调用起始于 fs/namei.c,定义如下:
SYSCALL_DEFINE2(mkdir, const char __user *, pathname, umode_t, mode)
{
return do_mkdirat(AT_FDCWD, pathname, mode);
}
do_mkdirat函数定义如下:
static long do_mkdirat(int dfd, const char __user *pathname, umode_t mode)
{
//...
retry:
dentry = user_path_create(dfd, pathname, &path, lookup_flags);
//...
error = security_path_mkdir(&path, dentry,
mode_strip_umask(path.dentry->d_inode, mode));
if (!error)
error = vfs_mkdir(path.dentry->d_inode, dentry, mode);
done_path_create(&path, dentry);
if (retry_estale(error, lookup_flags)) {
lookup_flags |= LOOKUP_REVAL;
goto retry;
}
//...
}
在do_mkdirat函数中,首先user_path_create通过用户传入的文件路创建对应的dentry,path保存父目录路径,dentry保存要新建的目录项内存
static struct dentry *
filename_create(int dfd, struct filename *name,
struct path *path, unsigned int lookup_flags)
{
//查找父目录文件路径,找到父目录后,将新建的目录关联到父目录
name = filename_parentat(dfd, name, lookup_flags, path, &last, &type);
//分别在dentry的哈希表和磁盘中查找目标dentry,没有则创建新的dentry
dentry = __lookup_hash(&last, path->dentry, lookup_flags);
}
在__lookup_hash函数中,先在全局哈希表查询,
static struct dentry *__lookup_hash(const struct qstr *name,
struct dentry *base, unsigned int flags)
{
//先在dentry hash表中查询目标dentry
struct dentry *dentry = lookup_dcache(name, base, flags);
...
//创建dentry
dentry = d_alloc(base, name);
//调用对应文件系统的lookup函数,查找目标目录
old = dir->i_op->lookup(dir, dentry, flags);
...
}
以configfs为例,对应的函数是configfs_lookup,在configfs_lookup中,调用inode = configfs_create(dentry, mode);创建了inode对象。当然不同的文件系统的实现不一样,有的文件系统在lookup中并不会去创建inode,而是在对应的mkdir中创建。