上回我们说到,如何创建文件夹和文件。我们发现,在sysfs中,inode并不那么重要。这是因为我们所要读写的信息已经就在内存中,并且已经形成了层次结构。我们只需有dentry,就可以dentry->fsdata,就能找到我们读些信息的来源 --- sysfs_dirent结构。这也是我觉得有必要研究 sysfs的原因之一,因为它简单,而且不涉及具体的硬件驱动,但是从这个过程中,我们可以把文件系统中的一些基本数据结构搞清楚。接下来,我以读取sysfs文件和文件夹的内容为例子,讲讲文件读的流程。那么关于写,还有关于symblink的东西完全可以以此类推了。

我们新建文件夹时,设置了

inode->i_op = &sysfs_dir_inode_operations;

inode->i_fop = &sysfs_dir_operations;

struct file_operations sysfs_dir_operations = {

.open = sysfs_dir_open,

.release = sysfs_dir_close,

.llseek = sysfs_dir_lseek,

.read = generic_read_dir,

.readdir = sysfs_readdir,

};

用一个简短的程序来做实验。

#include

<

sys

/

types.h

>

#include

<

dirent.h

>

#include

<

unistd.h

>

int

main()

...

{

DIR*dir;

structdirent*ptr;

dir=opendir("/sys/bus/");

while((ptr=readdir(dir))!=NULL)...{

printf("d_name:%s",ptr->d_name);

}closedir(dir);

return-1;

}

在用户空间,用gcc编译执行即可。我们来看看它究竟做了什么。

(1)sysfs_dir_open()

这是个用户空间的程序。opendir()是glibc的函数,glibc也就是著名的标准c库。至于opendir ()是如何与sysfs dir open ()接上头的,那还得去看glibc的代码。我就不想分析了...glibc可以从gnu的网站上自己下载源代码,编译。再用gdb调试,就可以看得跟清楚。

函数流程如下:

opendir("/sys/bus/") -> /*用户空间*/

-> 系统调用->

sys_open() -> filp_open()-> dentry_open() -> sysfs_dir_open()/*内核空间*/

static

int

sysfs_dir_open(

struct

inode

*

inode,

struct

file

*

file)

...

{

structdentry*dentry=file->f_dentry;

structsysfs_dirent*parent_sd=dentry->d_fsdata;

down(&dentry->d_inode->i_sem);

file->private_data=sysfs_new_dirent(parent_sd,NULL);

up(&dentry->d_inode->i_sem);

returnfile->private_data?0:-ENOMEM;

}

内核空间:新建一个dirent结构,连入父辈的dentry中,并将它地址保存在file->private_data中。这个dirent的具体作用待会会讲。

用户空间:新建了一个DIR结构,DIR结构如下。

#define __dirstream DIR

struct __dirstream

{

int fd; /* File descriptor. */

char *data; /* Directory block. */

size_t allocation; /* Space allocated for the block. */

size_t size; /* Total valid data in the block. */

size_t offset; /* Current offset into the block. */

off_t filepos; /* Position of next entry to read. */

__libc_lock_define (, lock) /* Mutex lock for this structure. */

};

(2)sysfs_readdir()

流程如下:

readdir(dir) -> getdents() ->/*用户空间*/

-> 系统调用->

sys32 readdir() -> vfs readdir() -> sysfs readdir()/*内核空间*/

readdir(dir)这个函数有点复杂,虽然在main函数里的while循环中,readdir被执行了多次,我们看看glibc里面的代码

readdir(dir)

...

{

......

if(dirp->offset>=dirp->size)...{

......

getdents()

......

}......

}

实际上,getdents() -> ... -> sysfs_readdir()只被调用了两次,getdents()一次就把所有的内容都读完,存在DIR结构当中,readdir()只是从DIR结构当中每次取出一个。DIR(dirstream)结构就是一个流。而回调函数filldir的作用就是往这个流中填充数据。第二次调用getdents()是用户把DIR里面的内容读完了,所以它又调用getdents()但是这次getdents()回返回NULL。

static

int

sysfs_readdir(

struct

file

*

filp,

void

*

dirent,filldir_tfilldir)

...

{

structdentry*dentry=filp->f_dentry;

structsysfs_dirent*parent_sd=dentry->d_fsdata;

structsysfs_dirent*cursor=filp->private_data;

structlist_head*p,*q=&cursor->s_sibling;

ino_tino;

inti=filp->f_pos;

switch(i)...{

case0:

ino=dentry->d_inode->i_ino;

if(filldir(dirent,".",1,i,ino,DT_DIR)<0)

break;

filp->f_pos++;

i++;

/**//*fallthrough*/case1:

ino=parent_ino(dentry);

if(filldir(dirent,"..",2,i,ino,DT_DIR)<0)

break;

filp->f_pos++;

i++;

/**//*fallthrough*/default:

if(filp->f_pos==2)...{

list_del(q);

list_add(q,&parent_sd->s_children);

}

for(p=q->next;p!=&parent_sd->s_children;p=p->next)...{

structsysfs_dirent*next;

constchar*name;

intlen;

next=list_entry(p,structsysfs_dirent,s_sibling);

if(!next->s_element)

continue;

name=sysfs_get_name(next);

len=strlen(name);

if(next->s_dentry)

ino=next->s_dentry->d_inode->i_ino;

elseino=iunique(sysfs_sb,2);

if(filldir(dirent,name,len,filp->f_pos,ino,dt_type(next))<0)

return0;

list_del(q);

list_add(q,p);

p=q;

filp->f_pos++;

}}return0;

}

看sysfs_readdir()其实很简单,它就是从我们调用sysfs_dir_open()时新建的一个sysfs_dirent结构开始,便利当前dentry->dirent下的所有子sysfs_dirent结构。读出名字,再回调函数filldir()将文件名,文件类型等信息,按照一定的格式写入某个缓冲区。

一个典型的filldir()就是filldir64(),它的作用的按一定格式向缓冲区写数据,再把数据复制到用户空间去。

linux getdents 例子,Linux那些事儿之我是Sysfs(12)举例三:sysfs读入文件夹内容相关推荐

  1. linux getdents 例子,Linux内建命令和外部命令(整理)

    Linux命令有内部命令(内建命令)和外部命令之分,内部命令和外部命令功能基本相同,但也有些细微差别. [内部命令 vs. 外部命令] (1)内部命令实际上是shell程序的一部分,其中包含的是一些比 ...

  2. linux grep 例子,Linux中Grep常用的15个例子

    Grep命令主要用于从文件中查找指定的字符串. 首先建一个demo_file: $ cat demo_file THIS LINE IS THE 1ST UPPER CASE LINE IN THIS ...

  3. Linux那些事儿之我是Hub(9)While You Were Sleeping(二)

    老实说,从函数一个开始的598行直到627行都没有什么可说的.其中需要一提的是,606行,调用usb_buffer_alloc()申请内存,赋给hub->buffer.614行,调用kmallo ...

  4. linux 那些事儿之我是 u 盘,《Linux那些事儿之我是USB》.PDF

    <Linux 那些事儿之我是 USB> 作者:华清远见 第 1 章 Linux 那些事儿之我是 USB Core 专业始于专注 卓识源于远见 1 .引子 老夫子们痛心疾首地总结说,现代青年 ...

  5. 《Linux那些事儿之我是USB》我是U盘(1)小城故事

    这个故事中使用的是2.6.22的内核代码.在Linux内核代码目录中,所有与设备驱动程序有关的代码都在drivers/目录下面,在这个目录中用ls命令可以看到很多子目录: lfg1:/usr/src/ ...

  6. Linux设备之我是usb,linux那些事儿之我是usb

    linux那些事儿之我是usb,复旦大学教授肖林甫先生给学生们解说的linux操作系统的一些硬件驱动开发的事儿. 内核说明: 我是U盘 说的是2.6.10的内核 我是Sysfs 说的是2.6.10的内 ...

  7. 读书笔记《Linux那些事儿之我是USB》

    第一篇:Linux那些事儿之我是USB Core USB诞生于inel 产生是为了解决前期计算机并口串口的问题,实现一种解决速度,扩展性,易用性的通信方式. 速度:usb2.0高速模式,480MB/s ...

  8. 《Linux那些事儿之我是USB》我是U盘(4)想到达明天现在就要启程

    既然知道了编写模块的方法,那么编写设备驱动程序自然也就不难了.我相信,每一个会写模块的人都不会觉得写设备驱动有困难. 真的,我没说假话,写驱动不是什么难事,你完全可以很自信地说,你已经可以写 设备驱动 ...

  9. Linux系统USB驱动目录,Linux那些事儿之我是USB 目录

    目录 第1篇  Linux那些事儿之我是USB Core 1.引子 2 2.它从哪里来 2 3.PK 3 4.漫漫辛酸路 3 5.我型我秀 4 6.我是一棵树 5 7.我是谁 9 8.好戏开始了 11 ...

最新文章

  1. 【Swift】 GETPOST请求 网络缓存的简单处理
  2. 碰撞检测碰撞Java简单游戏开发之碰撞检测
  3. Spring的AOP思想和实现AOP思想的框架AspectJ
  4. windows下,linux下c++生成文件夹
  5. 从多级延迟触发器到边沿检测
  6. BlogEngine学习一:操作符重载
  7. 使用 matlab 数字图像处理(七)—— 频率域处理
  8. java动态创建bean的意义_Spring Boot如何动态创建Bean示例代码
  9. linux设置服务开机自启动
  10. UNIX-LINUX编程实践教程-第五章-实例代码注解-echostate.c
  11. mysql concat函数进行模糊查询
  12. php自动发卡程序8.0_php自动发卡平台源码
  13. java编写自动化脚本_java+selenium自动化脚本编写
  14. APP内跳转QQ和陌生人聊天实现客服功能
  15. Mybatis-Plus 基础知识点
  16. SNS2124SNS2224SNS2248 光纤交换机配置
  17. 全球首份AR报告第二章:AR的工作原理
  18. 女程序员职业生涯发展
  19. win7系统无法更新计算机配置,win7提示无法更新启动配置怎么办
  20. 中文序列标注系列(绪)

热门文章

  1. 修改tomcat端口号、编码
  2. 10-java程序的编译阶段
  3. 单片机sleep函数的头文件_单片机空项目代码解析
  4. 树的直径(51Nod-2602)
  5. String Problem(HDU-3374)
  6. 数据结构 —— 在线操作与离线操作
  7. 15 MM配置-BP业务伙伴-定义供应商主记录的编号范围
  8. c++基础语句(条件判断)
  9. python 中time和datetime_python中time模块与datetime模块的详解
  10. python图像库_Python常用图像处理库整理