我们目前正在使用 Rust 开发单片操作系统 (x86)。我们的货物工作区大致如下所示:
project dir
|--src (contains all kernel related code, omitted here)
| |--main.rs
|
|--user
| |--arch
| | |--link.ld
| |--bin
| |--app1.rs
| |--app2.rs
|
|--Cargo.toml
|--build.rs
在项目工作区的编译过程中,我们创建一个包含用户目录的扁平化二进制文件的 initrd。 (使用
objcopy -O binary --set-section-flags .bss=alloc,load,contents <app> <flat binary>
压平)
内核稍后在运行时将这些二进制文件从 initrd 复制到相应的地址空间中。#[global_allocator]
static ALLOCATOR: LockedHeap = LockedHeap::empty();
当我们现在尝试在其中一个应用程序中创建
#[global_allocator]
时,就会出现问题:
#![no_std]
#![no_main]
#[global_allocator]
static ALLOCATOR: LockedHeap = LockedHeap::empty();
#[no_mangle]
pub extern "C" fn start() -> ! {
let mem_size = 3 * Page::SIZE;
let mem = syscall::mmap(mem_size);
unsafe {
ALLOCATOR.lock().init(mem, mem_size);
}
let v = vec![1, 2, 3];
}
这会在内核映像所在部分的内存位置触发页面错误。 那么我们需要如何更改设置/代码以使用户空间应用程序能够使用不同的堆,以便它们可以使用
alloc
板条箱。
一种选择是不为我们的内核声明
#[global_allocator]
并使用 new_in(...)
板条箱结构的 alloc
不稳定函数。然而,这是一种解决方法,而不是解决方案。经过几个小时的绞尽脑汁,我终于找到了问题的根源。 当我在用户应用程序中定义
#[global_allocator]
时,编译器将 eh_frame_hdr
部分放置在 text
部分通常所在的位置。这可以通过编辑链接器脚本,将 eh_frame_hdr 部分进一步向下移动来修复。