当前位置:网站首页>可執行程序執行流程
可執行程序執行流程
2022-04-23 05:26:00 【生活需要深度】
./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指令進入軟中斷轉入操作系統中斷處理中進行處理。
版权声明
本文为[生活需要深度]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204230525501380.html
边栏推荐
猜你喜欢
Redis的基本知识
Graphics.FromImage报错“Graphics object cannot be created from an image that has an indexed pixel ...”
Three of three JS (webgl) simple sorting of rotation attribute function, and a simple case of rotating around the axis based on this
Solution of how to log in with mobile phone verification code in wireless network
Graphics. Fromimage reports an error "graphics object cannot be created from an image that has an indexed pixel..."
selenium预先加载cookie的必要性
狼叔来找翻译人员了--plato--持续翻译中.....
JSP -- Introduction to JSP
Double click The jar package cannot run the solution
JSP-----JSP简介
随机推荐
MFC实现资源单独Dll实现
Kanban Quick Start Guide
MySQL series - install MySQL 5.6.27 on Linux and solve common problems
Using PHP post temporary file mechanism to upload arbitrary files
Qingdao agile tour, coming!
To understand Devops, you must read these ten books!
改进DevSecOps框架的 5 大关键技术
学习笔记:Unity CustomSRP-11-Post Processing---Bloom
CPT 104_ TTL 09
varnish入门
node中的redis使用--ioredis
what is wifi6?
Use pagoda + Xdebug + vscode to debug code remotely
phphphphphphphp
Getting started with varnish
CPT 104_TTL 09
Vscode settings JSON configuration
FileReader API file operation
Domain driven model DDD (III) -- using saga to manage transactions
分支与循环语句