当前位置:网站首页>可執行程序執行流程
可執行程序執行流程
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
边栏推荐
- Branch and loop statements
- Domain driven model DDD (III) -- using saga to manage transactions
- What are the reasons for the failure of digital transformation?
- Mairadb数据库基本操作之数据管理
- WTL 自绘控件库 (CQsCheckComboxBox)
- If I am PM's performance, movie VR ticket purchase display
- 4 个最常见的自动化测试挑战及应对措施
- 使用宝塔+xdebug+vscode远程调试代码
- egg测试的知识大全--mock、superTest、coffee
- CPT 104_ TTL 09
猜你喜欢

Nécessité de précharger les cookies dans le sélénium

Double click The jar package cannot run the solution

Master-slave replication of MariaDB database

我这位老程序员对时代危险和机遇的一点感悟?

Good test data management, in the end how to do?

es6数组的使用

Laravel routing job

(11) Vscode code formatting configuration

Use of ES6 array

Graphics. Fromimage reports an error "graphics object cannot be created from an image that has an indexed pixel..."
随机推荐
TSlint注释忽略错误和RESTful理解
JSP -- Introduction to JSP
狼叔来找翻译人员了--plato--持续翻译中.....
分支与循环语句
Study notes: unity customsrp-11-post processing --- bloom
日志简介和构建web应用
Call the interface to get the time
CPT 104_TTL 09
Uniapp wechat sharing
Knowledge of egg testing -- mock, Supertest, coffee
What are the most popular recruitment technical skills in 2022? You can't think of it
开源规则引擎——ice:致力于解决灵活繁复的硬编码问题
JS Array常见方法
To understand Devops, you must read these ten books!
Double click The jar package cannot run the solution
学习笔记:Unity CustomSRP-12-HDR
Three 之 three.js (webgl)模型的删除/场景的清空/内存的释放 的简单整理
史上最强egg框架的error处理机制
phphphphphphphp
If I am PM's performance, movie VR ticket purchase display