Linux进程在创建时的内核栈状态是什么?

11

我无法在任何地方找到这些信息。无论我看哪里,都能找到关于当你进入“main”(无论是什么入口点)时栈的样子的引用,这将是程序参数和环境,但我正在寻找的是系统如何设置栈以与switch_to宏配合使用。第一次切换任务时,它需要在由“tsk->thread->esp”指向的堆栈上具有EFLAGS、EBP、GCC保存的寄存器以及schedule()函数的返回地址,但我弄不清楚内核如何设置这个栈,因为它让GCC使用输出参数保存通用寄存器(使用内联汇编)。

我只涉及x86 PC。我正在研究Linux调度/进程系统,为我自己尝试编写的小内核而做准备,但我搞不明白我错过了什么。我知道我错过了某些东西,因为Slackware在我的计算机上运行就证明了调度程序正常工作:P

编辑:我表述得似乎很糟糕。我正在寻找有关如何设置任务内核栈的信息,而不是任务用户栈的设置。更具体地说,是由tsk->thread->esp指向的堆栈,并且 "switch_to" 切换到它。


看起来你有两个不同的问题 - 1)在进程初始化时堆栈状态和2)在IRQ中的内核'schedule()。您应该将其中一个问题发布为新问题,并将另一个问题保留在此处;这样,您将获得每个问题的专注答案。在Stack Overflow上,为每个问题启动单独的问题是完全可以的。 - user257111
好的,我会做!我长时间以来一直在这里阅读答案/问题,但从未发过帖子!谢谢你的提示 :)好的,我大约5分钟后会回复。我必须等待 :P - Caleb Stewart
3个回答

6
新进程的初始内核栈是在 copy_thread() 中设置的,这是一个特定于体系结构的函数。例如,x86版本的实现如下:
int copy_thread(unsigned long clone_flags, unsigned long sp,
unsigned long unused,
struct task_struct *p, struct pt_regs *regs)
{
    struct pt_regs *childregs;
    struct task_struct *tsk;
    int err;

    childregs = task_pt_regs(p);
    *childregs = *regs;
    childregs->ax = 0;
    childregs->sp = sp;

    p->thread.sp = (unsigned long) childregs;
    p->thread.sp0 = (unsigned long) (childregs+1);

    p->thread.ip = (unsigned long) ret_from_fork;

p->thread.spp->thread.ip分别是新线程的内核栈指针和指令指针。

请注意,它不会在那里放置已保存的%eflags%ebp等,因为当一个新创建的执行线程首次切换到时,它开始执行ret_from_fork(这是__switch_to()为新线程返回的位置),这意味着它不会执行switch_to()例程的后半部分。


谢谢!这正是我正在寻找的!我从来没有想到过要查看copy_thread。 - Caleb Stewart
@Caleb1994:当你记住Linux上所有新的执行线程都是通过克隆现有线程来创建的时,这就有意义了。我在结尾添加了另一个段落,可能会有所帮助。 - caf
1
这确实帮了很多忙!我的小内核现在支持fork()和yield()类型的调用 :) 非常感谢你的帮助! - Caleb Stewart

2
进程创建时堆栈的状态在X86-64 SVR4 ABI补充说明中有描述(适用于AMD64,即x86-64 64位机器)。相应的32位英特尔处理器的规范可能是ABI i386。我强烈建议您也阅读Assembly HOWTO。当然,您也应该阅读相关的Linux内核文件。

这些页面描述了执行开始后堆栈的状态。我的问题是执行前堆栈的状态,即内核设置堆栈时的状态。我的唯一问题是Linux让编译器保存通用寄存器(保存在堆栈上),但是这些寄存器的保存方式可能因编译器而异,因此我对系统如何设置初始堆栈感到困惑。我已经查看了代码,但找不到进程填充的位置。它被隐藏在机器抽象的某个地方。 - Caleb Stewart
执行之前栈不存在。所以我不明白你想要什么。内核正在按照ABI文档中描述的方式构建初始进程堆栈。 - Basile Starynkevitch
也许您忘记了内核空间和用户空间的栈是不同的? - Basile Starynkevitch
是的,我混淆了它们。对不起,我指的是内核栈。那个“switch_to”宏切换到的栈(tsk->thread->esp)。我假设由于状态信息是保存在那里的,它应该是一个内核栈:P我会相应地修改我的问题。+1因为技术上它确实回答了我似乎正在问的问题:P - Caleb Stewart

2
谷歌搜索“linux堆栈布局进程启动”会得到这个链接:“Linux/i386 ELF二进制文件的启动状态”,它描述了内核在转移控制权到libc启动代码之前执行的设置。请注意保留HTML标签,不要添加解释。

它是指在执行完成后的状态吗? - osgx
是的,它指的是在您的进程开始执行之前的状态。 - Employed Russian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接