mknod系统调用
是没有所谓的create系统调用的,只有mknod系统调用。mknodat和mknod两个syscall实际都调用do_mknodat()函数。
do_mknodat()都干啥呢。
---------------------------------------------------namei.c
long do_mknodat(int dfd, const char __user *filename, umode_t mode,
unsigned int dev)
{
struct dentry *dentry;
struct path path;
unsigned int lookup_flags = 0;
error = may_mknod(mode);
if (error) return error;
retry:
dentry = user_path_create(dfd, filename, &path, lookup_flags);
if (IS_ERR(dentry)) return PTR_ERR(dentry);
if (!IS_POSIXACL(path.dentry->d_inode)) mode &= ~current_umask();
error = security_path_mknod(&path, dentry, mode, dev);
if (error)
goto out;
switch (mode & S_IFMT) {
case 0: case S_IFREG:
error = vfs_create(path.dentry->d_inode,dentry,mode,true);
if (!error)
ima_post_path_mknod(dentry);
break;
case S_IFCHR: case S_IFBLK:
error = vfs_mknod(path.dentry->d_inode,dentry,mode,
new_decode_dev(dev));
break;
case S_IFIFO: case S_IFSOCK:
error = vfs_mknod(path.dentry->d_inode,dentry,mode,0);
break;
}
out:
done_path_create(&path, dentry);
if (retry_estale(error, lookup_flags)) {
lookup_flags |= LOOKUP_REVAL;
goto retry;
}
return error;
}
1. may_mknod根据mode检查文件是否可以创建,显然可以创建的是REG, CHR,BLK,FIFO和SOCK这五种文件,DIR和其他是非法的。
static int may_mknod(umode_t mode)
{
switch (mode & S_IFMT) {
case S_IFREG:
case S_IFCHR:
case S_IFBLK:
case S_IFIFO:
case S_IFSOCK:
case 0: /* zero mode translates to S_IFREG */
return 0;
case S_IFDIR:
return -EPERM;
default:
return -EINVAL;
}
}
2.根据文件类型使用相应的vfs_xxx
普通文件就vfs_create(parent_inode, sub_dentry, mode)
其他几种文件就vfs_mknod(parent_inode, sub_dentry, mode)
其实都是分别走到 parent dir的dir->i_op->create()和dir->i_op->mknod(),所以区别还是要看各个文件系统的dir的i_op是如何实现的了。
以ext4为例
-------------------------------------------------------------------fs/ext4/namei.c
/*
* directories can handle most operations...
*/
const struct inode_operations ext4_dir_inode_operations = {
.create = ext4_create,
.lookup = ext4_lookup,
.link = ext4_link,
.unlink = ext4_unlink,
.symlink = ext4_symlink,
.mkdir = ext4_mkdir,
.rmdir = ext4_rmdir,
.mknod = ext4_mknod,
.tmpfile = ext4_tmpfile,
.rename = ext4_rename2,
.setattr = ext4_setattr,
.getattr = ext4_getattr,
.listxattr = ext4_listxattr,
.get_acl = ext4_get_acl,
.set_acl = ext4_set_acl,
.fiemap = ext4_fiemap,
};
ext4_mknod和ext4_create的区别也不大
create比较好理解,就是基本的inode和file的ops;对应的mknod这边init_special_inode就是根据文件类型(CHR,BLK,FIFO)来设置不同的i_fops以及i_op。
open系统调用
如果flag中包含O_CREAT,文件不存在,则open系统调用就会创建文件,当然这个仅针对regular file,所以走的是create。