🆕 在shell中启动另一个程序

This commit is contained in:
fslongjin
2022-06-07 23:18:26 +08:00
parent 129d24296b
commit 4e04ab9eee
14 changed files with 109 additions and 77 deletions

View File

@ -100,7 +100,8 @@
"elf.h": "c",
"stdio.h": "c",
"wait_queue.h": "c",
"stddef.h": "c"
"stddef.h": "c",
"spinlock.h": "c"
},
"C_Cpp.errorSquiggles": "Enabled",
"esbonio.sphinx.confDir": ""

View File

@ -170,6 +170,8 @@ static inline struct List *list_next(struct List *entry)
//计算字符串的长度经过测试该版本比采用repne/scasb汇编的运行速度快16.8%左右)
static inline int strlen(char *s)
{
if(s == NULL)
return 0;
register int __res = 0;
while (s[__res] != '\0')
{

View File

@ -3,6 +3,7 @@
#include <exception/softirq.h>
#include <mm/slab.h>
#include <driver/timers/HPET/HPET.h>
#include <process/process.h>
void test_timer()
{
@ -24,11 +25,14 @@ void timer_init()
void do_timer_softirq(void *data)
{
// if(current_pcb->pid==3)
// kdebug("pid3 timer irq");
struct timer_func_list_t *tmp = container_of(list_next(&timer_func_head.list), struct timer_func_list_t, list);
while ((!list_empty(&timer_func_head.list)) && (tmp->expire_jiffies <= timer_jiffies))
{
if(current_pcb->pid==3)
kdebug("pid3 timer do");
timer_func_del(tmp);
tmp->func(tmp->data);
kfree(tmp);

View File

@ -6,6 +6,9 @@
#include <common/kprint.h>
#include <mm/mm.h>
#include <mm/slab.h>
#include <process/spinlock.h>
// 每个时刻只能有1个进程新增定时任务
spinlock_t video_timer_func_add_lock;
#define REFRESH_INTERVAL 15 // 启动刷新帧缓冲区任务的时间间隔
@ -67,11 +70,15 @@ void init_frame_buffer(bool level)
*/
static void video_refresh_framebuffer()
{
if(current_pcb->pid==3)
kdebug("pid3 flush fb");
memcpy((void *)sc_info.fb_vaddr, (void *)sc_info.double_fb_vaddr, (sc_info.length << 2));
// 新增下一个刷新定时任务
struct timer_func_list_t *tmp = (struct timer_func_list_t *)kmalloc(sizeof(struct timer_func_list_t), 0);
spin_lock(&video_timer_func_add_lock);
timer_func_init(tmp, &video_refresh_framebuffer, NULL, REFRESH_INTERVAL);
timer_func_add(tmp);
spin_unlock(&video_timer_func_add_lock);
}
/**
@ -86,6 +93,7 @@ int video_init(bool level)
init_frame_buffer(level);
if (level)
{
spin_init(&video_timer_func_add_lock);
// 启用双缓冲后使能printk滚动动画
// printk_enable_animation();
// 初始化第一个屏幕刷新任务

View File

@ -345,7 +345,7 @@ struct Page *alloc_pages(unsigned int zone_select, int num, ul flags)
x->attr = attr;
}
// 成功分配了页面,返回第一个页面的指针
kwarn("start page num=%d\n", start_page_num);
// kwarn("start page num=%d\n", start_page_num);
return (struct Page *)(memory_management_struct.pages_struct + start_page_num);
}
}
@ -483,7 +483,6 @@ void page_table_init()
flush_tlb();
kinfo("Page table Initialized. Affects:%d", js);
}
/**
@ -582,7 +581,10 @@ void mm_map_proc_page_table(ul proc_page_table_addr, bool is_phys, ul virt_addr_
ul *pde_ptr = pd_ptr + pde_id;
if (*pde_ptr != 0 && user)
{
kwarn("page already mapped!");
// kwarn("page already mapped!");
// 如果是用户态可访问的页,则释放当前新获取的物理页
free_pages(Phy_to_2M_Page((ul)phys_addr_start + length_mapped), 1);
length_mapped += PAGE_2M_SIZE;
continue;
}
// 页面写穿,禁止缓存

View File

@ -110,14 +110,6 @@ void __switch_to(struct process_control_block *prev, struct process_control_bloc
// set_tss64((uint *)phys_2_virt(TSS64_Table), initial_tss[0].rsp0, initial_tss[0].rsp1, initial_tss[0].rsp2, initial_tss[0].ist1,
// initial_tss[0].ist2, initial_tss[0].ist3, initial_tss[0].ist4, initial_tss[0].ist5, initial_tss[0].ist6, initial_tss[0].ist7);
if (next->pid == 2)
{
struct pt_regs *child_regs = (struct pt_regs *)next->thread->rsp;
kdebug("next->thd->rip=%#018lx", next->thread->rip);
kdebug("next proc's ret addr = %#018lx\t next child_regs->rsp = %#018lx, next new_rip=%#018lx)", child_regs->rip, child_regs->rsp, child_regs->rip);
}
__asm__ __volatile__("movq %%fs, %0 \n\t"
: "=a"(prev->thread->fs));
__asm__ __volatile__("movq %%gs, %0 \n\t"
@ -214,7 +206,7 @@ static int process_load_elf_file(struct pt_regs *regs, char *path)
retval = -EUNSUPPORTED;
goto load_elf_failed;
}
kdebug("filename=%s:\te_entry=%#018lx", path, ehdr.e_entry);
// kdebug("filename=%s:\te_entry=%#018lx", path, ehdr.e_entry);
regs->rip = ehdr.e_entry;
current_pcb->mm->code_addr_start = ehdr.e_entry;
@ -246,7 +238,7 @@ static int process_load_elf_file(struct pt_regs *regs, char *path)
pos = phdr->p_offset;
uint64_t virt_base = phdr->p_vaddr;
kdebug("virt_base = %#018lx, &memory_management_struct=%#018lx", virt_base, &memory_management_struct);
// kdebug("virt_base = %#018lx, &memory_management_struct=%#018lx", virt_base, &memory_management_struct);
while (remain_mem_size > 0)
{
@ -254,7 +246,7 @@ static int process_load_elf_file(struct pt_regs *regs, char *path)
// todo: 改用slab分配4K大小内存块并映射到4K页
if (!mm_check_mapped((uint64_t)current_pcb->mm->pgd, virt_base)) // 未映射,则新增物理页
{
mm_map_proc_page_table((uint64_t)current_pcb->mm->pgd, true, virt_base, alloc_pages(ZONE_NORMAL, 10, PAGE_PGT_MAPPED)->addr_phys, PAGE_2M_SIZE, PAGE_USER_PAGE, true, true);
mm_map_proc_page_table((uint64_t)current_pcb->mm->pgd, true, virt_base, alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys, PAGE_2M_SIZE, PAGE_USER_PAGE, true, true);
memset((void *)virt_base, 0, PAGE_2M_SIZE);
}
@ -280,16 +272,7 @@ static int process_load_elf_file(struct pt_regs *regs, char *path)
regs->rbp = current_pcb->mm->stack_start;
uint64_t pa = alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys;
// pa+= PAGE_2M_SIZE;
kdebug("pa1=%#018lx", pa);
// mm_map_proc_page_table((uint64_t)current_pcb->mm->pgd, true, current_pcb->mm->stack_start - PAGE_2M_SIZE, alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys, PAGE_2M_SIZE, PAGE_USER_PAGE, true, false);
// mm_map_proc_page_table((uint64_t)current_pcb->mm->pgd, true, current_pcb->mm->stack_start - PAGE_2M_SIZE, pa, PAGE_2M_SIZE, PAGE_USER_PAGE, true, true);
// pa = alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys;
// kdebug("pa2=%#018lx", pa);
// // mm_map_proc_page_table((uint64_t)current_pcb->mm->pgd, true, current_pcb->mm->stack_start - PAGE_2M_SIZE, pa, PAGE_2M_SIZE, PAGE_USER_PAGE, true, true);
// pa = alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys;
// kdebug("pa3=%#018lx", pa);
mm_map_proc_page_table((uint64_t)current_pcb->mm->pgd, true, current_pcb->mm->stack_start - PAGE_2M_SIZE, pa, PAGE_2M_SIZE, PAGE_USER_PAGE, true, true);
// mm_map_proc_page_table((uint64_t)current_pcb->mm->pgd, true, current_pcb->mm->stack_start - PAGE_2M_SIZE, alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys, 1 * PAGE_2M_SIZE, PAGE_USER_PAGE, true);
// 清空栈空间
@ -324,7 +307,7 @@ load_elf_failed:;
ul do_execve(struct pt_regs *regs, char *path, char *argv[], char *envp[])
{
kdebug("do_execve is running...");
// kdebug("do_execve is running...");
// 当前进程正在与父进程共享地址空间,需要创建
// 独立的地址空间才能使新程序正常运行
@ -389,6 +372,10 @@ ul do_execve(struct pt_regs *regs, char *path, char *argv[], char *envp[])
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);
@ -407,7 +394,7 @@ ul do_execve(struct pt_regs *regs, char *path, char *argv[], char *envp[])
regs->rdi = argc;
regs->rsi = (uint64_t)dst_argv;
}
kdebug("execve ok");
// kdebug("execve ok");
regs->cs = USER_CS | 3;
regs->ds = USER_DS | 3;
@ -671,7 +658,7 @@ unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned
// 拷贝成功
retval = tsk->pid;
kdebug("fork done: tsk->pid=%d", tsk->pid);
// kdebug("fork done: tsk->pid=%d", tsk->pid);
// kdebug("current_pcb->mm->brk_end=%#018lx", current_pcb->mm->brk_end);
// mm_map_proc_page_table((uint64_t)current_pcb->mm->pgd, true, 0x0000500000000000, alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys, PAGE_2M_SIZE, PAGE_USER_PAGE, true);
@ -838,7 +825,7 @@ uint64_t process_copy_mm(uint64_t clone_flags, struct process_control_block *pcb
// 当前页表项为空
if ((*(uint64_t *)(current_pgd + i)) == 0)
continue;
kdebug("user page [%d]", i);
// 分配新的二级页表
uint64_t *new_pdpt = (uint64_t *)kmalloc(PAGE_4K_SIZE, 0);
memset(new_pdpt, 0, PAGE_4K_SIZE);
@ -847,7 +834,7 @@ uint64_t process_copy_mm(uint64_t clone_flags, struct process_control_block *pcb
set_pml4t(new_pml4t + i, mk_pml4t(virt_2_phys(new_pdpt), (*(current_pgd + i)) & 0xfffUL));
uint64_t *current_pdpt = (uint64_t *)phys_2_virt((*(uint64_t *)(current_pgd + i)) & (~0xfffUL));
kdebug("current_pdpt=%#018lx, current_pid=%d", current_pdpt, current_pcb->pid);
// kdebug("current_pdpt=%#018lx, current_pid=%d", current_pdpt, current_pcb->pid);
for (int j = 0; j < 512; ++j)
{
if (*(current_pdpt + j) == 0)
@ -861,7 +848,8 @@ uint64_t process_copy_mm(uint64_t clone_flags, struct process_control_block *pcb
set_pdpt((uint64_t *)(new_pdpt + j), mk_pdpt(virt_2_phys(new_pdt), (*(current_pdpt + j)) & 0xfffUL));
uint64_t *current_pdt = (uint64_t *)phys_2_virt((*(current_pdpt + j)) & (~0xfffUL));
kdebug("current_pdt=%#018lx", current_pdt);
// kdebug("current_pdt=%#018lx", current_pdt);
// 循环拷贝三级页表
for (int k = 0; k < 512; ++k)
{
@ -878,21 +866,10 @@ uint64_t process_copy_mm(uint64_t clone_flags, struct process_control_block *pcb
// 拷贝数据
memcpy(phys_2_virt(pa), phys_2_virt((*(current_pdt + k)) & (~0x1ffUL)), PAGE_2M_SIZE);
// 计算当前虚拟地址
// uint64_t current_vaddr = 0;
// current_vaddr = ((1UL * i) << PAGE_GDT_SHIFT) | ((1UL * j) << PAGE_1G_SHIFT) | ((1UL * k) << PAGE_2M_SHIFT);
// mm_map_proc_page_table((uint64_t)pcb->mm->pgd, true, current_vaddr, pa, PAGE_2M_SIZE, PAGE_USER_PAGE, true, false);
// memcpy((void *)phys_2_virt(pa), (void *)current_vaddr, PAGE_2M_SIZE);
}
}
}
return retval;
}
@ -986,13 +963,13 @@ uint64_t process_copy_thread(uint64_t clone_flags, struct process_control_block
thd->fs = current_pcb->thread->fs;
thd->gs = current_pcb->thread->gs;
kdebug("pcb->flags=%ld", pcb->flags);
// kdebug("pcb->flags=%ld", pcb->flags);
// 根据是否为内核线程,设置进程的开始执行的地址
if (pcb->flags & PF_KTHREAD)
thd->rip = (uint64_t)kernel_thread_func;
else
thd->rip = (uint64_t)ret_from_system_call;
kdebug("new proc's ret addr = %#018lx\tthd->rip=%#018lx stack_start=%#018lx child_regs->rsp = %#018lx, new_rip=%#018lx)", child_regs->rbx, thd->rip, stack_start, child_regs->rsp, child_regs->rip);
// kdebug("new proc's ret addr = %#018lx\tthd->rip=%#018lx stack_start=%#018lx child_regs->rsp = %#018lx, new_rip=%#018lx)", child_regs->rbx, thd->rip, stack_start, child_regs->rsp, child_regs->rip);
return 0;
}

View File

@ -361,7 +361,7 @@ uint64_t sys_lseek(struct pt_regs *regs)
uint64_t sys_fork(struct pt_regs *regs)
{
kdebug("sys_fork");
// kdebug("sys_fork");
return do_fork(regs, 0, regs->rsp, 0);
}
uint64_t sys_vfork(struct pt_regs *regs)
@ -560,13 +560,13 @@ uint64_t sys_getdents(struct pt_regs *regs)
*/
uint64_t sys_execve(struct pt_regs *regs)
{
kdebug("sys_execve");
// kdebug("sys_execve");
char *user_path = (char *)regs->r8;
char **argv = (char **)regs->r9;
int path_len = strnlen_user(user_path, PAGE_4K_SIZE);
kdebug("path_len=%d", path_len);
// kdebug("path_len=%d", path_len);
if (path_len >= PAGE_4K_SIZE)
return -ENAMETOOLONG;
else if (path_len <= 0)
@ -578,12 +578,12 @@ uint64_t sys_execve(struct pt_regs *regs)
memset(path, 0, path_len + 1);
kdebug("before copy file path from user");
// kdebug("before copy file path from user");
// 拷贝文件路径
strncpy_from_user(path, user_path, path_len);
path[path_len] = '\0';
kdebug("before do_execve, path = %s", path);
// kdebug("before do_execve, path = %s", path);
// 执行新的程序
uint64_t retval = do_execve(regs, path, argv, NULL);

3
run.sh
View File

@ -88,10 +88,11 @@ else
flag_can_run=1
fi
# 拷贝shell到硬盘
# 拷贝应用程序到硬盘
cd tools
bash m*
sudo cp ${root_folder}/bin/user/shell.elf ${root_folder}/bin/disk_mount
sudo cp ${root_folder}/bin/user/about.elf ${root_folder}/bin/disk_mount
sync
bash u*
cd ..

View File

@ -1,5 +1,5 @@
user_apps_sub_dirs=shell
user_apps_sub_dirs=shell about
all:
@list='$(user_apps_sub_dirs)'; for subdir in $$list; do \

View File

@ -1,6 +1,6 @@
all: about.o
ld -b elf64-x86-64 -z muldefs -o $(tmp_output_dir)/about $(shell find . -name "*.o") $(shell find $(sys_libs_dir) -name "*.o") -T shell.lds
ld -b elf64-x86-64 -z muldefs -o $(tmp_output_dir)/about $(shell find . -name "*.o") $(shell find $(sys_libs_dir) -name "*.o") -T about.lds
objcopy -I elf64-x86-64 -S -R ".eh_frame" -R ".comment" -O elf64-x86-64 $(tmp_output_dir)/about $(output_dir)/about.elf
about.o: about.c

View File

@ -3,5 +3,6 @@
int main()
{
printf("Hello World!\n");
exit(0);
while(1);
}

50
user/apps/about/about.lds Normal file
View File

@ -0,0 +1,50 @@
OUTPUT_FORMAT("elf64-x86-64","elf64-x86-64","elf64-x86-64")
OUTPUT_ARCH(i386:x86-64)
ENTRY(main)
SECTIONS
{
. = 0x800000;
.text :
{
_text = .;
*(.text)
_etext = .;
}
. = ALIGN(8);
.data :
{
_data = .;
*(.data)
_edata = .;
}
rodata_start_pa = .;
.rodata :
{
_rodata = .;
*(.rodata)
_erodata = .;
}
.bss :
{
_bss = .;
*(.bss)
_ebss = .;
}
_end = .;
}

View File

@ -369,16 +369,15 @@ int shell_cmd_exec(int argc, char **argv)
{
pid_t pid = fork();
int retval = 0;
printf(" pid=%d \n",pid);
// printf(" pid=%d \n",pid);
while(1);
if (pid == 0)
{
printf("child proc\n");
// printf("child proc\n");
// 子进程
int path_len = 0;
char *file_path = get_target_filepath(argv[1], &path_len);
printf("before execv, path=%s\n", file_path);
// printf("before execv, path=%s, argc=%d\n", file_path, argc);
execv(file_path, argv);
free(argv);
while(1);
@ -387,13 +386,13 @@ int shell_cmd_exec(int argc, char **argv)
else
{
printf("parent process wait for pid:[ %d ]\n", pid);
while(1);
waitpid(pid, &retval, 0);
printf("parent process wait pid [ %d ], exit code=%d\n", pid, retval);
free(argv);
}
while(1);
}
/**

View File

@ -42,19 +42,6 @@ void main_loop(int kb_fd)
unsigned char input_buffer[INPUT_BUFFER_SIZE] = {0};
sbrk(24);
// brk(0x700000000000 + (1<<21));
pid_t pid = fork();
int retval = 0;
for(int i=0;i<10;++i)
printf(" @pid=%d ", pid);
if(pid == 0)
{
int a = 1/0;
}
// 初始化当前工作目录的路径
shell_current_path = (char *)malloc(3);