Linux文件系统与驱动

268 阅读3分钟

前言

在Linux中一切都是文件,所有的资源都是通过文件的形式来访问控制的。

驱动最终通过文件相关的系统调用来访问,Linux的驱动架构也是基于文件系统而设计的。

Linux文件系统

Linux文件目录

Linux根目录下面存在一些特定的目录,这些目录里面存放约定好的文件。

  • bin 存放基本命令程序
  • sbin 存放系统命令的程序
  • dev 设备文件存储目录,通过这些文件的访问操作来控制设备
  • etc 配置文件目录
  • lib 库文件的存放目录
  • mnt 一般用于存放挂载存储设备的目录, /etc/fstab里面可以设置一些自动挂载的目录
  • opt 可选软件安装目录
  • proc 操作系统运行时, 进程及内核的信息, proc不是真正的文件系统,而是存在内存中的
  • tmp 临时文件目录
  • usr 用户存放程序的目录
  • var 经常变动的文件放在这里 比如log文件
  • sys sysfs文件系统映射的目录。Linux设备驱动模型中的总线、驱动和设备都可以在这里找到对应的文件节点。上篇文章中的内核模块安装后也会在/sys/module里面创建对应的节点。

在内核中,用一个file_operations的结构控制文件的访问接口。每个打开的文件都有一个struct file对应,文件关闭后才释放, 里面存放了文件的一些flag和属性。在vfs中文件还对应一个indode的结构体,保存文件的权限属性、大小、访问时间等。

fs_driver.png

在/proc/devices文件中记录了系统中的所有设备。第一列是主设备号,第二列是设备名。

devfs和udev

devfs设备文件系统使得驱动可以自己管理设备文件,内核2.4版本引入的。一般在驱动加载的时候创建文件,在驱动卸载的时候删除文件。

devfs.png

udev用于取代devfs, 在内核2.6版本引入。udev工作在用户态,利用设备加入或者移除时发送的热插拔事件来工作。在设备热插拔时,内核会通过netlink套接字把信息发送出来, uevent。程序在接收到uevent后,根据信息管理文件。

下面有个例子,接收内核通过netlink发送出来的uevent的。

#include <linux/netlink.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <poll.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>


static void die(char *s)
{
    write(2, s, strlen(s));
    exit(1);
}


int main(void)
{
    struct sockaddr_nl nls;
    struct pollfd pfd;
    char buf[512];

    memset(&nls, 0, sizeof(nls));
    nls.nl_family = AF_NETLINK;
    nls.nl_pid = getpid();
    nls.nl_groups= -1;

    pfd.events = POLLIN;
    pfd.fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
    if (pfd.fd == -1)
        die("not root\r\n");

    if (bind(pfd.fd, (void*)&nls, sizeof(struct sockaddr_nl)))
        die("bind error\n");

    while (-1 != poll(&pfd, 1, -1)) {
        int i, len = recv(pfd.fd, buf, sizeof(buf), MSG_DONTWAIT);
        if (len == -1)
            die("recv\r\n");

        i = 0;
        while (i < len ) {
            printf("%s\r\n", buf+i);
            i += strlen(buf+i) + 1;
        }
    }
    die("poll\r\n");

    return 0;
}

编译运行之后,在virtual虚拟机可以控制CD光盘的加载删除触发uevent, 点击确定。

addcd.png

效果如下:

getuevent.png

对于冷设备, 可以往/sys/module/psmouse/uevent写入一个add触发uevent。


echo "add">/sys/module/psmouse/uevent

#收到的信息如下

ACTION=add
DEVPATH=/module/psmouse
SUBSYSTEM=module
SYNTH_UUID=0
SEQNUM=2736
USEC_INITIALIZED=384805379

udev有对应的工具监控netlink。


udevadm monitor --kernel --property --udev

更多

了解了netlink的使用, udev文件系统的工作的原理, 还有linux系统主要目录的用途、驱动跟文件系统的关联。一步步地加深对Linux内核的了解。

最近看了项目的驱动的代码,从一头雾水到渐渐明晰,这是个学习的过程,通过小结记录下相关的知识,加深印象和理解,不断进步中。。。


行动,才不会被动!

欢迎关注个人公众号 微信 -> 搜索 -> fishmwei,沟通交流。

博客地址: fishmwei.github.io

掘金主页: juejin.cn/user/208432…