热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

《Linux4.0设备驱动开发详解》笔记第五章:Linux文件系统与设备文件

5.1Linux文件操作5.1.1文件操作系统调用创建intcreate(constchar*filename,mode_tmode);mode是存取权限,它同uma

5.1 Linux文件操作

5.1.1 文件操作系统调用

  • 创建

int create(const char *filename, mode_t mode);

mode是存取权限,它同umask(在文件创建时需要去掉的一些权限)一起共同决定文件的最终权限
mode:O_…组合
- 打开

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

如果flags使用了O_CREAT标志,则使用第二个函数,指明创建并打开的文件权限
数字表示权限的含义
第一位 第二位 第三位 第四位 第五位
用户ID 组ID 自己的权限 组的权限 其他人的权限
例如:创建用户可读写执行,组没有权限,其他人可读执行 => 10 705

open("test", O_CREAT, 10 705);
等价于
open("test", O_CREAT, S_IRWXU | S_IROTH | S_IXOTH | S_ISUID);

  • 读写

int read(int fd, const void *buf, size_t length);
int write(int fd, const void *buf, size_t length);

  • 定位

int lseek(int fd, offset_t offset, int whence);

SEEK_SET:相对于文件开头
SEEK_CUR:相对于当前指针
SEEK_END:相对于文件末尾
offset:可为负数
lseek(fd, 0, SEEK_END);表示文件的长度

  • 关闭

int close(int fd);

5.1.2 库函数操作

  • 创建和打开

FILE *fopen(const char *path, const char *mode);

mode : r w b 组合
linux不区分文本文件和二进制文件

  • 读写

int fgetc(FILE *stream);
int fputc(int c, FILE *stream);
char *fgets(char *s, int n, FILE *stream);
int fputs(const char *s, FILE *stream);
int fprintf(FILE *stream, const char *format,...);
int fscanf(FILE *stream, const char *format,...);
size_t fread(void *ptr, size_t size, size_t n, FILE *stream);
size_t fwrite(void *ptr, size_t size, size_t n, FILE *stream);

  • 关闭

int fclose(FILE *stream);

5.2 Linux文件系统

5.2.1 Linux文件系统目录结构

  • /bin:包含基本命令,如ls、cp等
  • /sbin:系统命令,如modprobe、ifconfig等
  • /dev:设备文件存储目录,应用文件通过对这些文件的读写来控制实际设备
  • /etc:系统配置文件,如账号密码的配置文件,busybox的启动脚本也在这里
  • /lib:系统库文件
  • /mnt:挂载目录,如cdrom等目录
  • /proc:系统运行时,进程及内核信息(CPU、硬盘分区、内存信息等)存放在这里。/proc目录是为文件系统proc的挂载目录,proc不是真正的文件系统,它存在内存中
  • /tmp:存放运行程序是产生的临时文件
  • /usr:系统存放程序的目录,如用户命令、用户库等
  • /sys:sysfs文件系统的映射目录,Linux设备驱动模型中的总线、驱动和设备都可以在该目录下找到对应的节点。当内核检测到新设备时,会在sysfs文件系统中为该设备生成一项新的记录

5.2.2 Linux文件系统与设备驱动

  • file:代表一个打开的文件,每个打开的文件在内核中都有一个关联的struct file。
  • inode:包含文件访问权限、属主、组、大小、生成时间、访问时间、最后修改时间等信息
  • stat + 文件名 =>查看文件的inode信息
  • inode成员i_rdev字段包含设备号:前12是主设备号,后20位是此设备号
    • unsigned int ininor(struct inode *inode)
    • unsigned int imajor(struct inode *inode)
  • cat /proc/devices:查看系统注册的设备
    • 第一列为主设备号
    • 第二列为此设备号
  • /dev/目录中包含有设备文件
  • 参考
    http://www.cnblogs.com/itech/archive/2012/05/15/2502284.html

5.3 devfs

  • Linux2.4内核引进,但现在已经由udev取代

5.4 udev用户空间设备管理

5.4.1 udev与devfs区别

  • 机制与策略
    • 机制:做某件事的方法,相对固定不变
    • 策略:每个步骤采取的方法,灵活不固定
    • 内核中不应该出现策略
  • udev是利用设备的加入或者移除的时候内核所发送的热拔插事件来工作
    • 热拔插时设备的详细信息会由内核通过netlink套接字来发送出uevent事件
  • udev对冷拔插的处理
    • Linux提供sysfs下面1个uevent节点,往该节点下写一个“add”,导致内核重新发送netlink,之后udev就会收到冷拔插的netlink消息了

5.4.2 sysfs系统与Linux设备模型

  • sysfs是与proc、devfs和devpty同类别的虚拟文件系统,它可以产生包括所有的硬件系统的层级视图
  • sysfs把连接在系统上的设备和总线组织成一个分级的文件,他们可以由用户空间存取,向用户空间导出内核数据结构以及他们的属性
  • sysfs的一个目的是展示设备驱动模型中各组件的层次关系,顶层目录包括
    • block:所有的设备快
    • bus:所有的总线类型
    • dev
    • devices
    • class:系统中的设备类型(如网卡设备、声卡设备、输入设备等)
    • fs
    • kernel
    • power
  • bus_type表示总线,device_driver表示驱动,device表示设备
  • 设备和驱动必须依附于总线
    • 设备和驱动是独立分开注册的,注册设备的时候不需要其驱动已经注册,反之亦然
    • 设备和驱动各自共享·涌向内核,寻找自己的另一半,总线通过match()函数匹配两者
    • 匹配成功会调用xxx_driver的probe函数(xxx是总线的名字,如PCI、spi、USB等)
  • 总系、设备和驱动最终落实为sysfs中的一个目录,其attribute则落实为目录下的文件
    • 总线、设备和驱动实际上可以认为是kobject的派生类,kobject可以看作是总线、设备和驱动的抽象类
    • 1个kobject对应着sysfs的一个目录
    • attribute包好show和store两个函数,其用于attribute对应的sysfs的文件读写
  • 事实上,sysfs的目录源于bus_type、device_driver和device,而目录中的文件则来源于attribute
  • 例如:在driver/base/bus.c文件中找到这样的代码

static BUS_ATTR(driver_prove, ...);
static BUS_ATTR(driver_autoprove, ...);
static BUS_ATTR(uevent, ...);

而在/sys/bus/platform等里面可以找到对应的文件

$ls
devices drivers drivers_autoprove drivers_probe uevent

udev的组成

  • udev目前和systemd项目合并在一起了
  • udev在用户空间中执行,动态的建立或删除设备的文件,允许每个人都不用关心主次设备号而提供LBS(Linux标准规范)名字,并且根据需要固定名称
  • udev的工作过程
    • 当内核检测到系统中出现了新的设备的时候,内核会通过netlink套接字发送uevent
    • udev获取内核发送的信息,进行规则的匹配
      • 匹配的事物包括:SUBSYSTEM、ACTION、attribute、内核提供的名称(通过KETNEL=)以及其他的环境变量
  • 例如:在Linux系统上插入Kingston的U盘,通过udev的工具“udevadm monitor–kernel –property –udev”捕获到uevent包含的信息(包括U盘的设备商、U盘的类型、设备编号等等),根据这些信息创建一个规则,以便在插入的时候,为该U盘创建一个/dev/KingstomUD的符号链接

SUBSYSTEM=="block", ACTION=="add", KERNEL=="*sd", ENV{ID_TYPE}=="disk", ENV{ID_VENDOR}=="Kingston", ENV{ID_USB_DRIVER}=="usb-storage", SYMLINK+="kingstonUD"

插入U盘后就会自动的在/dev/下面创建一个符号链接

5.4.4 udev 规则文件

  • 规则文件一行为单位,以“#”为行代表注释符,其余的每一行代表一个规则
  • 每个规则分成一个或多个匹配部分和赋值部分
    • 匹配部分和赋值部分用专用的关键字来表示
    • 匹配关键字包括:ACTION/KERNEL/BUS/SUBSYSTEM/ATTR等
    • 赋值关键字包括:NAME/SYMLINK/OWNER/GROUP/IMPORT/MODE等
  • 例如

SUBSYSTEM=="net", ACTION=="add", KERNEL=="?*", ATTR{address}=="08:00:27:35:be:ff", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="ETH1"

- 规则意思:当系统中出现新的硬件属于net子系统范畴,系统柜该硬件采取的动作是“add”这个硬件,且这个硬件的address属性信息等于“08:00:27:35:be:ff”,dev_id属性等于“0x0”,"type"属性是1等,这个硬件在udev层次实行的动作是创建/dev/eth1.

  • udev 规则可以使用通配符,如*,?,[a-z]等,此外,%k就是KERNEL,%n就是KERNEL的序号(如存储设备的分区号)
  • Android采用的和udev类似的void机制

转载于:https://www.cnblogs.com/zcjboke/p/5513140.html


推荐阅读
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 在Docker中,将主机目录挂载到容器中作为volume使用时,常常会遇到文件权限问题。这是因为容器内外的UID不同所导致的。本文介绍了解决这个问题的方法,包括使用gosu和suexec工具以及在Dockerfile中配置volume的权限。通过这些方法,可以避免在使用Docker时出现无写权限的情况。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • 本文讨论了Kotlin中扩展函数的一些惯用用法以及其合理性。作者认为在某些情况下,定义扩展函数没有意义,但官方的编码约定支持这种方式。文章还介绍了在类之外定义扩展函数的具体用法,并讨论了避免使用扩展函数的边缘情况。作者提出了对于扩展函数的合理性的质疑,并给出了自己的反驳。最后,文章强调了在编写Kotlin代码时可以自由地使用扩展函数的重要性。 ... [详细]
  • 本文讨论了在openwrt-17.01版本中,mt7628设备上初始化启动时eth0的mac地址总是随机生成的问题。每次随机生成的eth0的mac地址都会写到/sys/class/net/eth0/address目录下,而openwrt-17.01原版的SDK会根据随机生成的eth0的mac地址再生成eth0.1、eth0.2等,生成后的mac地址会保存在/etc/config/network下。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • CEPH LIO iSCSI Gateway及其使用参考文档
    本文介绍了CEPH LIO iSCSI Gateway以及使用该网关的参考文档,包括Ceph Block Device、CEPH ISCSI GATEWAY、USING AN ISCSI GATEWAY等。同时提供了多个参考链接,详细介绍了CEPH LIO iSCSI Gateway的配置和使用方法。 ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • 本文介绍了一些Java开发项目管理工具及其配置教程,包括团队协同工具worktil,版本管理工具GitLab,自动化构建工具Jenkins,项目管理工具Maven和Maven私服Nexus,以及Mybatis的安装和代码自动生成工具。提供了相关链接供读者参考。 ... [详细]
  • 本文详细介绍了如何使用MySQL来显示SQL语句的执行时间,并通过MySQL Query Profiler获取CPU和内存使用量以及系统锁和表锁的时间。同时介绍了效能分析的三种方法:瓶颈分析、工作负载分析和基于比率的分析。 ... [详细]
  • 【shell】网络处理:判断IP是否在网段、两个ip是否同网段、IP地址范围、网段包含关系
    本文介绍了使用shell脚本判断IP是否在同一网段、判断IP地址是否在某个范围内、计算IP地址范围、判断网段之间的包含关系的方法和原理。通过对IP和掩码进行与计算,可以判断两个IP是否在同一网段。同时,还提供了一段用于验证IP地址的正则表达式和判断特殊IP地址的方法。 ... [详细]
author-avatar
Carre陈
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有