在文件读写之前,我们必须先打开文件。从应用程序的角度来看,这是通过标准库的open函数完成的,该函数返回一个文件描述符。内核中是由系统调用sys_open()函数完成。
-
-
SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, int, mode)
-
{
-
long ret;
-
-
-
-
if (force_o_largefile())
-
flags |= O_LARGEFILE;
-
-
ret = do_sys_open(AT_FDCWD, filename, flags, mode);
-
-
asmlinkage_protect(3, ret, filename, flags, mode);
-
return ret;
-
}
实际实现工作
-
class="cpp" name="code">long do_sys_open(int dfd, const char __user *filename, int flags, int mode)
-
{
-
-
char *tmp = getname(filename);
-
int fd = PTR_ERR(tmp);
-
-
if (!IS_ERR(tmp)) {
-
-
-
-
-
-
-
fd = get_unused_fd_flags(flags);
-
if (fd >= 0) {
-
-
struct file *f = do_filp_open(dfd, tmp, flags, mode, 0);
-
if (IS_ERR(f)) {
-
put_unused_fd(fd);
-
fd = PTR_ERR(f);
-
} else {
-
fsnotify_open(f->f_path.dentry);
-
fd_install(fd, f);
-
}
-
}
-
putname(tmp);
-
}
-
return fd;
-
}
-
-
"font-size:18px">打开文件主体实现
-
class
="cpp" name="code">
-
-
-
-
-
struct file *do_filp_open(int dfd, const char *pathname,
-
int open_flag, int mode, int acc_mode)
-
{
-
struct file *filp;
-
struct nameidata nd;
-
int error;
-
struct path path;
-
struct dentry *dir;
-
int count = 0;
-
int will_write;
-
-
int flag = open_to_namei_flags(open_flag);
-
-
if (!acc_mode)
-
acc_mode = MAY_OPEN | ACC_MODE(flag);
-
-
-
-
-
if (flag & O_TRUNC)
-
acc_mode |= MAY_WRITE;
-
-
-
-
-
if (flag & O_APPEND)
-
acc_mode |= MAY_APPEND;
-
-
-
-
-
-
if (!(flag & O_CREAT)) {
-
-
-
-
-
-
error = path_lookup_open(dfd, pathname, lookup_flags(flag),
-
&nd, flag);
-
if (error)
-
return ERR_PTR(error);
-
goto ok;
-
}
-
-
-
-
-
-
-
-
error = path_init(dfd, pathname, LOOKUP_PARENT, &nd);
-
if (error)
-
return ERR_PTR(error);
-
error = path_walk(pathname, &nd);
-
if (error) {
-
if (nd.root.mnt)
-
path_put(&nd.root);
-
return ERR_PTR(error);
-
}
-
if (unlikely(!audit_dummy_context()))
-
-
audit_inode(pathname, nd.path.dentry);
-
-
-
-
-
-
-
error = -EISDIR;
-
-
if (nd.last_type != LAST_NORM || nd.last.name[nd.last.len])
-
goto exit_parent;
-
-
error = -ENFILE;
-
-
filp = get_empty_filp();
-
if (filp == NULL)
-
goto exit_parent;
-
-
nd.intent.open.file = filp;
-
nd.intent.open.flags = flag;
-
nd.intent.open.create_mode = mode;
-
dir = nd.path.dentry;
-
nd.flags &= ~LOOKUP_PARENT;
-
nd.flags |= LOOKUP_CREATE | LOOKUP_OPEN;
-
if (flag & O_EXCL)
-
nd.flags |= LOOKUP_EXCL;
-
mutex_lock(&dir->d_inode->i_mutex);
-
-
-
-
-
path.dentry = lookup_hash(&nd);
-
path.mnt = nd.path.mnt;
-
-
do_last:
-
error = PTR_ERR(path.dentry);
-
if (IS_ERR(path.dentry)) {
-
mutex_unlock(&dir->d_inode->i_mutex);
-
goto exit;
-
}
-
-
if (IS_ERR(nd.intent.open.file)) {
-
error = PTR_ERR(nd.intent.open.file);
-
goto exit_mutex_unlock;
-
}
-
-
-
-
if (!path.dentry->d_inode) {
-
-
-
-
-
-
-
-
-
error = mnt_want_write(nd.path.mnt);
-
if (error)
-
goto exit_mutex_unlock;
-
-
error = __open_namei_create(&nd, &path, flag, mode);
-
if (error) {
-
mnt_drop_write(nd.path.mnt);
-
goto exit;
-
}
-
-
filp = nameidata_to_filp(&nd, open_flag);
-
if (IS_ERR(filp))
-
ima_counts_put(&nd.path,
-
acc_mode & (MAY_READ | MAY_WRITE |
-
MAY_EXEC));
-
-
mnt_drop_write(nd.path.mnt);
-
if (nd.root.mnt)
-
path_put(&nd.root);
-
return filp;
-
}
-
-
-
-
-
-
mutex_unlock(&dir->d_inode->i_mutex);
-
-
audit_inode(pathname, path.dentry);
-
-
error = -EEXIST;
-
if (flag & O_EXCL)
-
goto exit_dput;
-
-
-
-
if (__follow_mount(&path)) {
-
error = -ELOOP;
-
if (flag & O_NOFOLLOW)
-
goto exit_dput;
-
}
-
-
error = -ENOENT;
-
if (!path.dentry->d_inode)
-
goto exit_dput;
-
if (path.dentry->d_inode->i_op->follow_link)
-
goto do_link;
-
-
path_to_nameidata(&path, &nd);
-
error = -EISDIR;
-
-
if (path.dentry->d_inode && S_ISDIR(path.dentry->d_inode->i_mode))
-
goto exit;
-
-
ok:
-
-
-
-
-
-
-
-
-
-
-
will_write = open_will_write_to_fs(flag, nd.path.dentry->d_inode);
-
if (will_write) {
-
error = mnt_want_write(nd.path.mnt);
-
if (error)
-
goto exit;
-
}
-
-
error = may_open(&nd.path, acc_mode, flag);
-
if (error) {
-
if (will_write)
-
mnt_drop_write(nd.path.mnt);
-
goto exit;
-
}
-
-
filp = nameidata_to_filp(&nd, open_flag);
-
if (IS_ERR(filp))
-
ima_counts_put(&nd.path,
-
acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC));
-
-
-
-
-
-
if (will_write)
-
-
mnt_drop_write(nd.path.mnt);
-
if (nd.root.mnt)
-
-
path_put(&nd.root);
-
return filp;
-
-
exit_mutex_unlock:
-
mutex_unlock(&dir->d_inode->i_mutex);
-
exit_dput:
-
path_put_conditional(&path, &nd);
-
exit:
-
if (!IS_ERR(nd.intent.open.file))
-
release_open_intent(&nd);
-
exit_parent:
-
if (nd.root.mnt)
-
path_put(&nd.root);
-
path_put(&nd.path);
-
return ERR_PTR(error);
-
-
do_link:
-
error = -ELOOP;
-
if (flag & O_NOFOLLOW)
-
goto exit_dput;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
nd.flags |= LOOKUP_PARENT;
-
-
error = security_inode_follow_link(path.dentry, &nd);
-
if (error)
-
goto exit_dput;
-
-
error = __do_follow_link(&path, &nd);
-
if (error) {
-
-
-
-
-
release_open_intent(&nd);
-
if (nd.root.mnt)
-
path_put(&nd.root);
-
return ERR_PTR(error);
-
}
-
nd.flags &= ~LOOKUP_PARENT;
-
-
if (nd.last_type == LAST_BIND)
-
goto ok;
-
error = -EISDIR;
-
if (nd.last_type != LAST_NORM)
-
goto exit;
-
if (nd.last.name[nd.last.len]) {
-
__putname(nd.last.name);
-
goto exit;
-
}
-
error = -ELOOP;
-
-
if (count++==32) {
-
__putname(nd.last.name);
-
goto exit;
-
}
-
dir = nd.path.dentry;
-
mutex_lock(&dir->d_inode->i_mutex);
-
-
path.dentry = lookup_hash(&nd);
-
path.mnt = nd.path.mnt;
-
__putname(nd.last.name);
-
goto do_last;
-
}
-
-
"font-size:18px">在内核中要打开一个文件,首先应该找到这个文件,而查找文件的过程在vfs里面是由do_path_lookup或者path_lookup_open函数来完成的,关于文件路径查找在前面已经分析过相关的代码了。这两个函数将用户传进来的字符串表示的文件路径转换成一个dentry结构,并建立好相应的inode和file结构,将指向file的描述符返回用户。用户随后通过文件描述符,来访问这些数据结构。
阅读(1714) | 评论(0) | 转发(0) |