Skip to content

Commit e0de0fd

Browse files
authored
根据sysfs完善设备驱动模型 & 添加sysfs官方文档 (#254)
* 根据sysfs完善设备驱动模型 * 添加sysfs官方文档
1 parent f678331 commit e0de0fd

File tree

11 files changed

+581
-150
lines changed

11 files changed

+581
-150
lines changed

docs/kernel/filesystem/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@ todo: 由于文件系统模块重构,文档暂时不可用,预计在2023年4
1111

1212
overview
1313
vfs/index
14+
sysfs
1415

docs/kernel/filesystem/sysfs.md

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# SysFS
2+
3+
:::{note}
4+
本文作者:黄厅
5+
6+
7+
:::
8+
9+
## 1. SysFS和设备驱动模型
10+
11+
### 1.1. 设备、驱动、总线等彼此之间关系错综复杂
12+
13+
  如果想让内核运行流畅,那就必须为每个模块编码实现这些功能。如此一来,内核将变得非常臃肿、冗余。而设备模型的理念即是将这些代码抽象成各模块共用的框架,这样不但代码简洁了,也可让设备驱动开发者摆脱这本让人头痛但又必不可少的一劫,将有限的精力放于设备差异性的实现。
14+
15+
  设备模型恰是提供了一个模板,一个被证明过的最优的思路和流程,这减少了开发者设计过程中不必要的错误,也给以后的维护扫除了障碍。
16+
17+
### 1.2. sysfs是一个基于内存的文件系统,它的作用是将内核信息以文件的方式提供给用户程序使用。
18+
19+
  sysfs可以看成与proc,devfs和devpty同类别的文件系统,该文件系统是虚拟的文件系统,可以更方便对系统设备进行管理。它可以产生一个包含所有系统硬件层次视图,与提供进程和状态信息的proc文件系统十分类似。sysfs把连接在系统上的设备和总线组织成为一个分级的文件,它们可以由用户空间存取,向用户空间导出内核的数据结构以及它们的属性。
20+
21+
## 2. DragosOS中的设备驱动模型
22+
23+
### 2.1 由设备和驱动构成基本元素
24+
25+
#### 2.1.1. 设备
26+
27+
```rust
28+
/// @brief: 所有设备都应该实现该trait
29+
pub trait Device: Any + Send + Sync + Debug {}
30+
```
31+
32+
  DragonOS采用全局设备管理器管理系统中所有的设备。
33+
34+
```rust
35+
/// @brief Device管理器
36+
#[derive(Debug, Clone)]
37+
pub struct DeviceManager {
38+
devices: BTreeMap<IdTable, Arc<dyn Device>>, // 所有设备
39+
sys_info: Option<Arc<dyn IndexNode>>, // sys information
40+
}
41+
```
42+
43+
#### 2.1.2. 驱动
44+
45+
```rust
46+
/// @brief: 所有驱动驱动都应该实现该trait
47+
pub trait Driver: Any + Send + Sync + Debug {}
48+
```
49+
50+
&emsp;&emsp;同样的,驱动也使用全局的驱动管理器来管理
51+
52+
```rust
53+
/// @brief: 驱动管理器
54+
#[derive(Debug, Clone)]
55+
pub struct DriverManager {
56+
drivers: BTreeMap<IdTable, Arc<dyn Driver>>, // 所有驱动
57+
sys_info: Option<Arc<dyn IndexNode>>, // sys information
58+
}
59+
```
60+
61+
### 2.2. 总线
62+
63+
&emsp;&emsp;总线属于设备的一种类型,同样需要驱动来初始化,同时由于总线的特殊性,使用全局的总线管理器来进行管理。
64+
65+
```rust
66+
/// @brief: 总线驱动trait,所有总线驱动都应实现该trait
67+
pub trait BusDriver: Driver {}
68+
69+
/// @brief: 总线设备trait,所有总线都应实现该trait
70+
pub trait Bus: Device {}
71+
72+
/// @brief: 总线管理结构体
73+
#[derive(Debug, Clone)]
74+
pub struct BusManager {
75+
buses: BTreeMap<IdTable, Arc<dyn Bus>>, // 总线设备表
76+
bus_drvs: BTreeMap<IdTable, Arc<dyn BusDriver>>, // 总线驱动表
77+
sys_info: Option<Arc<dyn IndexNode>>, // 总线inode
78+
}
79+
```
80+
81+
&emsp;&emsp;可以看到,每个管理器中均存在sys_info,设备模型通过该成员与sysfs建立联系,sys_info指向sysfs中唯一的inode。对于device而言,对应sysfs下的devices文件夹,其他亦是如此。
82+
83+
## 3. 驱动开发如何进行
84+
85+
&emsp;&emsp;以平台总线platform为例,platform总线是一种虚拟总线,可以对挂载在其上的设备和驱动进行匹配,并驱动设备。该总线是一类设备,同时也是一类总线,编程时需要创建该设备实例,并为设备实例实现Device trait和Bus trait,以表明该结构是一类总线设备。同时,应该实现总线上的匹配规则,不同的总线匹配规则不同,该总线采用匹配表方式进行匹配,设备和驱动都应该存在一份匹配表,表示驱动支持的设备以及设备支持的驱动。
86+
87+
```rust
88+
pub struct CompatibleTable(BTreeSet<&'static str>);
89+
```
90+
91+
&emsp;&emsp;对于bus设备而言,需要调用bus_register,将bus注册进系统,并在sysfs中可视化。
92+
93+
```rust
94+
/// @brief: 总线注册,将总线加入全局总线管理器中,并根据id table在sys/bus和sys/devices下生成文件夹
95+
/// @parameter bus: Bus设备实体
96+
/// @return: 成功:() 失败:DeviceError
97+
pub fn bus_register<T: Bus>(bus: Arc<T>) -> Result<(), DeviceError> {
98+
BUS_MANAGER.add_bus(bus.get_id_table(), bus.clone());
99+
match sys_bus_register(&bus.get_id_table().to_name()) {
100+
Ok(inode) => {
101+
let _ = sys_bus_init(&inode);
102+
return device_register(bus);
103+
}
104+
Err(_) => Err(DeviceError::RegisterError),
105+
}
106+
}
107+
```
108+
109+
&emsp;&emsp;通过bus_register源码可知,该函数不仅在sysfs/bus下生成总线文件夹,同时内部调用device_register,该函数将总线加入设备管理器中,同时在sys/devices下生成设备文件夹。

kernel/src/driver/base/device/bus.rs

Lines changed: 72 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,26 @@
1-
use super::{driver::Driver, Device, DeviceError, DeviceState, IdTable};
1+
use super::{
2+
device_register, device_unregister,
3+
driver::{driver_register, driver_unregister, Driver, DriverError},
4+
Device, DeviceError, DeviceState, IdTable,
5+
};
26
use crate::{
3-
filesystem::sysfs::{self, SYS_BUS_INODE},
4-
kdebug,
7+
filesystem::{
8+
sysfs::{
9+
bus::{sys_bus_init, sys_bus_register},
10+
SYS_BUS_INODE,
11+
},
12+
vfs::IndexNode,
13+
},
514
libs::spinlock::SpinLock,
615
};
716
use alloc::{collections::BTreeMap, sync::Arc};
817
use core::fmt::Debug;
918
use lazy_static::lazy_static;
1019

20+
lazy_static! {
21+
pub static ref BUS_MANAGER: Arc<LockedBusManager> = Arc::new(LockedBusManager::new());
22+
}
23+
1124
/// @brief: 总线状态
1225
#[derive(Debug, Copy, Clone)]
1326
pub enum BusState {
@@ -58,52 +71,31 @@ pub trait BusDriver: Driver {
5871
}
5972

6073
/// @brief: 总线设备trait,所有总线都应实现该trait
61-
pub trait Bus: Device {
62-
/// @brief: 注册bus,在sysfs中生成相应文件夹
63-
/// @parameter name: 文件夹名
64-
/// @return: 注册成功,返回(),注册失败,返回错误码
65-
fn register_bus(&self, name: &str) -> Result<(), DeviceError> {
66-
match self.register_device(name) {
67-
Ok(_) => {
68-
let bus = sysfs::bus::bus_register(name).unwrap();
69-
kdebug!(
70-
"After register_bus: ls /sys/bus/: {:?}",
71-
SYS_BUS_INODE().list()
72-
);
73-
match sysfs::bus::bus_init(&bus) {
74-
Ok(_) => {
75-
kdebug!("After register_bus: ls /sys/bus/{}: {:?}", name, bus.list());
76-
return Ok(());
77-
}
78-
Err(_) => Err(DeviceError::RegisterError),
79-
}
80-
}
81-
Err(err) => Err(err),
82-
}
83-
}
84-
}
74+
pub trait Bus: Device {}
8575

8676
/// @brief: 总线管理结构体
8777
#[derive(Debug, Clone)]
8878
pub struct BusManager {
8979
buses: BTreeMap<IdTable, Arc<dyn Bus>>, // 总线设备表
9080
bus_drvs: BTreeMap<IdTable, Arc<dyn BusDriver>>, // 总线驱动表
81+
sys_info: Option<Arc<dyn IndexNode>>, // 总线inode
9182
}
9283

93-
/// @brief: 总线管理结构体加锁
94-
pub struct BusManagerLock(SpinLock<BusManager>);
84+
/// @brief: bus管理(锁)
85+
pub struct LockedBusManager(SpinLock<BusManager>);
9586

9687
/// @brief: 总线管理方法集
97-
impl BusManagerLock {
88+
impl LockedBusManager {
9889
/// @brief: 创建总线管理实例
9990
/// @parameter: None
10091
/// @return: 总线管理实例
10192
#[inline]
10293
#[allow(dead_code)]
10394
pub fn new() -> Self {
104-
BusManagerLock(SpinLock::new(BusManager {
95+
LockedBusManager(SpinLock::new(BusManager {
10596
buses: BTreeMap::new(),
10697
bus_drvs: BTreeMap::new(),
98+
sys_info: Some(SYS_BUS_INODE()),
10799
}))
108100
}
109101

@@ -124,7 +116,7 @@ impl BusManagerLock {
124116
/// @return: None
125117
#[inline]
126118
#[allow(dead_code)]
127-
pub fn add_bus_driver(&self, id_table: IdTable, bus_drv: Arc<dyn BusDriver>) {
119+
pub fn add_driver(&self, id_table: IdTable, bus_drv: Arc<dyn BusDriver>) {
128120
let mut bus_manager = self.0.lock();
129121
bus_manager.bus_drvs.insert(id_table, bus_drv);
130122
}
@@ -164,12 +156,57 @@ impl BusManagerLock {
164156
/// @return: 总线驱动实例
165157
#[inline]
166158
#[allow(dead_code)]
167-
pub fn get_bus_driver(&self, id_table: &IdTable) -> Option<Arc<dyn BusDriver>> {
159+
pub fn get_driver(&self, id_table: &IdTable) -> Option<Arc<dyn BusDriver>> {
168160
let bus_manager = self.0.lock();
169161
return bus_manager.bus_drvs.get(id_table).cloned();
170162
}
163+
164+
/// @brief: 获取总线管理器的sys information
165+
/// @parameter None
166+
/// @return: sys inode
167+
#[inline]
168+
#[allow(dead_code)]
169+
fn sys_info(&self) -> Option<Arc<dyn IndexNode>> {
170+
return self.0.lock().sys_info.clone();
171+
}
171172
}
172173

173-
lazy_static! {
174-
pub static ref BUS_MANAGER: Arc<BusManagerLock> = Arc::new(BusManagerLock::new());
174+
/// @brief: 总线注册,将总线加入全局总线管理器中,并根据id table在sys/bus和sys/devices下生成文件夹
175+
/// @parameter bus: Bus设备实体
176+
/// @return: 成功:() 失败:DeviceError
177+
pub fn bus_register<T: Bus>(bus: Arc<T>) -> Result<(), DeviceError> {
178+
BUS_MANAGER.add_bus(bus.get_id_table(), bus.clone());
179+
match sys_bus_register(&bus.get_id_table().to_name()) {
180+
Ok(inode) => {
181+
let _ = sys_bus_init(&inode);
182+
return device_register(bus);
183+
}
184+
Err(_) => Err(DeviceError::RegisterError),
185+
}
186+
}
187+
188+
/// @brief: 总线注销,将总线从全局总线管理器中删除,并在sys/bus和sys/devices下删除文件夹
189+
/// @parameter bus: Bus设备实体
190+
/// @return: 成功:() 失败:DeviceError
191+
#[allow(dead_code)]
192+
pub fn bus_unregister<T: Bus>(bus: Arc<T>) -> Result<(), DeviceError> {
193+
BUS_MANAGER.add_bus(bus.get_id_table(), bus.clone());
194+
return device_unregister(bus);
195+
}
196+
197+
/// @brief: 总线驱动注册,将总线驱动加入全局总线管理器中
198+
/// @parameter bus: Bus设备驱动实体
199+
/// @return: 成功:() 失败:DeviceError
200+
pub fn bus_driver_register<T: BusDriver>(bus_driver: Arc<T>) -> Result<(), DriverError> {
201+
BUS_MANAGER.add_driver(bus_driver.get_id_table(), bus_driver.clone());
202+
return driver_register(bus_driver);
203+
}
204+
205+
/// @brief: 总线驱动注销,将总线从全局总线管理器中删除
206+
/// @parameter bus: Bus设备驱动实体
207+
/// @return: 成功:() 失败:DeviceError
208+
#[allow(dead_code)]
209+
pub fn bus_driver_unregister<T: BusDriver>(bus_driver: Arc<T>) -> Result<(), DriverError> {
210+
BUS_MANAGER.add_driver(bus_driver.get_id_table(), bus_driver.clone());
211+
return driver_unregister(bus_driver);
175212
}

0 commit comments

Comments
 (0)