【问题标题】:What exactly happens with fork()?fork() 到底发生了什么?
【发布时间】:2012-02-21 14:08:00
【问题描述】:
int main(){

    char ch;

    fork();

    cin >> c;
}

在调用 fork() 之后,我应该有 2 个运行相同代码的确切进程。为什么在运行这个简单的例子之后,我要么被要求输入一个字符一次,要么两次?每次我运行这个程序时,系统不应该期待 2 个输入吗?

>./a.out 
a
>./a.out
a
b
>

【问题讨论】:

  • 这不是 C 代码,您使用的是 C++ 运算符,因此我们这些不会说 C++ 的人无法帮助您。
  • 第二个进程很有可能获得您在a 之后输入的\n 字符。尝试将ch 的类型更改为std::string,看看会发生什么。
  • 我刚做了,效果一样。
  • 另一个进程可能作为单独的“作业”运行,因为它不仅仅是一个线程,而是一个成熟的进程。见here。因此,尝试暂停活动作业 (Ctrl+Z),然后使用 jobs -l 列出作业并尝试将另一个作业带到前台 fg 2(而不是 2 使用另一个作业的 job_id)。

标签: c++ process fork


【解决方案1】:

您有两个进程同时从终端读取。任何人都可以猜测哪个进程获得输入。

  • 如果父进程首先获得输入,它会退出并将控制权返回给 shell。 (请注意,这实际上会导致相同情况的重复,shell 和子进程争夺输入。)
  • 如果子进程首先获得输入,则它会退出,但控制权不会返回到 shell,直到父进程退出。

如果你有两个进程从同一个终端读取,你不应该期望一致的行为。

【讨论】:

  • 注意第一种情况,第二个进程迟早会得到一行输入。在 shell 提示符之后,也许;在这种情况下,它似乎会从 shell 中窃取一行。
  • @James 我对此表示怀疑:父进程将关闭,子进程也会关闭,即使它没有收到它要请求的输入。
  • @Cookie503 父进程无法关闭子进程中打开的 fd。问题是这个 fd 指向哪里。如果它指向物理终端(实际设备),则该设备保持打开状态。如果它指向逻辑终端(窗口、远程登录等),则逻辑设备保持打开状态,但它指向的位置或它对未来 IO 的反应方式可能会发生变化,例如会话组已更改。
  • @Cookie503:“这实际上导致了相同情况的重复,shell 和子进程争夺输入。”
  • @Cookie503 是的。一旦你分叉,你就有两个打开的 fd 的“副本”。关闭一个只会关闭那个,而不是两个。
【解决方案2】:

当调用 fork() 时,操作系统通常会复制执行程序的整个内存空间(有点)。然后两个程序都运行。唯一不同的是,在“新”进程中,fork() 返回 0,而在“旧”进程中,它返回新进程的进程 ID。

只要求您输入一个输入的原因是其中一个程序正在后台运行。命令行 shell 一次只为一个进程执行 I/O。

【讨论】:

    【解决方案3】:

    fork() 创建一个子进程。

    但未确定哪个进程(在父进程和新出生的子进程中)获得 CPU 片。当两个进程都被阻止键盘输入时,孩子或父母都可以得到输入。 如果父级获得令牌,它将输入读取到其地址空间中定义的变量中并退出。而且孩子永远没有机会从输入中阅读。然后这个孤立的子进程将被“根”进程(pid = 1)采用。见ps 输出。

    在另一种情况下,孩子获取令牌并读取数据并退出,父母仍然活着,因此再次阻塞输入。

    【讨论】:

    • 即使父级退出,子级仍然应该属于同一个终端组,不是吗? (我不确定。我在这个级别工作已经有一段时间了。)在这种情况下,它迟早会得到一条线——它不再与已退出的父级竞争,而是与外壳竞争.
    【解决方案4】:

    在 fork() 之后包含一个 wait() 并尝试。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-04
      • 1970-01-01
      • 1970-01-01
      • 2012-08-29
      • 2021-03-18
      • 2018-08-25
      相关资源
      最近更新 更多