Linux VFS 之 open系统调用(kernel 3.4)
来源:互联网 发布:2016nba新秀弹跳数据 编辑:程序博客网 时间:2024/04/28 00:43
linux version: 3.4.67
kernel 代码
fs/open.cfs/namei.c
open命令调用关系
mount- > /fs/open.c/SYSCALL_DEFINE3(open, ....); -> do_sys_open->get_unused_fd_flags->
->do_filp_open->fd_install
根据调用关系对各函数注解
long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)
{
struct open_flags op;
int lookup = build_open_flags(flags, mode, &op);
char *tmp = getname(filename);
int fd = PTR_ERR(tmp);
if (!IS_ERR(tmp)) {
fd = get_unused_fd_flags(flags); //获取一个未使用的文件描述符,参考fs/file.c文件alloc_fd() ,后续仔细研究file.c文件。
if (fd >= 0) {
struct file *f = do_filp_open(dfd, tmp, &op, lookup); //直接调用path_openat打开文件,返回file文件对象。
if (IS_ERR(f)) {
put_unused_fd(fd);
fd = PTR_ERR(f);
} else {
fsnotify_open(f);
fd_install(fd, f); //file文件对象与当前进程current关联。fd作为file对象的索引,这样file与fd也一一对应。
}
}
putname(tmp);
}
return fd; //返回文件描述符
}
struct nameidata *nd, const struct open_flags *op, int flags)
{
struct file *base = NULL;
struct file *filp;
struct path path;
int error;
//申请文件对象file结构体内存批针
filp = get_empty_filp();
if (!filp)
return ERR_PTR(-ENFILE);
filp->f_flags = op->open_flag; //保存open flag
nd->intent.open.file = filp; //将文件对象到nd->intent.open.file,后面就直接从这儿拿文件对象指针
nd->intent.open.flags = open_to_namei_flags(op->open_flag);
nd->intent.open.create_mode = op->mode;
error = path_init(dfd, pathname, flags | LOOKUP_PARENT, nd, &base); //初始化nd
if (unlikely(error))
goto out_filp;
current->total_link_count = 0;
error = link_path_walk(pathname, nd);//查找到打开文件所在目录的目录项对象dentry和vfsmount,保存到nd。
filp = do_last(nd, &path, op, pathname); // 调用do_last继续做其它工作
........
return filp;
}
const struct open_flags *op, const char *pathname)
{
struct dentry *dir = nd->path.dentry; //所在目录的目录项对象dentry
struct dentry *dentry;
int open_flag = op->open_flag;
int will_truncate = open_flag & O_TRUNC;
int want_write = 0;
int acc_mode = op->acc_mode;
struct file *filp;
int error;
nd->flags &= ~LOOKUP_PARENT;
nd->flags |= op->intent;
path->mnt = nd->path.mnt;
/* Negative dentry, just create the file */
if (!dentry->d_inode) { //如果文件dentry对应的inode为空,则需要为它创建inode
umode_t mode = op->mode;
。。。。。。。
error = vfs_create(dir->d_inode, dentry, mode, nd); //利用所在目录的目录项对象的inode operation为相关文件创建新inode 。注:这里dentry与inode就关联起来了。
nd->path.dentry = dentry; //建文件的目录项对象保存到nd->path->dentry
goto common; // 跑到common 继续~~
}
filp = nameidata_to_filp(nd); //将nameidata相关项赋值给struct file对象。
return filp;
{
const struct cred *cred = current_cred();
struct file *filp;
/* Pick up the filp from the open intent */
filp = nd->intent.open.file; //获取函数path_openat申请并保存到nameidata的file对象
nd->intent.open.file = NULL;
path_get(&nd->path);
filp = __dentry_open(nd->path.dentry, nd->path.mnt, filp, // file对象初始化,包括file与dentry关联工作
NULL, cred);
}
return filp;
}
struct file *f,
int (*open)(struct inode *, struct file *),
const struct cred *cred)
{
static const struct file_operations empty_fops = {};
struct inode *inode;
int error;
f->f_mode = OPEN_FMODE(f->f_flags) | FMODE_LSEEK | //初始化打开mode
FMODE_PREAD | FMODE_PWRITE;
f->f_mode = FMODE_PATH; //打开的是目录
inode = dentry->d_inode; //从dentry中获取inode。 dentry和inode在前面的do_last函数已经关联过的。
f->f_mapping = inode->i_mapping; //地址空间map
f->f_path.dentry = dentry; // 注: 就在这儿file对象与目录象对象关联起来啦!!
f->f_path.mnt = mnt; // file对象与挂载点对象关联起来啦。
f->f_pos = 0; //初始文件批针位置为0.
file_sb_list_add(f, inode->i_sb); // add a file to the sb's file list
if (unlikely(f->f_mode & FMODE_PATH)) {
f->f_op = &empty_fops; //打开目录的话,file operation为空了,直接返回了。
return f;
}
//注: 在这儿file对象的file_operations初始化好了。
f->f_op = fops_get(inode->i_fop); //inode节点在初始化的时候已经赋值了i_fop,现在将文件操作赋值给f_op
// 通过file对象的file_operations->open指针,调用到特定文件系统的open函数,打开特定的设备或文件啦!
if (!open && f->f_op)
open = f->f_op->open;
if (open) {
error = open(inode, f);
if (error)
goto cleanup_all;
}
。。。。。。。。
/* NB: we're sure to have correct a_ops only after f_op->open */
if (f->f_flags & O_DIRECT) {
if (!f->f_mapping->a_ops ||
((!f->f_mapping->a_ops->direct_IO) &&
(!f->f_mapping->a_ops->get_xip_mem))) {
fput(f);
f = ERR_PTR(-EINVAL);
}
}
return f; //至此file对象已经初始化完成、并且调用特定文件系统的open方法
将进程的current->files对象与file文件对象进行
void fd_install(unsigned int fd, struct file *file)
{
struct files_struct *files = current->files; //获取当前进程打开的文件表批针
struct fdtable *fdt;
spin_lock(&files->file_lock);
fdt = files_fdtable(files); //获取当前进程的文件描述符表指针
BUG_ON(fdt->fd[fd] != NULL);
rcu_assign_pointer(fdt->fd[fd], file); //将fdt->fd[fd]指向file对象,这样文件对象与进程关联上了。 fd作为file对象的索引。这样file与fd也一一对应
spin_unlock(&files->file_lock);
}
fs/open.c 提供的内核常用方法
参考:
http://blog.csdn.net/chenjin_zhong/article/details/8452453
http://blog.csdn.net/chenjin_zhong/article/details/8452487
- Linux VFS 之 open系统调用(kernel 3.4)
- Linux VFS 之 mount系统调用(kernel 3.4)
- Linux VFS 之 write/read系统调用(kernel 3.4)
- Linux VFS 之 sync系统调用(kernel 3.4)
- Linux Kernel - open系统调用
- Linux VFS文件系统之打开(Open)文件
- Linux VFS文件系统之打开(Open)文件
- open系统调用流程--从vfs到底层文件系统
- Linux系统调用之open(), close()
- Linux系统调用之open, close
- VFS : linux kernel src document
- Linux Kernel - mknod系统调用
- Linux Kernel - mount系统调用
- Linux kernel 分析之八:系统调用参数
- Linux kernel 分析之九:fork()系统调用
- Linux VFS中write系统调用实现原理
- Linux VFS中write系统调用实现原理
- linux open 系统调用过程
- 让jqgrid里面数据循环滚动展示
- 索引的类型
- 数据库截取字段并转换成int型函数
- centos下的nfs安装配置
- 关于ListView的删除刷新列表
- Linux VFS 之 open系统调用(kernel 3.4)
- tomcat的webappclassloader中一个奇怪的异常信息
- iOS ffmpeg将音视频写入文件aac+h264
- python中的map、filter、reduce函数
- velocity 在图片上添加文字
- Libjingle 网络库
- 卡的卡卡的骄傲肯定减减肥
- puppet 变态语法 shell 下自检测
- HTTP协议 (六) 状态码详解