Ранее мы загружали QEMU и при этом использовали образ диска, который был упакован с помощью инструмента rcore-fs-fuse. Этот инструмент позволяет упаковывать файлы из каталога в файловую систему и затем упаковывает эту файловую систему в образ диска. Затем этот образ диска монтируется как устройство в QEMU, где он эмулируется как блочное устройство.
Поскольку файловая система сама по себе довольно обширна, мы используем модуль rcore-fs, который предоставляет множество форматов файловых систем. Мы выбираем самую простую файловую систему — Simple File System (именно поэтому идентификатор устройства в QEMU называется «sfs»). Подробности о файловой системе здесь не раскрываются, можно обратиться к анализу предыдущих разработчиков (../files/rcore-fs-analysis.pdf).
Однако для использования этого модуля необходимо получить доступ к корневому каталогу INode (INode представляет собой абстракцию местоположения файла, а каталог также является разновидностью файла). Все последующие операции с файловой системой могут быть выполнены через корневой каталог.
Здесь мы используем наш старый друг lazy_static, который будет инициализирован при первом использовании ROOT_INODE. Инициализация заключается в поиске первого блочного устройства среди всех устройств драйверов.
lazy_static! {
/// Корневой каталог INode файловой системы
pub static ref ROOT_INODE: Arc<dyn INode> = {
// Выбираем первое блочное устройство
for driver in DRIVERS.read().iter() {
if driver.device_type() == DeviceType::Block {
let device = BlockDevice(driver.clone());
// Динамически выделяем память для устройства Cache
let device_with_cache = Arc::new(BlockCache::new(device, BLOCK_CACHE_CAPACITY));
return SimpleFileSystem::open(device_with_cache)
.expect("failed to open SFS")
.root_inode();
}
}
panic!("failed to load fs")
};
}
Также стоит отметить, что мы добавили BlockCache, модуль, предоставляемый rcore-fs. Он предоставляет абстракцию кэша для хранения данных на устройстве и может быть преобразован в устройство с кэшем с помощью вызова BlockCache::new (device, BLOCK_CACHE_CAPACITY). Наконец, мы можем открыть и вернуть корневой узел с помощью SimpleFileSystem::open.
Наконец, мы подошли к волнующему этапу тестирования! Сначала мы запускаем инициализацию ROOT_INODE, а затем пытаемся вывести содержимое корневого каталога:
/// Выводит все файлы в каталоге
pub fn ls(path: &str) {
let mut id = 0;
let dir = ROOT_INODE.lookup(path).unwrap();
print!("files in {}: \n ", path);
while let Ok(name) = dir.get_entry(id) {
id += 1;
print!("{} ", name);
}
print!("\n");
}
/// Запускает инициализацию [`static@ROOT_INODE`] и выводит содержимое корневого каталога
pub fn init() {
ls("/");
println!("mod fs initialized");
}
В конце основной функции мы тестируем инициализацию, а затем тестируем создание папки в другом потоке ядра. Это делается для проверки операций, связанных с таблицами страниц, которые мы обсуждали ранее в контексте написания драйверов:
/// Функция входа в Rust
///
/// После того как `_start` выполнит ряд подготовительных действий, это первая вызываемая функция Rust
#[no_mangle]
pub extern "C" fn rust_main(_hart_id: usize, dtb_pa: PhysicalAddress) -> ! {
memory::init();
interrupt::init();
drivers::init(dtb_pa);
fs::init();
let process = Process::new_kernel().unwrap();
PROCESSOR
.lock()
.add_thread(Thread::new(process.clone(), simple as usize, Some(&[0])).unwrap());
// Отбрасываем лишнюю ссылку на процесс
drop(process);
PROCESSOR.lock().run()
}
/// Тестирует возможность работы любого потока ядра с файловой системой и драйверами
fn simple(id: usize) {
println!("hello from thread id {}", id);
// Создаём новую папку
fs::ROOT_INODE
.create("tmp", rcore_fs::vfs::FileType::Dir, 0o666)
.expect("failed to mkdir /tmp");
// Выводим содержимое корневого файла
fs::ls("/");
loop {}
}
После выполнения make run вы получите аналогичный вывод:
mod memory initialized
mod interrupt initialized
mod driver initialized
files in /:
. .. temp rust
mod fs initialized
hello from thread id 0
files in /:
. .. temp rust tmp
100 tick
200 tick
...
Успех! Система правильно считывает файлы и корректно создаёт файлы, обеспечивая хорошую защиту для последующего размещения данных пользовательских процессов.
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )