文件系统和设备之间的联系

原创 2007年10月12日 16:22:00

 如果写过设备驱动,就知道我们写驱动主要是为了实现一个设备驱动接口,一组
对设备操作的方法,我这里想简单地分析一下文件系统与设备驱动之间的接口。
先来看打开操作,我自己对文件系统也不是很了解,只知道在用户空间调用了open函数,
就会在内核中调用sys_open这个系统调用,原来的0.11内核都是通过int80x系统调用门
来实现的,不过这里似乎是直接调用的嘛,在include/asm-arm/unistd.h中
static inline long open(const char *file, int flag, int mode)
{
 extern long sys_open(const char *, int, int);
 return sys_open(file, flag, mode);
}
再来看fs/open.c中的sys_open函数
asmlinkage long sys_open(const char * filename, int flags, int mode)
{
 char * tmp;
 int fd, error;

#if BITS_PER_LONG != 32
 flags |= O_LARGEFILE;
#endif
 tmp = getname(filename);
 fd = PTR_ERR(tmp);
 if (!IS_ERR(tmp)) {
  fd = get_unused_fd(); //获取一个未用的文件指示符
  if (fd >= 0) {
   struct file *f = filp_open(tmp, flags, mode);
   //打开文件,建立file类型的结构并返回其指针
   error = PTR_ERR(f);
   if (IS_ERR(f))
    goto out_error;
   fd_install(fd, f);//把文件指示符和文件指针相关联
  }
out:
  putname(tmp);
 }
 return fd;
out_error:
 put_unused_fd(fd);
 fd = error;
 goto out;
}

这样主要是在filp_open中实现了打开操作。
struct file *filp_open(const char * filename, int flags, int mode)
{
 int namei_flags, error;
 struct nameidata nd;

 namei_flags = flags;
 if ((namei_flags+1) & O_ACCMODE)
  namei_flags++;
 if (namei_flags & O_TRUNC)
  namei_flags |= 2;

 error = open_namei(filename, namei_flags, mode, &nd);
 if (!error)
  return dentry_open(nd.dentry, nd.mnt, flags);

 return ERR_PTR(error);
}
关键是要知道是怎样得到file结构体的,首先当然是要读取设备文件对应的inode结构体
这是由函数open_namei实现的,然后dentry_open来建立file结构体。
struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
{
 struct file * f;
 struct inode *inode;
 static LIST_HEAD(kill_list);
 int error;

 error = -ENFILE;
 f = get_empty_filp(); //获取空的file结构体
 if (!f)
  goto cleanup_dentry;
 f->f_flags = flags;
 f->f_mode = (flags+1) & O_ACCMODE;
 inode = dentry->d_inode;
 if (f->f_mode & FMODE_WRITE) {
  error = get_write_access(inode);
  if (error)
   goto cleanup_file;
 }

 f->f_dentry = dentry;
 f->f_vfsmnt = mnt;
 f->f_pos = 0;
 f->f_reada = 0;
 f->f_op = fops_get(inode->i_fop); //获取设备的file_operations结构
 file_move(f, &inode->i_sb->s_files);

 /* preallocate kiobuf for O_DIRECT */
 f->f_iobuf = NULL;
 f->f_iobuf_lock = 0;
 if (f->f_flags & O_DIRECT) {
  error = alloc_kiovec(1, &f->f_iobuf);
  if (error)
   goto cleanup_all;
 }

 if (f->f_op && f->f_op->open) { //执行设备驱动中的open操作
  error = f->f_op->open(inode,f);
  if (error)
   goto cleanup_all;
 }
 f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);

 return f;

cleanup_all:
 if (f->f_iobuf)
  free_kiovec(1, &f->f_iobuf);
 fops_put(f->f_op);
 if (f->f_mode & FMODE_WRITE)
  put_write_access(inode);
 file_move(f, &kill_list); /* out of the way.. */
 f->f_dentry = NULL;
 f->f_vfsmnt = NULL;
cleanup_file:
 put_filp(f);
cleanup_dentry:
 dput(dentry);
 mntput(mnt);
 return ERR_PTR(error);
}
不同的文件系统会使用不同的函数取获取inode结构,对于设备文件系统,我猜想在注册设备
建立节点的时候,其inode结构中的struct file_operations *i_fop成员变量就已经被赋值
为设备驱动的file_operations了。还是以/dev/console为例,其驱动注册的file_operations
是tty_fops,于是file结构中的f_op指向的就是tty_fops结构。于是代开操作就会调用到tty_fops
中的open函数。而对于普通文件,会有默认的file_operations结构,其open函数什么也不做。
对于用register_chrdev注册的设备,显然注册的时候驱动的file_operations结构的指针并没有
传给inode结构,因为其节点是可以在注册之前就建立的,其实对于字符设备在用mknod建立imode
时赋给的file_operations也是默认的def_chr_fops,在fs/devices.c中定义
static struct file_operations def_chr_fops = {
 open:  chrdev_open,
};
于是打开字符设备的时候都会执行chrdev_open
int chrdev_open(struct inode * inode, struct file * filp)
{
 int ret = -ENODEV;

 filp->f_op = get_chrfops(MAJOR(inode->i_rdev), MINOR(inode->i_rdev));
 if (filp->f_op) {
  ret = 0;
  if (filp->f_op->open != NULL) {
   lock_kernel();
   ret = filp->f_op->open(inode,filp);
   unlock_kernel();
  }
 }
 return ret;
}
ok,在chrdev_open中又用filp->f_op重新赋值,这一次赋给的是真正的设备的file_operations指针于是下此使用read,write系统调用的时候,通过filp->f_op调用的函数就是真正设备的read,write函数了。

Linux 文件系统与设备文件系统 (二)—— sysfs 文件系统与Linux设备模型

提到 sysfs 文件系统 ,必须先需要了解的是Linux设备模型,什么事Linux设备模型呢? 一、Linux 设备模型 1、设备模型概述      从2.6版本开始,Linux开发团队便为内核建立...
  • zqixiao_09
  • zqixiao_09
  • 2016-03-12 12:19:28
  • 3257

系统调用与设备驱动

内置于Unix(以及Linux)系统的方法,被称为系统调用方法,是操作系统的接口。在操作系统的核心(内核)是一些设备驱动(device drivers),这是一系列用来控制系统硬件的底层接口(low-...
  • jaryguo
  • jaryguo
  • 2015-01-23 16:34:45
  • 1045

Linux 文件系统与设备文件系统 (一)—— udev 设备文件系统

一、什么是Linux设备文件系统       首先我们不看定义,定义总是太抽象很难理解,我们先看现象。当我们往开发板上移植了一个新的文件系统之后(假如各种设备驱动也移植好了),启动开发板,我们用串口工...
  • zqixiao_09
  • zqixiao_09
  • 2016-03-12 10:55:35
  • 5065

一个简单文件系统的实现

分类: 嵌入式系统开发 软件源码 Linux相关开发 c/c++开发2009-07-20 16:59 1148人阅读 评论(0) 收藏 举报  /*转载请注明作者 author got...
  • mirkerson
  • mirkerson
  • 2012-11-26 10:45:11
  • 4824

如何实现一个文件系统

摘要本章目的是分析在Linux系统中如何实现新的文件系统。在介绍文件系统具体实现前先介绍文件系统的概念和作用,抽象出了文件系统概念模型。熟悉文件系统的内涵后,我们再近一步讨论Linux系统中和文件系统...
  • hnhbdss
  • hnhbdss
  • 2007-12-26 14:34:00
  • 3232

文件系统和数据库存储数据的联系和区别

 其区别在于: (1) 文件系统用文件将数据长期保存在外存上,数 据库系统用数据库统一存储数据。 (2) 文件系统中的程序和数据有一 定的联系,数据库系统...
  • Echo_Ana
  • Echo_Ana
  • 2017-01-01 22:54:59
  • 2745

数据库系统和文件系统的区别与联系

很多人刚刚接触数据库时都有疑问:在很多程序中都会是有的直接读取一个静态文件,有的是读取数据库。直接读取静态文件,不访问数据库速度是会很快,但是为什么还要访问数据库呢?它们两则肯定是有区别的,那么区别是...
  • JackLiu16
  • JackLiu16
  • 2018-02-26 11:29:20
  • 93

文件系统和设备之间的联系

 如果写过设备驱动,就知道我们写驱动主要是为了实现一个设备驱动接口,一组对设备操作的方法,我这里想简单地分析一下文件系统与设备驱动之间的接口。先来看打开操作,我自己对文件系统也不是很了解,只知道在用户...
  • dansen_xu
  • dansen_xu
  • 2007-10-12 16:22:00
  • 1276

File-OS(简单文件系统的实现)

前言期末的OS的大作业,写了一个简单的文件管理系统,写了5天左右(实际整个项目历经一个月(大部分时间在挂机),花了不少时间来构思,设计系统的架构。。。。),写的比较辛苦,既然花了这么久的时间,那就拿出...
  • qq_24489717
  • qq_24489717
  • 2017-05-31 01:03:39
  • 1870

在UNIX祼设备和文件系统之间移动oracle

  • 2012年01月05日 22:32
  • 44KB
  • 下载
收藏助手
不良信息举报
您举报文章:文件系统和设备之间的联系
举报原因:
原因补充:

(最多只允许输入30个字)