proc: pass env along with args to spawn()
This commit is contained in:
parent
639f13eda4
commit
b21dbca0f9
@ -60,7 +60,7 @@ pub fn kinit() {
|
||||
let stderr = stdout.clone();
|
||||
|
||||
{
|
||||
let user_init = proc::exec::load_elf("init", file, &["/init", "xxx"]).unwrap();
|
||||
let user_init = proc::exec::load_elf("init", file, &["/init", "xxx"], &[]).unwrap();
|
||||
let mut io = user_init.io.lock();
|
||||
io.set_ioctx(ioctx);
|
||||
io.set_file(RawFd::STDIN, stdin).unwrap();
|
||||
|
131
src/proc/exec.rs
131
src/proc/exec.rs
@ -7,26 +7,78 @@ use vfs::FileRef;
|
||||
|
||||
use crate::{
|
||||
mem::{
|
||||
address::AsPhysicalAddress, phys, process::ProcessAddressSpace, table::MapAttributes,
|
||||
ForeignPointer,
|
||||
address::AsPhysicalAddress, phys, pointer::PhysicalRefMut, process::ProcessAddressSpace,
|
||||
table::MapAttributes, ForeignPointer,
|
||||
},
|
||||
proc,
|
||||
task::{context::TaskContextImpl, process::Process, TaskContext},
|
||||
};
|
||||
|
||||
fn setup_args(space: &ProcessAddressSpace, virt: usize, args: &[&str]) -> Result<(), Error> {
|
||||
// arg data len
|
||||
let args_size: usize = args.iter().map(|x| x.len()).sum();
|
||||
// 1 + arg ptr:len count
|
||||
let args_ptr_size = (1 + args.len() * 2) * size_of::<usize>();
|
||||
pub struct EnvWriter<'a> {
|
||||
data: &'a mut [u8],
|
||||
offset: usize,
|
||||
}
|
||||
|
||||
let total_size = args_size + args_ptr_size;
|
||||
impl<'a> EnvWriter<'a> {
|
||||
pub fn new(data: &'a mut [u8]) -> Self {
|
||||
Self { data, offset: 0 }
|
||||
}
|
||||
|
||||
pub fn write_usize(&mut self, value: usize) -> Result<(), Error> {
|
||||
self.write_bytes(&value.to_ne_bytes())
|
||||
}
|
||||
|
||||
pub fn write_bytes(&mut self, value: &[u8]) -> Result<(), Error> {
|
||||
if value.len() + self.offset > self.data.len() {
|
||||
return Err(Error::InvalidArgument);
|
||||
}
|
||||
debugln!("write_bytes {:#x} {:x?}", self.offset, value);
|
||||
self.data[self.offset..self.offset + value.len()].copy_from_slice(value);
|
||||
self.offset += value.len();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn write_2d_str_array(
|
||||
space: &ProcessAddressSpace,
|
||||
virt: usize,
|
||||
array: &[&str],
|
||||
) -> Result<(), Error> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
// TODO I hate this function, it's ugly
|
||||
fn setup_program_env(
|
||||
space: &ProcessAddressSpace,
|
||||
virt: usize,
|
||||
args: &[&str],
|
||||
envs: &[&str],
|
||||
) -> Result<(), Error> {
|
||||
const fn str_array_size(n: usize) -> usize {
|
||||
// length of the array itself (1 usize) + ptr:len pairs (2x usize * n)
|
||||
(1 + n * 2) * size_of::<usize>()
|
||||
}
|
||||
|
||||
const HEADER_SIZE: usize = 2 * size_of::<usize>();
|
||||
|
||||
// arg data len
|
||||
let args_data_size: usize = args.iter().map(|x| x.len()).sum();
|
||||
let envs_data_size: usize = envs.iter().map(|x| x.len()).sum();
|
||||
let ptrs_size = str_array_size(args.len()) + str_array_size(envs.len());
|
||||
let total_size = args_data_size + envs_data_size + ptrs_size + HEADER_SIZE;
|
||||
// 1 + arg ptr:len count
|
||||
// let args_ptr_size = (1 + args.len() * 2) * size_of::<usize>();
|
||||
// let envs_ptr_size = (1 + envs.len() * 2) * size_of::<usize>();
|
||||
|
||||
// Total size: offset arrays + data + args/env split position
|
||||
// let total_size = args_size + args_ptr_size + envs_size + envs_ptr_size + size_of::<usize>();
|
||||
|
||||
if total_size > 0x1000 {
|
||||
todo!();
|
||||
}
|
||||
|
||||
debugln!("arg data size = {}", args_size);
|
||||
// debugln!("arg data size = {}", args_size);
|
||||
// debugln!("env data size = {}", envs_size);
|
||||
|
||||
let phys_page = phys::alloc_page()?;
|
||||
space.map_single(
|
||||
@ -34,35 +86,44 @@ fn setup_args(space: &ProcessAddressSpace, virt: usize, args: &[&str]) -> Result
|
||||
phys_page,
|
||||
MapAttributes::USER_READ | MapAttributes::USER_WRITE | MapAttributes::NON_GLOBAL,
|
||||
)?;
|
||||
let write = phys_page.virtualize_raw();
|
||||
let mut slice = unsafe { PhysicalRefMut::map_slice(phys_page, 4096) };
|
||||
let mut writer = EnvWriter::new(&mut *slice);
|
||||
|
||||
let mut offset = args_ptr_size;
|
||||
let args_array_offset = HEADER_SIZE;
|
||||
let envs_array_offset = args_array_offset + str_array_size(args.len());
|
||||
let args_data_offset = envs_array_offset + str_array_size(envs.len());
|
||||
let envs_data_offset = args_data_offset + args_data_size;
|
||||
|
||||
unsafe {
|
||||
(write as *mut usize).write_volatile(args.len());
|
||||
}
|
||||
// Header
|
||||
writer.write_usize(virt + args_array_offset);
|
||||
writer.write_usize(virt + envs_array_offset);
|
||||
|
||||
for (i, arg) in args.iter().enumerate() {
|
||||
// Place the argument pointer
|
||||
let ptr_place = write + (i * 2 + 1) * size_of::<usize>();
|
||||
let len_place = ptr_place + size_of::<usize>();
|
||||
unsafe {
|
||||
(ptr_place as *mut usize).write_volatile(virt + offset);
|
||||
(len_place as *mut usize).write_volatile(arg.len());
|
||||
}
|
||||
// Args array
|
||||
writer.write_usize(args.len());
|
||||
|
||||
let mut offset = args_data_offset;
|
||||
for arg in args.iter() {
|
||||
writer.write_usize(arg.len());
|
||||
writer.write_usize(virt + offset);
|
||||
offset += arg.len();
|
||||
}
|
||||
|
||||
// Place the argument data
|
||||
// TODO rewrite using write_foreign
|
||||
unsafe {
|
||||
let arg_data_slice =
|
||||
core::slice::from_raw_parts_mut((write + args_ptr_size) as *mut u8, args_size);
|
||||
let mut offset = 0;
|
||||
for &s in args {
|
||||
arg_data_slice[offset..offset + s.len()].copy_from_slice(s.as_bytes());
|
||||
offset += s.len();
|
||||
}
|
||||
// Envs array
|
||||
writer.write_usize(envs.len());
|
||||
|
||||
let mut offset = envs_data_offset;
|
||||
for env in envs.iter() {
|
||||
writer.write_usize(env.len());
|
||||
writer.write_usize(virt + offset);
|
||||
offset += env.len();
|
||||
}
|
||||
|
||||
// String data
|
||||
for arg in args.iter() {
|
||||
writer.write_bytes(arg.as_bytes());
|
||||
}
|
||||
for env in envs.iter() {
|
||||
writer.write_bytes(env.as_bytes());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -73,6 +134,7 @@ fn setup_binary<S: Into<String>>(
|
||||
space: ProcessAddressSpace,
|
||||
entry: usize,
|
||||
args: &[&str],
|
||||
envs: &[&str],
|
||||
) -> Result<Arc<Process>, Error> {
|
||||
const USER_STACK_PAGES: usize = 16;
|
||||
|
||||
@ -87,7 +149,7 @@ fn setup_binary<S: Into<String>>(
|
||||
MapAttributes::USER_WRITE | MapAttributes::USER_READ | MapAttributes::NON_GLOBAL,
|
||||
)?;
|
||||
|
||||
setup_args(&space, virt_args_base, args)?;
|
||||
setup_program_env(&space, virt_args_base, args, envs)?;
|
||||
|
||||
debugln!(
|
||||
"Entry: {:#x}, Stack: {:#x}..{:#x}, Args: {:#x}",
|
||||
@ -124,9 +186,10 @@ pub fn load_elf<S: Into<String>>(
|
||||
name: S,
|
||||
file: FileRef,
|
||||
args: &[&str],
|
||||
envs: &[&str],
|
||||
) -> Result<Arc<Process>, Error> {
|
||||
let space = ProcessAddressSpace::new()?;
|
||||
let elf_entry = proc::elf::load_elf_from_file(&space, file)?;
|
||||
|
||||
setup_binary(name, space, elf_entry, args)
|
||||
setup_binary(name, space, elf_entry, args, envs)
|
||||
}
|
||||
|
@ -287,7 +287,12 @@ fn syscall_handler(func: SyscallFunction, args: &[u64]) -> Result<usize, Error>
|
||||
|
||||
// Setup a new process from the file
|
||||
let file = node.open(OpenOptions::READ, FileMode::empty())?;
|
||||
let child = proc::exec::load_elf(options.program, file, options.arguments)?;
|
||||
let child = proc::exec::load_elf(
|
||||
options.program,
|
||||
file,
|
||||
options.arguments,
|
||||
options.environment,
|
||||
)?;
|
||||
let pid = child.id() as u32;
|
||||
|
||||
// Inherit group and session from the creator
|
||||
|
Loading…
x
Reference in New Issue
Block a user