fork() 不并行运行

2024-05-03

我对编程过程很陌生,我的基本程序并没有真正按照我的预期工作。我在 Oracle VM 上的 Ubuntu 18.04 上运行此代码。

这是代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>


int main()
{
   printf("--beginning of program\n");

    int counter = 0;
    pid_t pid = fork();

    if (pid == 0)
    {
        // child process
        int i = 0;
        for (; i < 5; ++i)
        {
            printf("child process: counter=%d\n", ++counter);
        }
    }
    else if (pid > 0)
    {
        // parent process
        int j = 0;
        for (; j < 5; ++j)
        {
            printf("parent process: counter=%d\n", ++counter);
        }
    }
    else
    {
        // fork failed
        printf("fork() failed!\n");
        return 1;
    }

    printf("--end of program--\n");

    return 0;
}

这是我总是得到的结果:

--beginning of program
parent process: counter=1
parent process: counter=2
parent process: counter=3
parent process: counter=4
parent process: counter=5
--end of program--
--beginning of program
child process: counter=1
child process: counter=2
child process: counter=3
child process: counter=4
child process: counter=5
--end of program--

这是我编译程序的命令:

gcc main.c -o main

谢谢你!


打印 5 个字符串发生得太快,父进程在子进程开始其循环之前就完成了其循环。尝试更多循环,500 Works For Me™。

请注意,父母和孩子do not共享内存。孩子将继承counter = 0但不分享counter与其父级。他们都会独立计数。协调流程需要更先进的技术。


其他事宜。

你得到了--end of program--两次因为子进程没有退出。一旦完成循环,它就会继续运行其余的代码。添加一个exit(0)给孩子。

如果您想在子进程完成后声明“结束”,请使用wait https://stackoverflow.com/questions/23709888/how-to-use-wait-in-c等待您的子进程完成。

    waitpid(pid, NULL, 0);
    printf("--end of program--\n");

你可以得到--beginning of program如果输出到管道或文件,则两次,例如./program | cat or ./program > output。由于 I/O 缓冲。

写入磁盘很慢。不是在打印后立即写入所有内容,而是将其写入内存,然后写入磁盘。缓冲共有三种常见类型:无缓冲、行缓冲和块缓冲。哪种类型的缓冲取决于您要写入的内容。

无缓冲就是它所说的,你称之为printf并已发送。stderr通常是无缓冲的,因为在错误发生时看到错误很重要。

行缓冲将输出存储在内存中,直到看到换行符,然后发送整行。发送它称为“刷新缓冲区”。stdout通常是行缓冲的。这是终端在纸上打印一行的回溯。

这可能会导致奇怪的结果。

fprintf(stdout, "First");
fprintf(stderr, "Second");
fprintf(stdout, "Third\n");

Because stdout是行缓冲区,结果将是SecondFirstThird.

Unless stdout or stderr不会去航站楼。如果它们要访问管道或文件,则它们可能是块缓冲的。这意味着输出将被缓冲,直到看到一定量的数据,然后它将被刷新。

在你的代码中,如果stdout是行缓冲的printf("--beginning of program\n");立即被冲洗。但如果stdout被重定向到一个文件,它是块缓冲的并且不会立即写入。"--beginning of program\n"仍然在stdout的缓冲区。当您分叉时,子进程会获取该缓冲区的副本并添加到其中。所以孩子和父母都打印"--beginning of program\n".

您可以通过在分叉之前显式刷新标准输出缓冲区来解决此问题fflush https://en.cppreference.com/w/c/io/fflush.

    printf("--beginning of program\n");
    fflush(stdout);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

fork() 不并行运行 的相关文章

随机推荐

  • 将项目子文件夹中的文件放入输出目录

    我想在 C 项目中创建一个文件夹来包含一些配置文件 但是 我不希望将这些文件复制到bin Release MyFolder 我宁愿将它们复制到bin Release直接地 我认为这可以通过拥有一个 虚拟 文件夹 例如解决方案文件夹 来实现
  • 当我删除 @synthesize 语句时出现编译器错误“使用未声明的标识符”

    在最新的 LLVM 版本中 综合属性的要求已被删除 因此我能够删除我所有的 synthesize声明 除了以下声明NSFetchedResultsController 有谁知道为什么当我删除时编译器会警告我 synthesize fetch
  • Rails:如何将替代 Accept: content-types 视为 JSON?

    到目前为止我已经找到了两种方法request format json 在 Rails 中为 true 即传入请求被视为 JSON 一种是如果您请求资源并以 json另一个是如果您提供标头Accept application json在你的要
  • 在java中使用自定义比较器在数组中搜索

    为什么总是返回49999无论strToSearch变量保持 即使使用 clank 搜索变量 它也会返回相同的结果 我是不是错过了什么 String arr new String 100000 String strToSearch 12 fo
  • 可以在delphi数据集中创建一个假数据字段吗?

    我想在 DataSet 不是 ClientDataSet 中创建一个 假 数据字段 该字段不应存储在数据库中 它不是计算字段 应允许用户输入输入数据 该字段具有业务逻辑含义 因此用户更新其值后应该更新其他字段 使用 OnFieldChang
  • 无法在 GAE 应用程序中使用 google-cloud

    我的 Google App Engine 应用程序中的以下行 webapp py 无法导入谷歌云 https googlecloudplatform github io google cloud python 图书馆 from google
  • 如何使用 web.xml 阻止 IP 地址?

    如何通过 web xml 上的某些配置来阻止 IP 地址 我需要过滤器吗 我该如何实施 你不能纯粹通过配置来做到这一点web xml 不 不过 Servlet 过滤器是实现此类功能的好地方 The Filter接口提供HttpServlet
  • 在巨大的数据集上创建独特的节点和关系 NEO4J

    我的问题与这个非常相似 如何通过neo4j中导入的csv文件创建独特的节点和关系 https stackoverflow com questions 25090255 how to create unique nodes and relat
  • 如何动态更改表格单元格文本颜色?

    我需要一个解决方案来通过 javascript 动态更改表格单元格的文本颜色 文本可以是以下颜色 蓝色 绿色 红色和黑色 表示例
  • 200 响应但未返回 JSON 数据 - Restangular 问题?

    使用 reangular 和存根 hub api 我可以在 Firefox RestClient 上点击此 API 并获取包含所有 JSON 数据的响应正文 但在我的应用程序中 我收到 200 但没有响应正文 内容长度甚至表明存在某些内容
  • java小程序paint方法麻烦

    在代码中我正在调用repaint 方法来自init 方法 但输出并不符合我的预期 我打了电话repaint 方法 10 次但它调用paint 仅一次 参见 O P 的屏幕截图 我有什么错误吗 请帮我 谢谢 code import java
  • 更改用户名 Github “您必须验证您的电子邮件地址” git Push 上出现 403 错误

    我最近在 github 上更改了我的用户名 以便所有内容都重定向到我用户名上的新 URL 我通过命令行收到此错误git push 您必须验证您的电子邮件地址 致命 请求 URL 返回错误 403 但是 github 不允许我在帐户 gt 设
  • 如何使用 Openpyxl 获取当前行索引

    我编写了一个 Python 脚本 从 json 文件中提取一些字符串值 将它们存储在某个字典中 并使用我第一次使用的 Openpyxl 将它们填充到 xlsx 文件中 简而言之 它看起来像这样 WORKBOOK Workbook WORKS
  • 如何用C#替换PDF中的文本?

    我在这里看到了很多解决方案 但没有一个是明确或好的答案 这是我的简单问题 希望得到直接答案 我有一个 PDF 文件 模板 其创建的文本如下 名字 姓氏 地址 电话号码 是否可以使用 C 代码将这些模板替换为我选择的文本 没有字段 没有其他复
  • 如何让不显眼的 jquery 远程验证器执行异步..?

    在 MVC3 应用程序中 使用 jquery 不显眼的验证以及带有 远程 验证器的视图 模型 我试图在远程验证期间以及将有效表单提交到服务器时禁用提交按钮并显示等待图标 我以为我已经搞定了 直到我在 IE8 中尝试了它 问题是 当表单无效时
  • 什么是 Google API 发现?

    我无法理解 Google 产品 服务中使用的 API 发现 概念 以下是一些使用上述发现服务访问 Google Cloud Vision 的 Python 代码 from googleapiclient discovery import b
  • 使用 OpenCV 裁剪黑色边缘

    我认为这应该是一个很简单的问题 但我找不到解决方案或有效的关键字进行搜索 我只有这个图像 黑边没有用 所以我想把它们剪掉 只留下 Windows 图标 和蓝色背景 我不想计算Windows图标的坐标和大小 GIMP 和 Photoshop
  • 在 VBScript 中导航 XML 节点(对于 Dummy)

    我正在尝试编写一个脚本来为我操作 xml 文件中的一些数据 我对 VBScript 还很陌生 但有 VB NET 和 VBA 背景 所以我觉得我知道自己在做什么 我认为可能有更好的方法来导航文件 而不是对每一行进行大量调用 InStr 或类
  • 自定义 Javascript EventManager - 请帮我完成

    我正在尝试创建一个自定义 javascript EventManager 类 我采用了 Grant Skinner 在他的 essel js 框架中使用的格式来创建类 并且需要坚持使用它 在这一点上我真的迷失了 我认为 至少在概念意义上 我
  • fork() 不并行运行

    我对编程过程很陌生 我的基本程序并没有真正按照我的预期工作 我在 Oracle VM 上的 Ubuntu 18 04 上运行此代码 这是代码 include