mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-25 01:43:30 +00:00
@ -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"),
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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(());
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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(());
|
||||
}
|
||||
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
@ -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)));
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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> {
|
||||
|
Reference in New Issue
Block a user