【转载】linux open 系统调用过程

原文地址:http://blog.chinaunix.net/u2/71164/showart_1408897.html

 

 

 

 

 

linux open 系统调用过程

 
 

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

sys_openlinux系统调用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

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值