Linux的open函数的调用过程,linux open 系统调用过程

linux中系统掉用内核部分会调用sys_***(open ,read, write ,close.......)

sys_open是linux系统调用open的内核部部分的函数。

asmlinkage long sys_open(const char __user *filename, int flags, int mode)

{

if (force_o_largefile())

flags |= O_LARGEFILE;

return do_sys_open(filename, flags, mode);

}

long do_sys_open(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();

if (fd >= 0) {

struct file *f = filp_open(tmp, flags, mode);

if (IS_ERR(f)) {

put_unused_fd(fd);

fd = PTR_ERR(f);

} else {

fsnotify_open(f->f_dentry);

fd_install(fd, f); //将 fd 与file结构关联,以便 read write 等系统调用使用!  《1》   }

}

putname(tmp);

}

return fd;

}

struct file *filp_open(const char * filename, int flags, int mode)

{

int namei_flags, error;

struct nameidata nd;

struct file *f;

namei_flags = flags;

if ((namei_flags+1) & O_ACCMODE)

namei_flags++;

if (namei_flags & O_TRUNC)

namei_flags |= 2;

error = -ENFILE;

f = get_empty_filp(); //为每个打开的文件分配一个file结构

if (f == NULL)

return ERR_PTR(error);

error = open_namei(filename, namei_flags, mode, &nd);

if (!error)

return __dentry_open(nd.dentry, nd.mnt, flags, f);

put_filp(f);

return ERR_PTR(error);

}

static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,

int flags, struct file *f)

{

struct inode *inode;

int error;

f->f_flags = flags;

f->f_mode = ((flags+1) & O_ACCMODE) | FMODE_LSEEK |

FMODE_PREAD | FMODE_PWRITE;

inode = dentry->d_inode;

if (f->f_mode & FMODE_WRITE) {

error = get_write_access(inode);

if (error)

goto cleanup_file;

}

f->f_mapping = inode->i_mapping;

f->f_dentry = dentry;

f->f_vfsmnt = mnt;

f->f_pos = 0;

f->f_op = fops_get(inode->i_fop);//从inode节点中找出对应文件的file_opereations(可见每打开一次文件就有一个file 结构被创建而无论这个文件有多少个进程打开打都指向同一个inode) file_move(f, &inode->i_sb->s_files);

if (f->f_op && f->f_op->open) {

error = f->f_op->open(inode,f); //在这里调用驱动程序中的open函数

if (error)

goto cleanup_all;

}

f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);

file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping);

/* 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_page))) {

fput(f);

f = ERR_PTR(-EINVAL);

}

}

return f;

cleanup_all:

fops_put(f->f_op);

if (f->f_mode & FMODE_WRITE)

put_write_access(inode);

file_kill(f);

f->f_dentry = NULL;

f->f_vfsmnt = NULL;

cleanup_file:

put_filp(f);

dput(dentry);

mntput(mnt);

return ERR_PTR(error);

}

《1》

/*

* Install a file pointer in the fd array.

*

* The VFS is full of places where we drop the files lock between

* setting the open_fds bitmap and installing the file in the file

* array.  At any such point, we are vulnerable to a dup2() race

* installing a file in the array before us.  We need to detect this and

* fput() the struct file we are about to overwrite in this case.

*

* It should never happen - if we allow dup2() do it, _really_ bad things

* will follow.

*/

void fastcall 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);

spin_unlock(&files->file_lock);

}

《end 1》

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值