Revert "新的内存管理模块 (#301)" (#302)

This reverts commit d8ad0a5e77.
This commit is contained in:
LoGin
2023-07-22 16:24:55 +08:00
committed by GitHub
parent d8ad0a5e77
commit bb5f098a86
124 changed files with 5151 additions and 8278 deletions

View File

@ -1,86 +0,0 @@
/// An enumeration of the possible values for the `AT_*` constants.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum AtType {
/// End of vector.
Null,
/// Entry should be ignored.
Ignore,
/// File descriptor of program.
ExecFd,
/// Program headers for program.
Phdr,
/// Size of program header entry.
PhEnt,
/// Number of program headers.
PhNum,
/// System page size.
PageSize,
/// Base address of interpreter.
Base,
/// Flags.
Flags,
/// Entry point of program.
Entry,
/// Program is not ELF.
NotElf,
/// Real uid.
Uid,
/// Effective uid.
EUid,
/// Real gid.
Gid,
/// Effective gid.
EGid,
/// String identifying CPU for optimizations.
Platform,
/// Arch dependent hints at CPU capabilities.
HwCap,
/// Frequency at which times() increments.
ClkTck,
/// Secure mode boolean.
Secure,
/// String identifying real platform, may differ from AT_PLATFORM.
BasePlatform,
/// Address of 16 random bytes.
Random,
/// Extension of AT_HWCAP.
HwCap2,
/// Filename of program.
ExecFn,
/// Minimal stack size for signal delivery.
MinSigStackSize,
}
impl TryFrom<u32> for AtType {
type Error = &'static str;
fn try_from(value: u32) -> Result<Self, Self::Error> {
match value {
0 => Ok(AtType::Null),
1 => Ok(AtType::Ignore),
2 => Ok(AtType::ExecFd),
3 => Ok(AtType::Phdr),
4 => Ok(AtType::PhEnt),
5 => Ok(AtType::PhNum),
6 => Ok(AtType::PageSize),
7 => Ok(AtType::Base),
8 => Ok(AtType::Flags),
9 => Ok(AtType::Entry),
10 => Ok(AtType::NotElf),
11 => Ok(AtType::Uid),
12 => Ok(AtType::EUid),
13 => Ok(AtType::Gid),
14 => Ok(AtType::EGid),
15 => Ok(AtType::Platform),
16 => Ok(AtType::HwCap),
17 => Ok(AtType::ClkTck),
23 => Ok(AtType::Secure),
24 => Ok(AtType::BasePlatform),
25 => Ok(AtType::Random),
26 => Ok(AtType::HwCap2),
31 => Ok(AtType::ExecFn),
51 => Ok(AtType::MinSigStackSize),
_ => Err("Invalid value for AtType"),
}
}
}

View File

@ -1,115 +0,0 @@
use core::{ffi::c_void, ptr::null_mut};
use alloc::boxed::Box;
use crate::{
arch::{asm::current::current_pcb, fpu::FpState},
include::bindings::bindings::process_control_block,
syscall::SystemError,
};
use super::{fork::copy_mm, process::init_stdio, process_init};
#[no_mangle]
pub extern "C" fn rs_process_init() {
process_init();
}
#[no_mangle]
pub extern "C" fn rs_process_copy_mm(clone_vm: bool, new_pcb: &mut process_control_block) -> usize {
return copy_mm(clone_vm, new_pcb)
.map(|_| 0)
.unwrap_or_else(|err| err.to_posix_errno() as usize);
}
/// @brief 初始化当前进程的文件描述符数组
/// 请注意,如果当前进程已经有文件描述符数组,那么本操作将被禁止
#[no_mangle]
pub extern "C" fn process_init_files() -> i32 {
let r = current_pcb().init_files();
if r.is_ok() {
return 0;
} else {
return r.unwrap_err().to_posix_errno();
}
}
#[no_mangle]
pub extern "C" fn rs_drop_address_space(pcb: &'static mut process_control_block) -> i32 {
unsafe {
pcb.drop_address_space();
}
return 0;
}
/// @brief 拷贝当前进程的文件描述符信息
///
/// @param clone_flags 克隆标志位
/// @param pcb 新的进程的pcb
#[no_mangle]
pub extern "C" fn process_copy_files(
clone_flags: u64,
from: &'static process_control_block,
) -> i32 {
let r = current_pcb().copy_files(clone_flags, from);
if r.is_ok() {
return 0;
} else {
return r.unwrap_err().to_posix_errno();
}
}
/// @brief 回收进程的文件描述符数组
///
/// @param pcb 要被回收的进程的pcb
///
/// @return i32
#[no_mangle]
pub extern "C" fn process_exit_files(pcb: &'static mut process_control_block) -> i32 {
let r: Result<(), SystemError> = pcb.exit_files();
if r.is_ok() {
return 0;
} else {
return r.unwrap_err().to_posix_errno();
}
}
/// @brief 复制当前进程的浮点状态
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn rs_dup_fpstate() -> *mut c_void {
// 如果当前进程没有浮点状态,那么就返回一个默认的浮点状态
if current_pcb().fp_state == null_mut() {
return Box::leak(Box::new(FpState::default())) as *mut FpState as usize as *mut c_void;
} else {
// 如果当前进程有浮点状态,那么就复制一个新的浮点状态
let state = current_pcb().fp_state as usize as *mut FpState;
unsafe {
let s = state.as_ref().unwrap();
let state: &mut FpState = Box::leak(Box::new(s.clone()));
return state as *mut FpState as usize as *mut c_void;
}
}
}
/// @brief 释放进程的浮点状态所占用的内存
#[no_mangle]
pub extern "C" fn rs_process_exit_fpstate(pcb: &'static mut process_control_block) {
if pcb.fp_state != null_mut() {
let state = pcb.fp_state as usize as *mut FpState;
unsafe {
drop(Box::from_raw(state));
}
}
}
#[no_mangle]
pub extern "C" fn rs_init_stdio() -> i32 {
let r = init_stdio();
if r.is_ok() {
return 0;
} else {
return r.unwrap_err().to_posix_errno();
}
}

View File

@ -1,288 +0,0 @@
use core::{fmt::Debug, ptr::null};
use alloc::{collections::BTreeMap, string::String, sync::Arc, vec::Vec};
use crate::{
filesystem::vfs::{
file::{File, FileMode},
ROOT_INODE,
},
io::SeekFrom,
libs::elf::ELF_LOADER,
mm::{
ucontext::{AddressSpace, UserStack},
VirtAddr,
},
syscall::SystemError,
};
/// 系统支持的所有二进制文件加载器的列表
const BINARY_LOADERS: [&'static dyn BinaryLoader; 1] = [&ELF_LOADER];
pub trait BinaryLoader: 'static + Debug {
/// 检查二进制文件是否为当前加载器支持的格式
fn probe(self: &'static Self, param: &ExecParam, buf: &[u8]) -> Result<(), ExecError>;
fn load(
self: &'static Self,
param: &mut ExecParam,
head_buf: &[u8],
) -> Result<BinaryLoaderResult, ExecError>;
}
/// 二进制文件加载结果
#[derive(Debug)]
pub struct BinaryLoaderResult {
/// 程序入口地址
entry_point: VirtAddr,
}
impl BinaryLoaderResult {
pub fn new(entry_point: VirtAddr) -> Self {
Self { entry_point }
}
pub fn entry_point(&self) -> VirtAddr {
self.entry_point
}
}
#[allow(dead_code)]
#[derive(Debug)]
pub enum ExecError {
/// 二进制文件不可执行
NotExecutable,
/// 二进制文件不是当前架构的
WrongArchitecture,
/// 访问权限不足
PermissionDenied,
/// 不支持的操作
NotSupported,
/// 解析文件本身的时候出现错误(比如一些字段本身不合法)
ParseError,
/// 内存不足
OutOfMemory,
/// 参数错误
InvalidParemeter,
/// 无效的地址
BadAddress(Option<VirtAddr>),
Other(String),
}
impl Into<SystemError> for ExecError {
fn into(self) -> SystemError {
match self {
ExecError::NotExecutable => SystemError::ENOEXEC,
ExecError::WrongArchitecture => SystemError::EOPNOTSUPP_OR_ENOTSUP,
ExecError::PermissionDenied => SystemError::EACCES,
ExecError::NotSupported => SystemError::EOPNOTSUPP_OR_ENOTSUP,
ExecError::ParseError => SystemError::ENOEXEC,
ExecError::OutOfMemory => SystemError::ENOMEM,
ExecError::InvalidParemeter => SystemError::EINVAL,
ExecError::BadAddress(_addr) => SystemError::EFAULT,
ExecError::Other(_msg) => SystemError::ENOEXEC,
}
}
}
bitflags! {
pub struct ExecParamFlags: u32 {
// 是否以可执行文件的形式加载
const EXEC = 1 << 0;
}
}
#[derive(Debug)]
pub struct ExecParam<'a> {
file_path: &'a str,
file: Option<File>,
vm: Arc<AddressSpace>,
/// 一些标志位
flags: ExecParamFlags,
/// 用来初始化进程的一些信息。这些信息由二进制加载器和exec机制来共同填充
init_info: ProcInitInfo,
}
#[derive(Debug, Eq, PartialEq)]
pub enum ExecLoadMode {
/// 以可执行文件的形式加载
Exec,
/// 以动态链接库的形式加载
DSO,
}
#[allow(dead_code)]
impl<'a> ExecParam<'a> {
pub fn new(file_path: &'a str, vm: Arc<AddressSpace>, flags: ExecParamFlags) -> Self {
Self {
file_path,
file: None,
vm,
flags,
init_info: ProcInitInfo::new(),
}
}
pub fn file_path(&self) -> &'a str {
self.file_path
}
pub fn vm(&self) -> &Arc<AddressSpace> {
&self.vm
}
pub fn flags(&self) -> &ExecParamFlags {
&self.flags
}
pub fn init_info(&self) -> &ProcInitInfo {
&self.init_info
}
pub fn init_info_mut(&mut self) -> &mut ProcInitInfo {
&mut self.init_info
}
/// 获取加载模式
pub fn load_mode(&self) -> ExecLoadMode {
if self.flags.contains(ExecParamFlags::EXEC) {
ExecLoadMode::Exec
} else {
ExecLoadMode::DSO
}
}
pub fn file_mut(&mut self) -> &mut File {
self.file.as_mut().unwrap()
}
}
/// ## 加载二进制文件
pub fn load_binary_file(param: &mut ExecParam) -> Result<BinaryLoaderResult, SystemError> {
let inode = ROOT_INODE().lookup(param.file_path)?;
// 读取文件头部,用于判断文件类型
let file = File::new(inode, FileMode::O_RDONLY)?;
param.file = Some(file);
let mut head_buf = [0u8; 512];
param.file_mut().lseek(SeekFrom::SeekSet(0))?;
let _bytes = param.file_mut().read(512, &mut head_buf)?;
// kdebug!("load_binary_file: read {} bytes", _bytes);
let mut loader = None;
for bl in BINARY_LOADERS.iter() {
let probe_result = bl.probe(param, &head_buf);
if probe_result.is_ok() {
loader = Some(bl);
break;
}
}
// kdebug!("load_binary_file: loader: {:?}", loader);
if loader.is_none() {
return Err(SystemError::ENOEXEC);
}
let loader: &&dyn BinaryLoader = loader.unwrap();
assert!(param.vm().is_current());
// kdebug!("load_binary_file: to load with param: {:?}", param);
let result: BinaryLoaderResult = loader
.load(param, &head_buf)
.unwrap_or_else(|e| panic!("load_binary_file failed: error: {e:?}, param: {param:?}"));
// kdebug!("load_binary_file: load success");
return Ok(result);
}
/// 程序初始化信息,这些信息会被压入用户栈中
#[derive(Debug)]
pub struct ProcInitInfo {
pub args: Vec<String>,
pub envs: Vec<String>,
pub auxv: BTreeMap<u8, usize>,
}
impl ProcInitInfo {
pub fn new() -> Self {
Self {
args: Vec::new(),
envs: Vec::new(),
auxv: BTreeMap::new(),
}
}
/// 把程序初始化信息压入用户栈中
/// 这个函数会把参数、环境变量、auxv等信息压入用户栈中
///
/// ## 返回值
///
/// 返回值是一个元组第一个元素是最终的用户栈顶地址第二个元素是环境变量pointer数组的起始地址
pub unsafe fn push_at(
&self,
ustack: &mut UserStack,
) -> Result<(VirtAddr, VirtAddr), SystemError> {
// 先把程序的名称压入栈中
self.push_str(ustack, self.args[0].as_str())?;
// 然后把环境变量压入栈中
let envps = self
.envs
.iter()
.map(|s| {
self.push_str(ustack, s.as_str()).expect("push_str failed");
ustack.sp()
})
.collect::<Vec<_>>();
// 然后把参数压入栈中
let argps = self
.args
.iter()
.map(|s| {
self.push_str(ustack, s.as_str()).expect("push_str failed");
ustack.sp()
})
.collect::<Vec<_>>();
// 压入auxv
self.push_slice(ustack, &[null::<u8>(), null::<u8>()])?;
for (&k, &v) in self.auxv.iter() {
self.push_slice(ustack, &[k as usize, v])?;
}
// 把环境变量指针压入栈中
self.push_slice(ustack, &[null::<u8>()])?;
self.push_slice(ustack, envps.as_slice())?;
// 把参数指针压入栈中
self.push_slice(ustack, &[null::<u8>()])?;
self.push_slice(ustack, argps.as_slice())?;
let argv_ptr = ustack.sp();
// 把argc压入栈中
self.push_slice(ustack, &[self.args.len()])?;
return Ok((ustack.sp(), argv_ptr));
}
fn push_slice<T: Copy>(&self, ustack: &mut UserStack, slice: &[T]) -> Result<(), SystemError> {
let mut sp = ustack.sp();
sp -= slice.len() * core::mem::size_of::<T>();
sp -= sp.data() % core::mem::align_of::<T>();
unsafe { core::slice::from_raw_parts_mut(sp.data() as *mut T, slice.len()) }
.copy_from_slice(slice);
unsafe {
ustack.set_sp(sp);
}
return Ok(());
}
fn push_str(&self, ustack: &mut UserStack, s: &str) -> Result<(), SystemError> {
self.push_slice(ustack, &[b'\0'])?;
self.push_slice(ustack, s.as_bytes())?;
return Ok(());
}
}

View File

@ -10,7 +10,6 @@ extern void kernel_thread_func(void);
extern uint64_t rs_procfs_register_pid(uint64_t);
extern uint64_t rs_procfs_unregister_pid(uint64_t);
extern void *rs_dup_fpstate();
extern uint64_t rs_process_copy_mm(bool clone_vm, struct process_control_block *new_pcb);
extern int process_copy_files(uint64_t clone_flags, struct process_control_block *pcb);
int process_copy_flags(uint64_t clone_flags, struct process_control_block *pcb);
@ -138,7 +137,7 @@ unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned
// 创建对应procfs文件
rs_procfs_register_pid(tsk->pid);
// kdebug("Fork ok. pid: %d\n", tsk->pid);
// 唤醒进程
process_wakeup(tsk);
@ -186,9 +185,88 @@ int process_copy_flags(uint64_t clone_flags, struct process_control_block *pcb)
*/
int process_copy_mm(uint64_t clone_flags, struct process_control_block *pcb)
{
pcb->address_space = NULL;
bool clone_vm = (clone_flags & CLONE_VM);
return (int)rs_process_copy_mm(clone_vm, pcb);
int retval = 0;
// 与父进程共享内存空间
if (clone_flags & CLONE_VM)
{
pcb->mm = current_pcb->mm;
return retval;
}
// 分配新的内存空间分布结构体
struct mm_struct *new_mms = (struct mm_struct *)kmalloc(sizeof(struct mm_struct), 0);
memset(new_mms, 0, sizeof(struct mm_struct));
memcpy(new_mms, current_pcb->mm, sizeof(struct mm_struct));
new_mms->vmas = NULL;
pcb->mm = new_mms;
// 分配顶层页表, 并设置顶层页表的物理地址
new_mms->pgd = (pml4t_t *)virt_2_phys(kmalloc(PAGE_4K_SIZE, 0));
// 由于高2K部分为内核空间在接下来需要覆盖其数据因此不用清零
memset(phys_2_virt(new_mms->pgd), 0, PAGE_4K_SIZE / 2);
// 拷贝内核空间的页表指针
memcpy(phys_2_virt(new_mms->pgd) + 256, phys_2_virt(initial_proc[proc_current_cpu_id]->mm->pgd) + 256,
PAGE_4K_SIZE / 2);
uint64_t *current_pgd = (uint64_t *)phys_2_virt(current_pcb->mm->pgd);
uint64_t *new_pml4t = (uint64_t *)phys_2_virt(new_mms->pgd);
// 拷贝用户空间的vma
struct vm_area_struct *vma = current_pcb->mm->vmas;
while (vma != NULL)
{
if (vma->vm_end > USER_MAX_LINEAR_ADDR || vma->vm_flags & VM_DONTCOPY)
{
vma = vma->vm_next;
continue;
}
int64_t vma_size = vma->vm_end - vma->vm_start;
// kdebug("vma_size=%ld, vm_start=%#018lx", vma_size, vma->vm_start);
if (vma_size > PAGE_2M_SIZE / 2)
{
int page_to_alloc = (PAGE_2M_ALIGN(vma_size)) >> PAGE_2M_SHIFT;
for (int i = 0; i < page_to_alloc; ++i)
{
uint64_t pa = alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys;
struct vm_area_struct *new_vma = NULL;
int ret = mm_create_vma(new_mms, vma->vm_start + i * PAGE_2M_SIZE, PAGE_2M_SIZE, vma->vm_flags,
vma->vm_ops, &new_vma);
// 防止内存泄露
if (unlikely(ret == -EEXIST))
free_pages(Phy_to_2M_Page(pa), 1);
else
mm_map_vma(new_vma, pa, 0, PAGE_2M_SIZE);
memcpy((void *)phys_2_virt(pa), (void *)(vma->vm_start + i * PAGE_2M_SIZE),
(vma_size >= PAGE_2M_SIZE) ? PAGE_2M_SIZE : vma_size);
vma_size -= PAGE_2M_SIZE;
}
}
else
{
uint64_t map_size = PAGE_4K_ALIGN(vma_size);
uint64_t va = (uint64_t)kmalloc(map_size, 0);
struct vm_area_struct *new_vma = NULL;
int ret = mm_create_vma(new_mms, vma->vm_start, map_size, vma->vm_flags, vma->vm_ops, &new_vma);
// 防止内存泄露
if (unlikely(ret == -EEXIST))
kfree((void *)va);
else
mm_map_vma(new_vma, virt_2_phys(va), 0, map_size);
memcpy((void *)va, (void *)vma->vm_start, vma_size);
}
vma = vma->vm_next;
}
return retval;
}
/**

View File

@ -44,7 +44,7 @@ pub extern "C" fn process_copy_sighand(clone_flags: u64, pcb: *mut process_contr
// kdebug!("DEFAULT_SIGACTION.sa_flags={}", DEFAULT_SIGACTION.sa_flags);
// 拷贝sigaction
let mut flags: usize = 0;
let mut flags: u64 = 0;
spin_lock_irqsave(unsafe { &mut (*current_pcb().sighand).siglock }, &mut flags);
compiler_fence(core::sync::atomic::Ordering::SeqCst);
@ -64,7 +64,7 @@ pub extern "C" fn process_copy_sighand(clone_flags: u64, pcb: *mut process_contr
}
compiler_fence(core::sync::atomic::Ordering::SeqCst);
spin_unlock_irqrestore(unsafe { &mut (*current_pcb().sighand).siglock }, flags);
spin_unlock_irqrestore(unsafe { &mut (*current_pcb().sighand).siglock }, &flags);
compiler_fence(core::sync::atomic::Ordering::SeqCst);
// 将信号的处理函数设置为default(除了那些被手动屏蔽的)
@ -131,39 +131,3 @@ pub extern "C" fn process_exit_sighand(pcb: *mut process_control_block) {
(*pcb).signal = 0 as *mut crate::include::bindings::bindings::signal_struct;
}
}
/// 拷贝进程的地址空间
///
/// ## 参数
///
/// - `clone_vm`: 是否与父进程共享地址空间。true表示共享
/// - `new_pcb`: 新进程的pcb
///
/// ## 返回值
///
/// - 成功返回Ok(())
/// - 失败返回Err(SystemError)
///
/// ## Panic
///
/// - 如果当前进程没有用户地址空间则panic
pub fn copy_mm(clone_vm: bool, new_pcb: &mut process_control_block) -> Result<(), SystemError> {
// kdebug!("copy_mm, clone_vm: {}", clone_vm);
let old_address_space = current_pcb()
.address_space()
.expect("copy_mm: Failed to get address space of current process.");
if clone_vm {
unsafe { new_pcb.set_address_space(old_address_space) };
return Ok(());
}
let new_address_space = old_address_space.write().try_clone().unwrap_or_else(|e| {
panic!(
"copy_mm: Failed to clone address space of current process, current pid: [{}], new pid: [{}]. Error: {:?}",
current_pcb().pid, new_pcb.pid, e
)
});
unsafe { new_pcb.set_address_space(new_address_space) };
return Ok(());
}

View File

@ -1,38 +1,6 @@
use core::{
ptr::null_mut,
sync::atomic::{compiler_fence, Ordering},
};
use crate::{
arch::asm::current::current_pcb,
kdebug,
mm::{
set_INITIAL_PROCESS_ADDRESS_SPACE, ucontext::AddressSpace, INITIAL_PROCESS_ADDRESS_SPACE,
},
};
pub mod abi;
pub mod c_adapter;
pub mod exec;
pub mod fork;
pub mod initial_proc;
pub mod pid;
pub mod preempt;
pub mod process;
pub mod syscall;
pub fn process_init() {
unsafe {
compiler_fence(Ordering::SeqCst);
current_pcb().address_space = null_mut();
kdebug!("To create address space for INIT process.");
// test_buddy();
set_INITIAL_PROCESS_ADDRESS_SPACE(
AddressSpace::new(true).expect("Failed to create address space for INIT process."),
);
kdebug!("INIT process address space created.");
compiler_fence(Ordering::SeqCst);
current_pcb().set_address_space(INITIAL_PROCESS_ADDRESS_SPACE());
compiler_fence(Ordering::SeqCst);
};
}

View File

@ -61,14 +61,14 @@ struct thread_struct
// ========= pcb->flags =========
// 进程标志位
#define PF_KTHREAD (1UL << 0) // 内核线程
#define PF_NEED_SCHED (1UL << 1) // 进程需要被调度
#define PF_VFORK (1UL << 2) // 标志进程是否由于vfork而存在资源共享
#define PF_KFORK (1UL << 3) // 标志在内核态下调用fork临时标记do_fork()结束后会将其复位)
#define PF_NOFREEZE (1UL << 4) // 当前进程不能被冻结
#define PF_EXITING (1UL << 5) // 进程正在退出
#define PF_WAKEKILL (1UL << 6) // 进程由于接收到终止信号唤醒
#define PF_SIGNALED (1UL << 7) // 进程由于接收到信号而退出
#define PF_KTHREAD (1UL << 0) // 内核线程
#define PF_NEED_SCHED (1UL << 1) // 进程需要被调度
#define PF_VFORK (1UL << 2) // 标志进程是否由于vfork而存在资源共享
#define PF_KFORK (1UL << 3) // 标志在内核态下调用fork临时标记do_fork()结束后会将其复位)
#define PF_NOFREEZE (1UL << 4) // 当前进程不能被冻结
#define PF_EXITING (1UL << 5) // 进程正在退出
#define PF_WAKEKILL (1UL << 6) // 进程由于接收到终止信号唤醒
#define PF_SIGNALED (1UL << 7) // 进程由于接收到信号而退出
#define PF_NEED_MIGRATE (1UL << 8) // 进程需要迁移到其他的核心
/**
@ -87,6 +87,9 @@ struct process_control_block
// pcb的名字
char name[PCB_NAME_LEN];
// 内存空间分布结构体, 记录内存页表和程序段信息
struct mm_struct *mm;
// 进程切换时保存的状态信息
struct thread_struct *thread;
@ -108,7 +111,7 @@ struct process_control_block
int64_t rt_time_slice; // 由实时调度器管理的时间片
// 进程拥有的文件描述符的指针数组(由Rust进行管理)
void *fds;
void * fds;
// 链表中的下一个pcb
struct process_control_block *prev_pcb, *next_pcb;
@ -133,15 +136,11 @@ struct process_control_block
// 如果当前进程等待被迁移到另一个cpu核心上也就是flags中的PF_NEED_MIGRATE被置位
// 该字段存储要被迁移到的目标处理器核心号
uint32_t migrate_to;
// Fpstate 用于用户态切换到内核态时保存浮点寄存器里面的值
void *fp_state;
// 指向进程的地址空间的arc指针.
void *address_space;
void* fp_state;//Fpstate 用于用户态切换到内核态时保存浮点寄存器里面的值
};
// 将进程的pcb和内核栈融合到一起,8字节对齐
union proc_union
{
union proc_union {
struct process_control_block pcb;
ul stack[STACK_SIZE / sizeof(ul)];
} __attribute__((aligned(8)));

View File

@ -38,6 +38,7 @@ extern void kernel_thread_func(void);
extern void rs_procfs_unregister_pid(uint64_t);
ul _stack_start; // initial proc的栈基地址虚拟地址
extern struct mm_struct initial_mm;
extern struct signal_struct INITIAL_SIGNALS;
extern struct sighand_struct INITIAL_SIGHAND;
@ -45,20 +46,17 @@ extern void process_exit_sighand(struct process_control_block *pcb);
extern void process_exit_signal(struct process_control_block *pcb);
extern void initial_proc_init_signal(struct process_control_block *pcb);
extern void rs_process_exit_fpstate(struct process_control_block *pcb);
extern void rs_drop_address_space(struct process_control_block *pcb);
extern int process_init_files();
extern int rs_init_stdio();
extern uint64_t rs_do_execve(const char *filename, const char *const argv[], const char *const envp[], struct pt_regs *regs);
extern uint64_t rs_exec_init_process(struct pt_regs *regs);
// 设置初始进程的PCB
#define INITIAL_PROC(proc) \
{ \
.state = PROC_UNINTERRUPTIBLE, .flags = PF_KTHREAD, .preempt_count = 0, .signal = 0, .cpu_id = 0, \
.thread = &initial_thread, .addr_limit = 0xffffffffffffffff, .pid = 0, .priority = 2, \
.virtual_runtime = 0, .fds = {0}, .next_pcb = &proc, .prev_pcb = &proc, .parent_pcb = &proc, .exit_code = 0, \
.wait_child_proc_exit = 0, .worker_private = NULL, .policy = SCHED_NORMAL, .sig_blocked = 0, \
.signal = &INITIAL_SIGNALS, .sighand = &INITIAL_SIGHAND, .address_space = NULL \
#define INITIAL_PROC(proc) \
{ \
.state = PROC_UNINTERRUPTIBLE, .flags = PF_KTHREAD, .preempt_count = 0, .signal = 0, .cpu_id = 0, \
.mm = &initial_mm, .thread = &initial_thread, .addr_limit = 0xffffffffffffffff, .pid = 0, .priority = 2, \
.virtual_runtime = 0, .fds = {0}, .next_pcb = &proc, .prev_pcb = &proc, .parent_pcb = &proc, .exit_code = 0, \
.wait_child_proc_exit = 0, .worker_private = NULL, .policy = SCHED_NORMAL, .sig_blocked = 0, \
.signal = &INITIAL_SIGNALS, .sighand = &INITIAL_SIGHAND, \
}
struct thread_struct initial_thread = {
@ -115,10 +113,8 @@ void __switch_to(struct process_control_block *prev, struct process_control_bloc
// initial_tss[0].ist2, initial_tss[0].ist3, initial_tss[0].ist4, initial_tss[0].ist5,
// initial_tss[0].ist6, initial_tss[0].ist7);
__asm__ __volatile__("movq %%fs, %0 \n\t"
: "=a"(prev->thread->fs));
__asm__ __volatile__("movq %%gs, %0 \n\t"
: "=a"(prev->thread->gs));
__asm__ __volatile__("movq %%fs, %0 \n\t" : "=a"(prev->thread->fs));
__asm__ __volatile__("movq %%gs, %0 \n\t" : "=a"(prev->thread->gs));
__asm__ __volatile__("movq %0, %%fs \n\t" ::"a"(next->thread->fs));
__asm__ __volatile__("movq %0, %%gs \n\t" ::"a"(next->thread->gs));
@ -149,6 +145,359 @@ int process_open_exec_file(char *path)
return fd;
}
/**
* @brief 加载elf格式的程序文件到内存中并设置regs
*
* @param regs 寄存器
* @param path 文件路径
* @return int
*/
static int process_load_elf_file(struct pt_regs *regs, char *path)
{
int retval = 0;
int fd = process_open_exec_file(path);
if ((long)fd < 0)
{
kdebug("(long)fd=%ld", (long)fd);
return (unsigned long)fd;
}
void *buf = kzalloc(PAGE_4K_SIZE, 0);
uint64_t pos = 0;
retval = enter_syscall_int(SYS_LSEEK, fd, 0, SEEK_SET, 0, 0, 0, 0, 0);
// 读取 Elf64_Ehdr
retval = enter_syscall_int(SYS_READ, fd, (uint64_t)buf, sizeof(Elf64_Ehdr), 0, 0, 0, 0, 0);
pos = enter_syscall_int(SYS_LSEEK, fd, 0, SEEK_CUR, 0, 0, 0, 0, 0);
if (retval != sizeof(Elf64_Ehdr))
{
kerror("retval=%d, not equal to sizeof(Elf64_Ehdr):%d", retval, sizeof(Elf64_Ehdr));
}
retval = 0;
if (!elf_check(buf))
{
kerror("Not an ELF file: %s", path);
retval = -ENOTSUP;
goto load_elf_failed;
}
#if ARCH(X86_64)
// 暂时只支持64位的文件
if (((Elf32_Ehdr *)buf)->e_ident[EI_CLASS] != ELFCLASS64)
{
kdebug("((Elf32_Ehdr *)buf)->e_ident[EI_CLASS]=%d", ((Elf32_Ehdr *)buf)->e_ident[EI_CLASS]);
retval = -EUNSUPPORTED;
goto load_elf_failed;
}
Elf64_Ehdr ehdr = *(Elf64_Ehdr *)buf;
// 暂时只支持AMD64架构
if (ehdr.e_machine != EM_AMD64)
{
kerror("e_machine=%d", ehdr.e_machine);
retval = -EUNSUPPORTED;
goto load_elf_failed;
}
#else
#error Unsupported architecture!
#endif
if (ehdr.e_type != ET_EXEC)
{
kerror("Not executable file! filename=%s\tehdr->e_type=%d", path, ehdr.e_type);
retval = -EUNSUPPORTED;
goto load_elf_failed;
}
// kdebug("filename=%s:\te_entry=%#018lx", path, ehdr.e_entry);
regs->rip = ehdr.e_entry;
current_pcb->mm->code_addr_start = ehdr.e_entry;
// kdebug("ehdr.e_phoff=%#018lx\t ehdr.e_phentsize=%d, ehdr.e_phnum=%d", ehdr.e_phoff, ehdr.e_phentsize,
// ehdr.e_phnum); 将指针移动到program header处
// 读取所有的phdr
pos = ehdr.e_phoff;
pos = enter_syscall_int(SYS_LSEEK, fd, pos, SEEK_SET, 0, 0, 0, 0, 0);
memset(buf, 0, PAGE_4K_SIZE);
enter_syscall_int(SYS_READ, fd, (uint64_t)buf, (uint64_t)ehdr.e_phentsize * (uint64_t)ehdr.e_phnum, 0, 0, 0, 0, 0);
pos = enter_syscall_int(SYS_LSEEK, fd, 0, SEEK_CUR, 0, 0, 0, 0, 0);
if ((long)retval < 0)
{
kdebug("(unsigned long)filp=%d", (long)retval);
retval = -ENOEXEC;
goto load_elf_failed;
}
Elf64_Phdr *phdr = buf;
// 将程序加载到内存中
for (int i = 0; i < ehdr.e_phnum; ++i, ++phdr)
{
// kdebug("phdr[%d] phdr->p_offset=%#018lx phdr->p_vaddr=%#018lx phdr->p_memsz=%ld phdr->p_filesz=%ld
// phdr->p_type=%d", i, phdr->p_offset, phdr->p_vaddr, phdr->p_memsz, phdr->p_filesz, phdr->p_type);
// 不是可加载的段
if (phdr->p_type != PT_LOAD)
continue;
int64_t remain_mem_size = phdr->p_memsz;
int64_t remain_file_size = phdr->p_filesz;
pos = phdr->p_offset;
uint64_t virt_base = 0;
uint64_t beginning_offset = 0; // 由于页表映射导致的virtbase与实际的p_vaddr之间的偏移量
if (remain_mem_size >= PAGE_2M_SIZE) // 接下来存在映射2M页的情况因此将vaddr按2M向下对齐
virt_base = phdr->p_vaddr & PAGE_2M_MASK;
else // 接下来只有4K页的映射
virt_base = phdr->p_vaddr & PAGE_4K_MASK;
beginning_offset = phdr->p_vaddr - virt_base;
remain_mem_size += beginning_offset;
while (remain_mem_size > 0)
{
// kdebug("loading...");
int64_t map_size = 0;
if (remain_mem_size >= PAGE_2M_SIZE)
{
uint64_t pa = alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys;
struct vm_area_struct *vma = NULL;
int ret =
mm_create_vma(current_pcb->mm, virt_base, PAGE_2M_SIZE, VM_USER | VM_ACCESS_FLAGS, NULL, &vma);
// 防止内存泄露
if (ret == -EEXIST)
free_pages(Phy_to_2M_Page(pa), 1);
else
mm_map(current_pcb->mm, virt_base, PAGE_2M_SIZE, pa);
// mm_map_vma(vma, pa, 0, PAGE_2M_SIZE);
io_mfence();
memset((void *)virt_base, 0, PAGE_2M_SIZE);
map_size = PAGE_2M_SIZE;
}
else
{
// todo: 使用4K、8K、32K大小内存块混合进行分配提高空间利用率减少了bmp的大小
map_size = ALIGN(remain_mem_size, PAGE_4K_SIZE);
// 循环分配4K大小内存块
for (uint64_t off = 0; off < map_size; off += PAGE_4K_SIZE)
{
uint64_t paddr = virt_2_phys((uint64_t)kmalloc(PAGE_4K_SIZE, 0));
struct vm_area_struct *vma = NULL;
int val = mm_create_vma(current_pcb->mm, virt_base + off, PAGE_4K_SIZE, VM_USER | VM_ACCESS_FLAGS,
NULL, &vma);
// kdebug("virt_base=%#018lx", virt_base + off);
if (val == -EEXIST)
kfree(phys_2_virt(paddr));
else
mm_map(current_pcb->mm, virt_base + off, PAGE_4K_SIZE, paddr);
// mm_map_vma(vma, paddr, 0, PAGE_4K_SIZE);
io_mfence();
memset((void *)(virt_base + off), 0, PAGE_4K_SIZE);
}
}
pos = enter_syscall_int(SYS_LSEEK, fd, pos, SEEK_SET, 0, 0, 0, 0, 0);
int64_t val = 0;
if (remain_file_size > 0)
{
int64_t to_trans = (remain_file_size > PAGE_2M_SIZE) ? PAGE_2M_SIZE : remain_file_size;
void *buf3 = kzalloc(PAGE_4K_SIZE, 0);
while (to_trans > 0)
{
int64_t x = 0;
x = enter_syscall_int(SYS_READ, fd, (uint64_t)buf3, to_trans, 0, 0, 0, 0, 0);
memcpy(virt_base + beginning_offset + val, buf3, x);
val += x;
to_trans -= x;
pos = enter_syscall_int(SYS_LSEEK, fd, 0, SEEK_CUR, 0, 0, 0, 0, 0);
}
kfree(buf3);
// kdebug("virt_base + beginning_offset=%#018lx, val=%d, to_trans=%d", virt_base + beginning_offset,
// val,
// to_trans);
// kdebug("to_trans=%d", to_trans);
}
if (val < 0)
goto load_elf_failed;
remain_mem_size -= map_size;
remain_file_size -= val;
virt_base += map_size;
}
}
// 分配2MB的栈内存空间
regs->rsp = current_pcb->mm->stack_start;
regs->rbp = current_pcb->mm->stack_start;
{
struct vm_area_struct *vma = NULL;
uint64_t pa = alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys;
int val = mm_create_vma(current_pcb->mm, current_pcb->mm->stack_start - PAGE_2M_SIZE, PAGE_2M_SIZE,
VM_USER | VM_ACCESS_FLAGS, NULL, &vma);
if (val == -EEXIST)
free_pages(Phy_to_2M_Page(pa), 1);
else
mm_map_vma(vma, pa, 0, PAGE_2M_SIZE);
}
// 清空栈空间
memset((void *)(current_pcb->mm->stack_start - PAGE_2M_SIZE), 0, PAGE_2M_SIZE);
load_elf_failed:;
{
enter_syscall_int(SYS_CLOSE, fd, 0, 0, 0, 0, 0, 0, 0);
}
if (buf != NULL)
kfree(buf);
return retval;
}
/**
* @brief 使当前进程去执行新的代码
*
* @param regs 当前进程的寄存器
* @param path 可执行程序的路径
* @param argv 参数列表
* @param envp 环境变量
* @return ul 错误码
*/
#pragma GCC push_options
#pragma GCC optimize("O0")
ul do_execve(struct pt_regs *regs, char *path, char *argv[], char *envp[])
{
// 当前进程正在与父进程共享地址空间,需要创建
// 独立的地址空间才能使新程序正常运行
if (current_pcb->flags & PF_VFORK)
{
// kdebug("proc:%d creating new mem space", current_pcb->pid);
// 分配新的内存空间分布结构体
struct mm_struct *new_mms = (struct mm_struct *)kmalloc(sizeof(struct mm_struct), 0);
memset(new_mms, 0, sizeof(struct mm_struct));
current_pcb->mm = new_mms;
// 分配顶层页表, 并设置顶层页表的物理地址
new_mms->pgd = (pml4t_t *)virt_2_phys(kmalloc(PAGE_4K_SIZE, 0));
// 由于高2K部分为内核空间在接下来需要覆盖其数据因此不用清零
memset(phys_2_virt(new_mms->pgd), 0, PAGE_4K_SIZE / 2);
// 拷贝内核空间的页表指针
memcpy(phys_2_virt(new_mms->pgd) + 256, phys_2_virt(initial_proc[proc_current_cpu_id]) + 256, PAGE_4K_SIZE / 2);
}
// 设置用户栈和用户堆的基地址
unsigned long stack_start_addr = 0x6ffff0a00000UL;
const uint64_t brk_start_addr = 0x700000000000UL;
process_switch_mm(current_pcb);
// 为用户态程序设置地址边界
if (!(current_pcb->flags & PF_KTHREAD))
current_pcb->addr_limit = USER_MAX_LINEAR_ADDR;
current_pcb->mm->code_addr_end = 0;
current_pcb->mm->data_addr_start = 0;
current_pcb->mm->data_addr_end = 0;
current_pcb->mm->rodata_addr_start = 0;
current_pcb->mm->rodata_addr_end = 0;
current_pcb->mm->bss_start = 0;
current_pcb->mm->bss_end = 0;
current_pcb->mm->brk_start = brk_start_addr;
current_pcb->mm->brk_end = brk_start_addr;
current_pcb->mm->stack_start = stack_start_addr;
// 清除进程的vfork标志位
current_pcb->flags &= ~PF_VFORK;
// 加载elf格式的可执行文件
int tmp = process_load_elf_file(regs, path);
if (tmp < 0)
goto exec_failed;
int argc = 0;
char **dst_argv = NULL;
// kdebug("stack_start_addr=%#018lx", stack_start_addr);
// 拷贝参数列表
if (argv != NULL)
{
// 目标程序的argv基地址指针最大8个参数
dst_argv = (char **)(stack_start_addr - (sizeof(char **) << 3));
uint64_t str_addr = (uint64_t)dst_argv;
for (argc = 0; argc < 8 && argv[argc] != NULL; ++argc)
{
if (*argv[argc] == NULL)
break;
// 测量参数的长度最大1023
int argv_len = strnlen_user(argv[argc], 1023) + 1;
strncpy((char *)(str_addr - argv_len), argv[argc], argv_len - 1);
str_addr -= argv_len;
dst_argv[argc] = (char *)str_addr;
// 字符串加上结尾字符
((char *)str_addr)[argv_len] = '\0';
}
// 重新设定栈基址,并预留空间防止越界
stack_start_addr = str_addr - 8;
}
// kdebug("stack_start_addr=%#018lx", stack_start_addr);
// ==== 生成relibc所需的Stack结构体
{
uint64_t *ptr_stack = (uint64_t *)(stack_start_addr - 8);
if (argc == 0)
*ptr_stack = 0;
else
*ptr_stack = (uint64_t)dst_argv;
ptr_stack--;
*ptr_stack = argc;
stack_start_addr -= 16;
}
// 传递参数(旧版libc)
regs->rdi = argc;
regs->rsi = (uint64_t)dst_argv;
// 设置用户栈基地址
current_pcb->mm->stack_start = stack_start_addr;
regs->rsp = regs->rbp = stack_start_addr;
// kdebug("execve ok");
// 设置进程的段选择子为用户态可访问
regs->cs = USER_CS | 3;
regs->ds = USER_DS | 3;
regs->ss = USER_DS | 0x3;
regs->rflags = 0x200246;
regs->rax = 1;
regs->es = 0;
return 0;
exec_failed:;
process_do_exit(tmp);
}
#pragma GCC pop_options
/**
* @brief 初始化实时进程rt_pcb
*
@ -178,24 +527,43 @@ ul initial_kernel_thread(ul arg)
kinfo("initial proc running...\targ:%#018lx, vruntime=%d", arg, current_pcb->virtual_runtime);
int val = 0;
val = scm_enable_double_buffer();
io_mfence();
rs_init_stdio();
io_mfence();
// block_io_scheduler_init();
ahci_init();
mount_root_fs();
io_mfence();
rs_virtio_probe();
io_mfence();
// 使用单独的内核线程来初始化usb驱动程序
// 注释由于目前usb驱动程序不完善因此先将其注释掉
// int usb_pid = kernel_thread(usb_init, 0, 0);
kinfo("LZ4 lib Version=%s", LZ4_versionString());
io_mfence();
__rust_demo_func();
io_mfence();
// while (1)
// {
// /* code */
// }
// 对completion完成量进行测试
// __test_completion();
// // 对一些组件进行单元测试
uint64_t tpid[] = {
// ktest_start(ktest_test_bitree, 0), ktest_start(ktest_test_kfifo, 0), ktest_start(ktest_test_mutex, 0),
// ktest_start(ktest_test_idr, 0),
// usb_pid,
};
// kinfo("Waiting test thread exit...");
// // 等待测试进程退出
// for (int i = 0; i < sizeof(tpid) / sizeof(uint64_t); ++i)
// waitpid(tpid[i], NULL, NULL);
// kinfo("All test done.");
// 测试实时进程
// struct process_control_block *test_rt1 = kthread_run_rt(&test, NULL, "test rt");
// kdebug("process:rt test kthread is created!!!!");
// 准备切换到用户态
struct pt_regs *regs;
@ -220,8 +588,8 @@ ul initial_kernel_thread(ul arg)
// 这里的设计思路和switch_to类似 加载用户态程序shell.elf
__asm__ __volatile__("movq %1, %%rsp \n\t"
"pushq %2 \n\t"
"jmp rs_exec_init_process \n\t" ::"D"(current_pcb->thread->rsp),
"m"(current_pcb->thread->rsp), "m"(current_pcb->thread->rip), "c"(NULL),
"jmp do_execve \n\t" ::"D"(current_pcb->thread->rsp),
"m"(current_pcb->thread->rsp), "m"(current_pcb->thread->rip), "S"("/bin/shell.elf"), "c"(NULL),
"d"(NULL)
: "memory");
@ -310,15 +678,9 @@ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
* @brief 初始化进程模块
* ☆前置条件:已完成系统调用模块的初始化
*/
#pragma GCC push_options
#pragma GCC optimize("O0")
void process_init()
{
kinfo("Initializing process...");
// rs_test_buddy();
io_mfence();
rs_process_init();
io_mfence();
initial_tss[proc_current_cpu_id].rsp0 = initial_thread.rbp;
@ -330,23 +692,18 @@ void process_init()
list_init(&initial_proc_union.pcb.list);
wait_queue_init(&initial_proc_union.pcb.wait_child_proc_exit, NULL);
io_mfence();
// 初始化init进程的signal相关的信息
initial_proc_init_signal(current_pcb);
kdebug("Initial process to init files");
io_mfence();
process_init_files();
kdebug("Initial process init files ok");
io_mfence();
// 临时设置IDLE进程的的虚拟运行时间为0防止下面的这些内核线程的虚拟运行时间出错
current_pcb->virtual_runtime = 0;
barrier();
kernel_thread(initial_kernel_thread, 10, CLONE_FS | CLONE_SIGNAL); // 初始化内核线程
barrier();
kthread_mechanism_init(); // 初始化kthread机制
barrier();
initial_proc_union.pcb.state = PROC_RUNNING;
initial_proc_union.pcb.preempt_count = 0;
@ -355,7 +712,6 @@ void process_init()
// 将IDLE进程的虚拟运行时间设置为一个很大的数值
current_pcb->virtual_runtime = (1UL << 60);
}
#pragma GCC pop_options
/**
* @brief 根据pid获取进程的pcb。存在对应的pcb时返回对应的pcb的指针否则返回NULL
@ -430,7 +786,57 @@ int process_wakeup_immediately(struct process_control_block *pcb)
*/
uint64_t process_exit_mm(struct process_control_block *pcb)
{
rs_drop_address_space(pcb);
if (pcb->flags & CLONE_VM)
return 0;
if (pcb->mm == NULL)
{
kdebug("pcb->mm==NULL");
return 0;
}
if (pcb->mm->pgd == NULL)
{
kdebug("pcb->mm->pgd==NULL");
return 0;
}
// // 获取顶层页表
pml4t_t *current_pgd = (pml4t_t *)phys_2_virt(pcb->mm->pgd);
// 循环释放VMA中的内存
struct vm_area_struct *vma = pcb->mm->vmas;
while (vma != NULL)
{
struct vm_area_struct *cur_vma = vma;
vma = cur_vma->vm_next;
uint64_t pa;
mm_unmap_vma(pcb->mm, cur_vma, &pa);
uint64_t size = (cur_vma->vm_end - cur_vma->vm_start);
// 释放内存
switch (size)
{
case PAGE_4K_SIZE:
kfree(phys_2_virt(pa));
break;
default:
break;
}
vm_area_del(cur_vma);
vm_area_free(cur_vma);
}
// 释放顶层页表
kfree(current_pgd);
if (unlikely(pcb->mm->vmas != NULL))
{
kwarn("pcb.mm.vmas!=NULL");
}
// 释放内存空间分布结构体
kfree(pcb->mm);
return 0;
}
@ -451,6 +857,9 @@ void process_exit_thread(struct process_control_block *pcb)
*/
int process_release_pcb(struct process_control_block *pcb)
{
// 释放子进程的页表
// BUG 暂时注释process_exit_mm
// process_exit_mm(pcb);
if ((pcb->flags & PF_KTHREAD)) // 释放内核线程的worker private结构体
free_kthread_struct(pcb);
@ -462,8 +871,6 @@ int process_release_pcb(struct process_control_block *pcb)
process_exit_signal(pcb);
rs_process_exit_fpstate(pcb);
rs_procfs_unregister_pid(pcb->pid);
// 释放进程的地址空间
process_exit_mm(pcb);
// 释放当前pcb
kfree(pcb);
return 0;

View File

@ -31,18 +31,18 @@ extern int process_exit_files(struct process_control_block *pcb);
*/
// 设置初始进程的tss
#define INITIAL_TSS \
{ \
.reserved0 = 0, .rsp0 = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)), \
.rsp1 = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)), \
.rsp2 = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)), .reserved1 = 0, .ist1 = 0xffff800000007c00, \
.ist2 = 0xffff800000007c00, .ist3 = 0xffff800000007c00, .ist4 = 0xffff800000007c00, \
.ist5 = 0xffff800000007c00, .ist6 = 0xffff800000007c00, .ist7 = 0xffff800000007c00, .reserved2 = 0, \
.reserved3 = 0, .io_map_base_addr = 0 \
#define INITIAL_TSS \
{ \
.reserved0 = 0, .rsp0 = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)), \
.rsp1 = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)), \
.rsp2 = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)), .reserved1 = 0, .ist1 = 0xffff800000007c00, \
.ist2 = 0xffff800000007c00, .ist3 = 0xffff800000007c00, .ist4 = 0xffff800000007c00, \
.ist5 = 0xffff800000007c00, .ist6 = 0xffff800000007c00, .ist7 = 0xffff800000007c00, .reserved2 = 0, \
.reserved3 = 0, .io_map_base_addr = 0 \
}
#define GET_CURRENT_PCB \
"movq %rsp, %rbx \n\t" \
#define GET_CURRENT_PCB \
"movq %rsp, %rbx \n\t" \
"andq $-32768, %rbx\n\t"
/**
@ -51,23 +51,23 @@ extern int process_exit_files(struct process_control_block *pcb);
* 然后调用__switch_to切换栈配置其他信息最后恢复下一个进程的rax rbp。
*/
#define switch_to(prev, next) \
do \
{ \
__asm__ __volatile__("pushq %%rbp \n\t" \
"pushq %%rax \n\t" \
"movq %%rsp, %0 \n\t" \
"movq %2, %%rsp \n\t" \
"leaq 2f(%%rip), %%rax \n\t" \
"movq %%rax, %1 \n\t" \
"pushq %3 \n\t" \
"jmp __switch_to \n\t" \
"2: \n\t" \
"popq %%rax \n\t" \
"popq %%rbp \n\t" \
: "=m"(prev->thread->rsp), "=m"(prev->thread->rip) \
: "m"(next->thread->rsp), "m"(next->thread->rip), "D"(prev), "S"(next) \
: "memory", "rax"); \
#define switch_to(prev, next) \
do \
{ \
__asm__ __volatile__("pushq %%rbp \n\t" \
"pushq %%rax \n\t" \
"movq %%rsp, %0 \n\t" \
"movq %2, %%rsp \n\t" \
"leaq 2f(%%rip), %%rax \n\t" \
"movq %%rax, %1 \n\t" \
"pushq %3 \n\t" \
"jmp __switch_to \n\t" \
"2: \n\t" \
"popq %%rax \n\t" \
"popq %%rbp \n\t" \
: "=m"(prev->thread->rsp), "=m"(prev->thread->rip) \
: "m"(next->thread->rsp), "m"(next->thread->rip), "D"(prev), "S"(next) \
: "memory", "rax"); \
} while (0)
/**
@ -112,6 +112,17 @@ int process_wakeup(struct process_control_block *pcb);
*/
int process_wakeup_immediately(struct process_control_block *pcb);
/**
* @brief 使当前进程去执行新的代码
*
* @param regs 当前进程的寄存器
* @param path 可执行程序的路径
* @param argv 参数列表
* @param envp 环境变量
* @return ul 错误码
*/
ul do_execve(struct pt_regs *regs, char *path, char *argv[], char *envp[]);
/**
* @brief 释放进程的页表
*
@ -155,11 +166,10 @@ int process_release_pcb(struct process_control_block *pcb);
* @param next 下一个进程的pcb
*
*/
#define process_switch_mm(next_pcb) \
do \
{ \
asm volatile("movq %0, %%cr3 \n\t" ::"r"(next_pcb->mm->pgd) \
: "memory"); \
#define process_switch_mm(next_pcb) \
do \
{ \
asm volatile("movq %0, %%cr3 \n\t" ::"r"(next_pcb->mm->pgd) : "memory"); \
} while (0)
// flush_tlb();

View File

@ -1,13 +1,12 @@
use core::{
ffi::c_void,
mem::ManuallyDrop,
ptr::{null_mut, read_volatile, write_volatile},
};
use alloc::{boxed::Box, sync::Arc};
use crate::{
arch::asm::current::current_pcb,
arch::{asm::current::current_pcb, fpu::FpState},
filesystem::vfs::{
file::{File, FileDescriptorVec, FileMode},
FileType, ROOT_INODE,
@ -17,7 +16,6 @@ use crate::{
PROC_UNINTERRUPTIBLE,
},
libs::casting::DowncastArc,
mm::ucontext::AddressSpace,
net::socket::SocketInode,
sched::core::{cpu_executing, sched_enqueue},
smp::core::{smp_get_processor_id, smp_send_reschedule},
@ -313,41 +311,94 @@ impl process_control_block {
.expect("Not a socket inode");
return Some(socket);
}
}
/// 释放pcb中存储的地址空间的指针
pub unsafe fn drop_address_space(&mut self) {
let p = self.address_space as *const AddressSpace;
if p.is_null() {
return;
}
let p: Arc<AddressSpace> = Arc::from_raw(p);
drop(p);
self.address_space = null_mut();
}
// =========== 导出到C的函数在将来进程管理模块被完全重构之后需要删掉他们 BEGIN ============
/// 设置pcb中存储的地址空间的指针
///
/// ## panic
/// 如果当前pcb已经有地址空间那么panic
pub unsafe fn set_address_space(&mut self, address_space: Arc<AddressSpace>) {
assert!(self.address_space.is_null(), "Address space already set");
self.address_space = Arc::into_raw(address_space) as *mut c_void;
}
/// 获取当前进程的地址空间的指针
pub fn address_space(&self) -> Option<Arc<AddressSpace>> {
let ptr = self.address_space as *const AddressSpace;
if ptr.is_null() {
return None;
}
// 为了防止pcb中的指针被释放这里需要将其包装一下使得Arc的drop不会被调用
let arc_wrapper = ManuallyDrop::new(unsafe { Arc::from_raw(ptr) });
let result = Arc::clone(&arc_wrapper);
return Some(result);
/// @brief 初始化当前进程的文件描述符数组
/// 请注意,如果当前进程已经有文件描述符数组,那么本操作将被禁止
#[no_mangle]
pub extern "C" fn process_init_files() -> i32 {
let r = current_pcb().init_files();
if r.is_ok() {
return 0;
} else {
return r.unwrap_err().to_posix_errno();
}
}
/// @brief 拷贝当前进程的文件描述符信息
///
/// @param clone_flags 克隆标志位
/// @param pcb 新的进程的pcb
#[no_mangle]
pub extern "C" fn process_copy_files(
clone_flags: u64,
from: &'static process_control_block,
) -> i32 {
let r = current_pcb().copy_files(clone_flags, from);
if r.is_ok() {
return 0;
} else {
return r.unwrap_err().to_posix_errno();
}
}
/// @brief 回收进程的文件描述符数组
///
/// @param pcb 要被回收的进程的pcb
///
/// @return i32
#[no_mangle]
pub extern "C" fn process_exit_files(pcb: &'static mut process_control_block) -> i32 {
let r: Result<(), SystemError> = pcb.exit_files();
if r.is_ok() {
return 0;
} else {
return r.unwrap_err().to_posix_errno();
}
}
/// @brief 复制当前进程的浮点状态
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn rs_dup_fpstate() -> *mut c_void {
// 如果当前进程没有浮点状态,那么就返回一个默认的浮点状态
if current_pcb().fp_state == null_mut() {
return Box::leak(Box::new(FpState::default())) as *mut FpState as usize as *mut c_void;
} else {
// 如果当前进程有浮点状态,那么就复制一个新的浮点状态
let state = current_pcb().fp_state as usize as *mut FpState;
unsafe {
let s = state.as_ref().unwrap();
let state: &mut FpState = Box::leak(Box::new(s.clone()));
return state as *mut FpState as usize as *mut c_void;
}
}
}
/// @brief 释放进程的浮点状态所占用的内存
#[no_mangle]
pub extern "C" fn rs_process_exit_fpstate(pcb: &'static mut process_control_block) {
if pcb.fp_state != null_mut() {
let state = pcb.fp_state as usize as *mut FpState;
unsafe {
drop(Box::from_raw(state));
}
}
}
#[no_mangle]
pub extern "C" fn rs_init_stdio() -> i32 {
let r = init_stdio();
if r.is_ok() {
return 0;
} else {
return r.unwrap_err().to_posix_errno();
}
}
// =========== 以上为导出到C的函数在将来进程管理模块被完全重构之后需要删掉他们 END ============
/// @brief 初始化pid=1的进程的stdio
pub fn init_stdio() -> Result<(), SystemError> {