_do_fork()如何返回两个不同的PID(一个用于父进程,一个用于子进程)

Xaphanius;

我正在查看_do_fork()函数(),试图了解如何fork()返回父进程的子PID和子进程的0。

我认为其中nr包含子进程的PID(将返回给调用者进程),但是我看不到它如何能够向子进程返回0。

答案fork()如何知道何时返回0?表示返回值是在为新流程创建的堆栈上传递的,但是(虽然不是很了解),但是我在代码中找不到

那么,子进程的返回值0设置在哪里呢?

_do_fork()函数的代码复制如下:

long _do_fork(unsigned long clone_flags,
          unsigned long stack_start,
          unsigned long stack_size,
          int __user *parent_tidptr,
          int __user *child_tidptr,
          unsigned long tls)
{
    struct task_struct *p;
    int trace = 0;
    long nr;

    /*
     * Determine whether and which event to report to ptracer.  When
     * called from kernel_thread or CLONE_UNTRACED is explicitly
     * requested, no event is reported; otherwise, report if the event
     * for the type of forking is enabled.
     */
    if (!(clone_flags & CLONE_UNTRACED)) {
        if (clone_flags & CLONE_VFORK)
            trace = PTRACE_EVENT_VFORK;
        else if ((clone_flags & CSIGNAL) != SIGCHLD)
            trace = PTRACE_EVENT_CLONE;
        else
            trace = PTRACE_EVENT_FORK;

        if (likely(!ptrace_event_enabled(current, trace)))
            trace = 0;
    }

    p = copy_process(clone_flags, stack_start, stack_size,
             child_tidptr, NULL, trace, tls, NUMA_NO_NODE);
    add_latent_entropy();
    /*
     * Do this prior waking up the new thread - the thread pointer
     * might get invalid after that point, if the thread exits quickly.
     */
    if (!IS_ERR(p)) {
        struct completion vfork;
        struct pid *pid;

        trace_sched_process_fork(current, p);

        pid = get_task_pid(p, PIDTYPE_PID);
        nr = pid_vnr(pid);

        if (clone_flags & CLONE_PARENT_SETTID)
            put_user(nr, parent_tidptr);

        if (clone_flags & CLONE_VFORK) {
            p->vfork_done = &vfork;
            init_completion(&vfork);
            get_task_struct(p);
        }

        wake_up_new_task(p);

        /* forking complete and child started to run, tell ptracer */
        if (unlikely(trace))
            ptrace_event_pid(trace, pid);

        if (clone_flags & CLONE_VFORK) {
            if (!wait_for_vfork_done(p, &vfork))
                ptrace_event_pid(PTRACE_EVENT_VFORK_DONE, pid);
        }

        put_pid(pid);
    } else {
        nr = PTR_ERR(p);
    }
    return nr;
}
阿杰(Ajay Brahmakshatriya):

您已使用正确标识了如何将新的进程ID返回给父进程return nr但是,return 0由于此代码是在父线程上执行的,所以您将永远看不到任何地方。此代码不适用于创建的新过程。

现在让我们检查一下_do_fork功能。

...
}
p = copy_process(clone_flags, stack_start, stack_size,
         child_tidptr, NULL, trace, tls, NUMA_NO_NODE);
add_latent_entropy();
...

这是所有魔术发生的地方。当您调用copy_process时,它在内部调用copy_thread目标特定代码。该函数负责处理与线程相关的数据结构。

现在说我们的目标为X86_64,调用约定为在%rax寄存器中返回返回值然后,此函数复制0(指令指针)中,并将地址%rax的值复制return_from_fork%rip(指令指针)中。

在其他平台上,ABI可能需要返回值才能进入堆栈。在这种情况下0,将其放在堆栈上。copy_thread是特定于目标的,但copy_process不是。

copy_threadX86_64 的实现您可以在第160行看到sp寄存器正在设置。在第182行,您可以看到%ax(它是%rax的子寄存器)被设置为0。

我希望这可以消除一些混乱。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

父进程有多个子进程,而两个子进程有一个子进程

将一个Android应用程序划分为两个进程,以便可以将一个进程用于位图操作,以避开OutOfMemoryErrors

在父进程中仅将一个写入流用于多个子进程

两个进程可以通过 ptrace 附加到同一个 PID

创建一个没有fork()的子进程

FFMPEG:一个动作的两个进程

如何确定我有一个带有两个线程的进程,还是两个进程?

Kubernetes-一个容器如何由两个进程启动并绑定到两个进程?

如果已知父进程,如何获取一个非常短的子进程的ID?

如何让非 root 父进程在 MacOS/X 下生成一个 root 子进程?

一个进程是否可以加载两个同名但版本不同的dll?

GitHub:两个不同的自定义域,一个用于组织,一个用于项目

如何制作一个分离的fork进程?

如何从 2 个不同的表中选择两个父级和一个子级

Github action 一个接一个运行两个进程

两个文本标签(一个用于条形,一个用于线形)

有两个表-一个用于选择,一个用于更新

两个cronjobs不起作用(一个启动一个进程,一个停止一个进程)

如何在两个CPU上分配一个进程

两个仅用于一个连接的插座

一个QWebEnginePage用于两个或多个QWebEngineView

如何在同一Shell脚本中将一个进程的PID传递给另一个进程?

如何强制2个Python子进程一个接一个地运行

git用于具有一个不同文件的两个应用程序

如何从其他两个创建一个向量,一个用于标签,另一个用于值?

一个进程如何阻止另一个进程(该进程产生)?

一个活动中如何将一个界面用于两个以上的后台Android任务?

一个Tomcat实例,用于两个域和两个webapp

以编程方式获取另一个进程的父pid?