免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 898 | 回复: 0
打印 上一主题 下一主题

linux open 系统调用过程 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-11-12 13:06 |只看该作者 |倒序浏览
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》

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/71164/showart_1408897.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP