从中断到终端
可以说,我们的操作系统之旅,从zhong duan(中断)开始, 也在zhong duan(终端)结束。
我们的终端需要实现这样的功能: 根据输入的程序名称, 从文件系统里加载对应的程序并执行。我们采取fork() exec()的方式来加载执行程序,exec()的一系列接口都需要重写来使用文件系统。以do_execve()为例,
以前的函数原型从内存的某个位置加载程序
int do_execve(const char *name, size_t len, unsigned char *binary, size_t size) ;现在则调用文件系统接口加载程序:
// kern/process/proc.c
// do_execve - call exit_mmap(mm)&put_pgdir(mm) to reclaim memory space of current process
// - call load_icode to setup new memory space accroding binary prog.
int
do_execve(const char *name, int argc, const char **argv) {
static_assert(EXEC_MAX_ARG_LEN >= FS_MAX_FPATH_LEN);
struct mm_struct *mm = current->mm;
if (!(argc >= 1 && argc <= EXEC_MAX_ARG_NUM)) {
return -E_INVAL;
}
char local_name[PROC_NAME_LEN + 1];
memset(local_name, 0, sizeof(local_name));
char *kargv[EXEC_MAX_ARG_NUM];
const char *path;
int ret = -E_INVAL;
lock_mm(mm);
if (name == NULL) {
snprintf(local_name, sizeof(local_name), "<null> %d", current->pid);
}
else {
if (!copy_string(mm, local_name, name, sizeof(local_name))) {
unlock_mm(mm);
return ret;
}
}
if ((ret = copy_kargv(mm, argc, kargv, argv)) != 0) {
unlock_mm(mm);
return ret;
}
path = argv[0];
unlock_mm(mm);
files_closeall(current->filesp);
/* sysfile_open will check the first argument path, thus we have to use a user-space pointer, and argv[0] may be incorrect */
int fd;
if ((ret = fd = sysfile_open(path, O_RDONLY)) < 0) {
goto execve_exit;
}
if (mm != NULL) {
lcr3(boot_cr3);
if (mm_count_dec(mm) == 0) {
exit_mmap(mm);
put_pgdir(mm);
mm_destroy(mm);
}
current->mm = NULL;
}
ret= -E_NO_MEM;;
if ((ret = load_icode(fd, argc, kargv)) != 0) {
goto execve_exit;
}
put_kargv(argc, kargv);
set_proc_name(current, local_name);
return 0;
execve_exit:
put_kargv(argc, kargv);
do_exit(ret);
panic("already exit: %e.\n", ret);
}我们还要看一下终端程序的实现。可以发现终端程序需要对命令进行词法和语法分析。
如果我们能够把终端运行起来,并能输入命令执行用户程序,就说明程序运行正常。
最后更新于
这有帮助吗?