./hello_world这个命令在linux内核系统中具体是怎么执行的。文件系统使用busybox,对应的linux内核调用过程。
busybox中shell解析命令行
int ash_main(int argc, char **argv)
{
state4: /* XXX ??? - why isn't this before the "if" statement */
cmdloop(1);
}
static int
cmdloop(int top)
{
union node *n;
struct stackmark smark;
int inter;
int numeof = 0;
printf("1. cmdloop\n");
TRACE(("cmdloop(%d) called\n", top));
for (;;) {
} else if (nflag == 0) {
/* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
printf("3. cmdloop\n");
job_warning >>= 1;
numeof = 0;
evaltree(n, 0);
printf("4. cmdloop\n");
}
}
static void
evaltree(union node *n, int flags)
{
int checkexit = 0;
void (*evalfn)(union node *, int);
unsigned isor;
int status;
if (n == NULL) {
TRACE(("evaltree(NULL) called\n"));
goto out;
}
case NCMD:
evalfn = evalcommand;
printf("2. evaltree ncmd switch\n");
checkexit:
if (eflag && !(flags & EV_TESTED))
checkexit = ~0;
goto calleval;
calleval:
evalfn(n, flags);
break;
}
}
static void
evalcommand(union node *cmd, int flags)
{
static const struct builtincmd bltin = {
"\0\0", bltincmd
};
struct stackmark smark;
/* Execute the command. */
switch (cmdentry.cmdtype) {
default:
printf("2. cmdentry.cmdtype default.\n");
/* Fork off a child process if necessary. */
if (!(flags & EV_EXIT) || trap[0]) {
INT_OFF;
jp = makejob(cmd, 1);
if (forkshell(jp, cmd, FORK_FG) != 0) {
exitstatus = waitforjob(jp);
INT_ON;
break;
}
printf("3. cmdentry.cmdtype forkshell.\n");
FORCE_INT_ON;
}
listsetvar(varlist.list, VEXPORT|VSTACK);
shellexec(argv, path, cmdentry.u.index);
/* NOTREACHED */
}
命令执行过程中这里面会调用两个系统调用forkshell和shellexec,通过shellexec举例看系统调用
static void
shellexec(char **argv, const char *path, int idx)
{
char *cmdname;
int e;
char **envp;
int exerrno;
clearredir(1);
envp = environment();
if (strchr(argv[0], '/')
#if ENABLE_FEATURE_SH_STANDALONE
|| find_applet_by_name(argv[0])
#endif
) {
tryexec(argv[0], argv, envp);
e = errno;
} else {
e = ENOENT;
while ((cmdname = padvance(&path, argv[0])) != NULL) {
if (--idx < 0 && pathopt == NULL) {
tryexec(cmdname, argv, envp);
if (errno != ENOENT && errno != ENOTDIR)
e = errno;
}
stunalloc(cmdname);
}
}
}
static void
tryexec(char *cmd, char **argv, char **envp)
{
int repeated = 0;
repeat:
#ifdef SYSV
do {
execve(cmd, argv, envp);
} while (errno == EINTR);
#else
execve(cmd, argv, envp);
#endif
}
execve函数是gcc编译工具提供的库文件实现glibc-2.3.6/sysdeps/unix/sysv/linux/execve.c中定义
int
__execve (file, argv, envp)
const char *file;
char *const argv[];
char *const envp[];
{
#if __BOUNDED_POINTERS__
{
char *const *v;
int i;
char *__unbounded *__unbounded ubp_argv;
char *__unbounded *__unbounded ubp_envp;
char *__unbounded *__unbounded ubp_v;
for (v = argv; *v; v++)
;
i = v - argv + 1;
ubp_argv = (char *__unbounded *__unbounded) alloca (sizeof (*ubp_argv) * i);
for (v = argv, ubp_v = ubp_argv; --i; v++, ubp_v++)
*ubp_v = CHECK_STRING (*v);
*ubp_v = 0;
for (v = envp; *v; v++)
;
i = v - envp + 1;
ubp_envp = (char *__unbounded *__unbounded) alloca (sizeof (*ubp_envp) * i);
for (v = envp, ubp_v = ubp_envp; --i; v++, ubp_v++)
*ubp_v = CHECK_STRING (*v);
*ubp_v = 0;
return INLINE_SYSCALL (execve, 3, CHECK_STRING (file), ubp_argv, ubp_envp);
}
#else
return INLINE_SYSCALL (execve, 3, file, argv, envp);
#endif
}
weak_alias (__execve, execve)
最终调用到INLINE_SYSCALL宏在头文件glibc-2.3.6/sysdeps/unix/sysv/linux/arm/sysdep.h中实现
/* Define a macro which expands into the inline wrapper code for a system
call. */
#undef INLINE_SYSCALL
#define INLINE_SYSCALL(name, nr, args...) \
({ unsigned int _sys_result = INTERNAL_SYSCALL (name, , nr, args); \
if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_sys_result, ), 0)) \
{ \
__set_errno (INTERNAL_SYSCALL_ERRNO (_sys_result, )); \
_sys_result = (unsigned int) -1; \
} \
(int) _sys_result; })
#undef INTERNAL_SYSCALL_DECL
#define INTERNAL_SYSCALL_DECL(err) do { } while (0)
#undef INTERNAL_SYSCALL
#define INTERNAL_SYSCALL(name, err, nr, args...) \
({ unsigned int _sys_result; \
{ \
register int _a1 asm ("a1"); \
LOAD_ARGS_##nr (args) \
asm volatile ("swi %1 @ syscall " #name \
: "=r" (_a1) \
: "i" (SYS_ify(name)) ASM_ARGS_##nr \
: "memory"); \
_sys_result = _a1; \
} \
(int) _sys_result; })
最终会调用到arm的switch指令进入软中断转入操作系统中断处理中进行处理。
|