【问题标题】:What is a child process? And how do I start it? (Linux, C)什么是子进程?我该如何开始呢? (Linux, C)
【发布时间】:2014-10-20 17:19:40
【问题描述】:

我对 C 完全不熟悉。

如何启动子进程?这个子进程将通过调用execve() 来执行指定的命令。命令执行后会尝试在环境变量PATH指定的文件目录中搜索 发现为可执行文件。

到目前为止我已经这样做了:

//Do commands 
pid_t childId;

// Fork the child process
child_id = safefork.c(); //can't use fork();

safefork.c

导师提供的代码;不要诅咒信使!

#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/errno.h>
extern int errno;
#define MAX_PROCESSES 6
static int n_processes(void)
{
    return system("exit `/bin/ps | /store/bin/wc -l`")/256;
}
pid_t safefork(void)
{
    static int n_initial = -1;
    if (n_initial == -1) /* Første gang funksjonen kalles: */
        n_initial = n_processes();
    else if (n_processes() >= n_initial+MAX_PROCESSES) {
        sleep(2);
        errno = EAGAIN;
        return (pid_t)-1;
    }
    return fork();
}

【问题讨论】:

  • 为什么不能使用fork??我认为除了fork() 之外,没有其他方法可以分叉子进程
  • 欢迎来到 Stack Overflow。请尽快阅读About 页面。符号 safefork.c() 在 C 中并不常见;我可以设计一种结构类型来使它工作,但这可能不是你的意思。 “不能使用fork()”是什么意思?主要的替代机制是vfork(),这是fork()的一个非常受限的变体(不要使用它);或者你可以使用posix_spawn()posix_spawnp()——它们是非常复杂的替代方案。我认为没有其他选择。分叉后,您可以使用execvp() 而不是execve() - 它会为您进行路径搜索。
  • 我们得到了另一个名为 safefork 的文件 :) 我们不允许使用 fork,只能使用已经给出的 safefork
  • 好的;这很好奇。大概,你有一个标题safefork.h,它声明了你应该使用的任何函数(可能是extern int safefork(void);),还有一个文件safefork.c,它做了一些事情来环绕fork()或其他什么。 '这很奇怪:我不认为 fork() 是一个危险的功能。我很想知道“安全叉子”的作用,但我怀疑它是否比标准叉子功能更安全。 (我想它可以在调用 fork() 之前执行一些类似 fflush(0) 的操作,或者在 fork() 失败时执行错误退出,但这是在挑战极限。)
  • 'safefork()` 的代码令人憎恶。它运行一个运行 pswc 的 shell,以找出您当前正在运行的进程数,如果您不能执行 fork(),则进入睡眠 2 秒,因为有太多(超过 6 ,包括safefork() 正在运行的3 个!)然后返回“我失败了”。有人需要他们的头脑注意(不,那不是你;它是代码的作者)。哦,extern int errno; 不正确;声明errno 的唯一安全方法是通过#include &lt;errno.h&gt;。这个错误给老师打负分。

标签: c linux process pid child-process


【解决方案1】:

修复您的代码

在您的代码中,获取一致拼写的变量名称(child_idchildId 不同)。

pid_t child_id = simplefork();
if (child_id < 0)
{
    ...handle error...
}
else if (child_id == 0)
{
    ...do childish code - execve() etc...
}
else
{
    ...do parental code - waitpid() etc...
}

请注意,您可以使用的simplefork() 函数中的fork() 调用负责创建新进程。仅此而已;除了第一个进程之外,所有进程都是这样处理的。


为什么不fork()

“不能使用fork()”是什么意思?主要的替代机制是vfork(),这是fork()的一个非常受限的变体(不要使用它);或者你可以使用posix_spawn()posix_spawnp()——它们是非常复杂的替代方案。我认为没有其他选择。

分叉后,您也许可以使用execvp() 而不是execve() — 它会为您进行路径搜索。当然,除非练习的目的是根据execve() 来实现execvp()

您的代码使用符号safefork.c(),但这在C 中通常不正确;我可以设计一种结构类型让它工作,但这可能不是你的意思。

我们得到了另一个名为safefork.c 的文件——我们不能使用fork,只能使用已经给出的safefork

[…在发布代码之前]

好的;这很好奇。大概,你有一个标题safefork.h,它声明了你应该使用的任何函数(可能是extern pid_t safefork(void);),还有一个文件safefork.c,它做了一些事情来环绕fork()。 '这很奇怪:我不认为 fork() 是一个危险的函数。我很想知道“安全叉子”的作用,但我怀疑它是否比标准叉子功能更安全。 (我想它可以在调用 fork() 之前执行 fflush(0) 之类的操作,或者在 fork() 失败时执行错误退出,但这是在挑战极限。)

[……代码发布后]

safefork() 代码的批评,我完全认识到这不是您自己的代码,而是提供给您使用的代码。

safefork() 的代码令人憎恶。它通过system() 运行一个shell,该shell 运行pswc,以找出您当前正在运行的进程数,如果您不能执行fork(),则进入休眠2 秒,因为有太多正在运行的进程(超过 6 个,可能包括 safefork() 正在运行的 3 个!),然后返回“我失败了”。有人需要他们的头脑注意(不,那不是你;它是代码的作者)。

哦,extern int errno; 不正确;声明errno 的唯一安全方法是通过#include &lt;errno.h&gt;。那个错误给老师打负分。 #include &lt;sys/errno.h&gt; 不是一个好主意; #include &lt;sys/types.h&gt; 在现代 POSIX 中并不经常需要——无论如何从 POSIX 2008 开始;在此之前可能没有必要)。在safefork.h 标头的上下文中,使其独立确实需要#include &lt;sys/types.h&gt;

即使假设safefork() 是一个好主意(它不是),它也应该按如下所示实现。

safefork.h

#ifndef SAFEFORK_H_INCLUDED
#define SAFEFORK_H_INCLUDED

#include <sys/types.h>   // pid_t
extern pid_t safefork(void);

#endif

safefork.c

#include "safefork.h"
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>

#define MAX_PROCESSES 6

static int n_processes(void)
{
    return system("exit `/bin/ps | /store/bin/wc -l`") / 256;
}

pid_t safefork(void)
{
    static int n_initial = -1;
    if (n_initial == -1)
        n_initial = n_processes();
    else if (n_processes() >= n_initial+MAX_PROCESSES)
    {
        errno = EAGAIN;
        return (pid_t)-1;
    }
    return fork();
}

【讨论】:

  • 这是一项大学作业,其中安全叉作为附件提供。我们必须用 safefork 替换 fork,所以进程不应该乱跑——而且我们必须使用 execv
  • 好的;我修改了答案以使其结构更清晰。第一部分是关于如何修复/编写代码。其余部分是simplefork() 代码的解构。您可以忽略其余部分;第一部分包含您需要使用的信息。
猜你喜欢
  • 2010-10-08
  • 1970-01-01
  • 1970-01-01
  • 2020-11-03
  • 1970-01-01
  • 2010-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多