0%

周谈(26)-Linux文件系统与驱动

前言

在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的结构体,保存文件的权限属性、大小、访问时间等。

avatar

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

devfs和udev

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

avatar

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#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, 点击确定。

avatar

效果如下:

avatar

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

1
2
3
4
5
6
7
8
9
10
11
12

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

#收到的信息如下

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

udev有对应的工具监控netlink。

1
2
3

udevadm monitor --kernel --property --udev

更多

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

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


行动,才不会被动!

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

博客地址: https://fishmwei.github.io

掘金主页: https://juejin.cn/user/2084329776486919