- 下载解压 bash-3.2
- 编译bash
export LFS=/my/soft/mylfs tar xvf $LFS/sources/bash-3.2.tar.gz -C $LFS/sources/ cd $LFS/sources/bash-3.2/ patch -Np1 -i ../bash-3.2-fixes-5.patch ./configure --prefix=$LFS/builds --without-bash-malloc make make install
- 常用的调用堆栈
在读取命令之前执行一些命令,如PS1的打印 bash [C/C++ Application] bash [9867] [cores: 0] Thread #1 9867 [core: 0] (Suspended : Step) execute_builtin_or_function() at execute_cmd.c:3,562 0x42bf86 execute_simple_command() at execute_cmd.c:3,019 0x42bf86 execute_command_internal() at execute_cmd.c:672 0x42952e parse_and_execute() at evalstring.c:275 0x45dc63 execute_variable_command() at parse.y:2,159 0x41e157 parse_command() at eval.c:215 0x41b1c2 read_command() at eval.c:266 0x41b2a6 reader_loop() at eval.c:132 0x41b4e4 main() at shell.c:715 0x41ac53 gdb (7.2)
执行用户输入命令的堆栈 bash [C/C++ Application] bash [2689] [cores: 0] Thread #1 2689 [core: 0] (Suspended : Step) cd_builtin() at cd.def:163 0x45a830 execute_builtin() at execute_cmd.c:3,153 0x4283d1 execute_builtin_or_function() at execute_cmd.c:3,539 0x42bf60 execute_simple_command() at execute_cmd.c:3,019 0x42bf60 execute_command_internal() at execute_cmd.c:672 0x42952e execute_command() at execute_cmd.c:352 0x429ffe reader_loop() at eval.c:147 0x41b412 main() at shell.c:715 0x41ac53 gdb (7.2)
execute_builtin_or_function 方法有一个分支,分为执行内建命令和执行函数 if (builtin) result = execute_builtin (builtin, words, flags, 0); else result = execute_function (var, words, flags, fds_to_close, 0, 0); 如果是执行函数,如何找到执行的函数呢? func = find_function (words->word->word); /* Return the pointer to the function implementing builtin command NAME. */ sh_builtin_func_t * find_shell_builtin (name) char *name; { current_builtin = builtin_address_internal (name, 0); return (current_builtin ? current_builtin->function : (sh_builtin_func_t *)NULL); }
- 执行内置命令的方法如下:
static int execute_builtin (builtin, words, flags, subshell) sh_builtin_func_t *builtin; WORD_LIST *words; int flags, subshell; { int old_e_flag, result, eval_unwind; int isbltinenv; old_e_flag = exit_immediately_on_error; /* The eval builtin calls parse_and_execute, which does not know about the setting of flags, and always calls the execution functions with flags that will exit the shell on an error if -e is set. If the eval builtin is being called, and we're supposed to ignore the exit value of the command, we turn the -e flag off ourselves, then restore it when the command completes. */ if (subshell == 0 && builtin == eval_builtin && (flags & CMD_IGNORE_RETURN)) { begin_unwind_frame ("eval_builtin"); unwind_protect_int (exit_immediately_on_error); exit_immediately_on_error = 0; eval_unwind = 1; } else eval_unwind = 0; /* The temporary environment for a builtin is supposed to apply to all commands executed by that builtin. Currently, this is a problem only with the `unset', `source' and `eval' builtins. */ isbltinenv = (builtin == source_builtin || builtin == eval_builtin || builtin == unset_builtin); if (isbltinenv) { if (subshell == 0) begin_unwind_frame ("builtin_env"); if (temporary_env) { push_scope (VC_BLTNENV, temporary_env); if (subshell == 0) add_unwind_protect (pop_scope, (flags & CMD_COMMAND_BUILTIN) ? 0 : "1"); temporary_env = (HASH_TABLE *)NULL; } } /* `return' does a longjmp() back to a saved environment in execute_function. If a variable assignment list preceded the command, and the shell is running in POSIX mode, we need to merge that into the shell_variables table, since `return' is a POSIX special builtin. */ if (posixly_correct && subshell == 0 && builtin == return_builtin && temporary_env) { begin_unwind_frame ("return_temp_env"); add_unwind_protect (merge_temporary_env, (char *)NULL); } /* 执行执行的语句,会调用不同的内置方法执行具体的命令,如cd命令会执行cd.def中的cd_builtin方法,内置方法的文件都在builtins目录下 */ result = ((*builtin) (words->next)); /* This shouldn't happen, but in case `return' comes back instead of longjmp'ing, we need to unwind. */ if (posixly_correct && subshell == 0 && builtin == return_builtin && temporary_env) discard_unwind_frame ("return_temp_env"); if (subshell == 0 && isbltinenv) run_unwind_frame ("builtin_env"); if (eval_unwind) { exit_immediately_on_error += old_e_flag; discard_unwind_frame ("eval_builtin"); } return (result); }