当前位置:网站首页>可執行程序執行流程
可執行程序執行流程
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
边栏推荐
- Knowledge of egg testing -- mock, Supertest, coffee
- The title bar will be pushed to coincide with the status bar
- 双击.jar包无法运行解决方法
- What are the most popular recruitment technical skills in 2022? You can't think of it
- 狼叔来找翻译人员了--plato--持续翻译中.....
- Multi process model in egg -- egg document Porter
- 2021-10-12
- Mairadb数据库基本操作之数据管理
- selenium預先加載cookie的必要性
- MFC implementation resources are implemented separately by DLL
猜你喜欢
Kanban Quick Start Guide
JSP -- Introduction to JSP
phphphphphphphp
Excel 2016 打开文件第一次打不开,有时空白,有时很慢要打开第二次才行
Open source rule engine - Ice: dedicated to solving flexible and complex hard coding problems
Uncle wolf is looking for a translator -- Plato -- ongoing translation
selenium預先加載cookie的必要性
双击.jar包无法运行解决方法
青岛敏捷之旅,来了!
Getting started with varnish
随机推荐
Five key technologies to improve the devsecops framework
The title bar will be pushed to coincide with the status bar
Master-slave replication of MariaDB database
Parsing of string class intern() method
(11) Vscode code formatting configuration
Error handling mechanism of the strongest egg framework in history
d.ts---更详细的知识还是需要看官网的介绍(声明文件章节)
Data bus realizes the communication between brother components
Source code analysis of how to use jump table in redis
狼叔来找翻译人员了--plato--持续翻译中.....
Semi synchronous replication of MariaDB
4 个最常见的自动化测试挑战及应对措施
4 most common automated test challenges and Countermeasures
MySQL series - install MySQL 5.6.27 on Linux and solve common problems
App Store年交易额100万美元只缴15%佣金,中小开发者心里很矛盾
How to set the initial value of El input number to null
Ehcache Memcache redis three caches
egg中的多进程模型--egg文档搬运工
How to add beautiful code blocks in word | a very complete method to sort out and compare
Nécessité de précharger les cookies dans le sélénium