首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >系统调用do_execv还是execv?

系统调用do_execv还是execv?
EN

Stack Overflow用户
提问于 2021-05-07 18:05:17
回答 1查看 211关注 0票数 1

引用我演讲中的话:

注意到用户空间和内核空间之间的清晰边界。用户程序不能在代码中包含内核头,也不能直接调用内核函数。换句话说,您的程序不能简单地调用sys_read()服务函数从磁盘读取文件。类似地,内核代码不像printf()那样调用用户空间函数,不包括像这样的用户空间标头,也不链接到libc这样的用户空间库。如前所述,用户可以使用的内核模式(和OS服务)的唯一入口是syscall指令。

  1. “用户程序不能包括内核头”,所以当我在C程序中编写getpid()时,这个用户空间函数是

吗?

  1. ,当我在终端中键入getpid时,它是相同的(使用空间函数)吗?

  1. I不能访问系统/home/ user / linux -4.15中的linux头文件,所以怎么说用户空间不能访问内核空间?

  1. 给出了以下图像:

我打开了一些linux文件(init/main.c)并看到:

代码语言:javascript
复制
static int run_init_process(const char *init_filename)
{
      argv_init[0] = init_filename;
      return do_execve(getname_kernel(init_filename),....
}

这个do_execve在哪里声明的?图中只显示execvsys_execv..。有什么区别吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-05-07 19:38:44

“用户程序不能包括内核标题”,所以当我在C程序getpid()中编写时,这个用户空间函数是吗?

是。它是libc中调用系统调用的薄包装器。但是,取决于体系结构和libc实现,在用户空间中可能会有一些簿记(例如,为以后的调用缓存结果)。

对于许多简单的系统,glibc使用预处理宏生成这些包装器。在我的系统中,对getpid的用户空间调用转到sysdeps/unix/syscall-template.S文件。

代码语言:javascript
复制
0x00007ffff7ea6244  59  in ../sysdeps/unix/syscall-template.S
(gdb) disassemble 
Dump of assembler code for function getpid:
   0x00007ffff7ea6240 <+0>: endbr64 
=> 0x00007ffff7ea6244 <+4>: mov    $0x27,%eax
   0x00007ffff7ea6249 <+9>: syscall 
   0x00007ffff7ea624b <+11>:    retq   
End of assembler dump.

它简单地将syscall号放在寄存器中并执行syscall指令。

我们使用这个包装器的原因是为了避免了解不同体系结构和内核的syscall机制和数量的具体情况。这使得我们的程序更便携。我们所链接的libc知道0x27是这个系统上的getpid,并且应该写入%eax等等。

执行syscall指令时,处理器切换到内核模式,并从arch/x86/entry/entry_64.S开始执行,其中entry_SYSCALL_64调用位于arch/x86/entry/common.c中的do_syscall_64

代码语言:javascript
复制
        regs->ax = sys_call_table[nr](regs);

您可以看到,它在索引nr处调用sys_call_table的函数。此表由符号列表(sys_something)填充,其中每个符号由宏:SYSCALL_DEFINEn定义,其中n是参数数。因为getpid不是一个参数,所以在kernel/sys.c中它被定义为SYSCALL_DEFINE0(getpid)

代码语言:javascript
复制
/**
 * sys_getpid - return the thread group id of the current process
 *
 * Note, despite the name, this returns the tgid not the pid.  The tgid and
 * the pid are identical unless CLONE_THREAD was specified on clone() in
 * which case the tgid is the same in all threads of the same group.
 *
 * This is SMP safe as current->tgid does not change.
 */
SYSCALL_DEFINE0(getpid)
{
    return task_tgid_vnr(current);
}

,当我在终端中输入getpid时,它是相同的(使用空间函数)吗?

我不知道终端命令getpid,但如果有,它将是一个可执行的二进制文件(或脚本),最终会调用syscall或syscall的libc包装器。因为内核维护任务和进程ID,并且用户空间代码无法访问内核内存。

我不能访问我的系统/home/ user / linux -4.15中的linux头文件,那么怎么说用户空间不能访问内核空间呢?

你是说你可以访问头文件吗?当然,您可以访问整个源代码。但是,即使您在程序中包含了这些头部,并编译它们,并以某种方式将它们与内核代码链接起来,但这并不意味着您可以在内核模式下运行它们。

除了,如果您使用可加载的内核模块。实际上,您需要内核头文件来编译内核模块。然后,您可以请求内核以内核模式加载和执行这些模块。但是您需要调用另一个syscall (init_module)来实现这一点。

,do_execve在哪里声明的?图中只显示了execv和sys_execv..。有什么区别吗?

以下是syscall execve的定义

代码语言:javascript
复制
SYSCALL_DEFINE3(execve,
        const char __user *, filename,
        const char __user *const __user *, argv,
        const char __user *const __user *, envp)
{
    return do_execve(getname(filename), argv, envp);
}

getpid类似,execve是用一个生成sys_execve符号的SYSCALL_DEFINEn (这次是三个参数)宏定义的。在内部,内核调用do_execve。如果搜索文件的其余部分,您将看到do_execve本身是do_execveat_common的包装器。经过一些检查和初始化后,调用bprm_execve,它调用exec_binprm,等等。

,你能详细说明一下do_execvesys_execve的区别吗?

没什么区别。除了,sys_execve符号是由SYSCALL_DEFINE3宏定义的,它是由特定于体系结构的syscall机制调用的,它可以不同于常规的C函数(例如asmlinkage)。do_execve是一个正则C函数。在这个例子中,它不是从任何其他C代码中调用的,但是它是可能的。但是,直接从内核代码中调用sys_execve是不正确的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67439775

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档