与2个管道进行过程同步

时间:2018-12-05 17:19:24

标签: c operating-system pipe

我正在做作业。我需要与一个孩子一起编写一个C程序,然后父亲和孩子必须打印出每一行的标准输出。 基本上我想要这样的东西:

I'm the father
I'm the child
I'm the father
I'm the child
I'm the father
I'm the child
...

只允许使用两个管道进行过程通信。 这是我写的:

int par_read = pipe1[0];
int par_write = pipe2[1];
int cld_read = pipe2[0];
int cld_write = pipe1[1];

char w;

if (fork()) // par
{
    close(cld_read);
    close(cld_write);

    while(1)
    {
        printf("I'm the father\n");

        if (write(par_write, &w, 1) == -1)
        {
            fprintf(stderr, "Error on par_write: %s\n", strerror(errno));
            exit(EXIT_FAILURE);
        }

        if (read(par_read, &w, 1) == -1)
        {
            fprintf(stderr, "Error on par_read: %s\n", strerror(errno));
            exit(EXIT_FAILURE);
        }
    }

}
else    // cld
{
    close(par_read);
    close(par_write);

    while(1)
    {
        if (read(cld_read, &w, 1) == -1)
        {
            fprintf(stderr, "Error on cld_read: %s\n", strerror(errno));
            exit(EXIT_FAILURE);
        }

        printf("I'm the child\n");

        if (write(cld_write, &w, 1) == -1)
        {
            fprintf(stderr, "Error on cld_write: %s\n", strerror(errno));
            exit(EXIT_FAILURE);
        }
    }

完整代码here。 问题在于这两个进程仅在几百行之后才可以正常工作。第一行充满了“我是父亲”。我还检查了行数:

$ ./ex > ex_out
$ cat ex_out | wc -l
40960
$ cat ex_out | uniq | wc - l
255

我做错了什么?

1 个答案:

答案 0 :(得分:2)

printf的输出可能不会立即写入,但会延迟直到缓冲区已满,因为stdio.hsetbuf(stdout, NULL);中的其他函数默认使用缓冲的输出。

尝试以下操作之一:

  • fork()之前添加fflush(stdout)以禁用缓冲或
  • printf之后使用write
  • 使用printf代替func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. var launchDashBoard = false let isUserLoggedIn = UserDefaults.standard.object(forKey: TAG_IS_USER_LOGGEDIN) as? Bool if isUserLoggedIn != nil { launchDashBoard = isUserLoggedIn! } if launchDashBoard { self.loadDashBoard() }else{ self.loadIntro() } return true } func loadHome(){ let storyboard = UIStoryboard(name: "Main", bundle: nil) let home = storyboard.instantiateViewController(withIdentifier: "dashboard") as! Dashboard let navigationController = UINavigationController(rootViewController: home) self.window?.rootViewController = navigationController } func loadLogin(_ viewController: UIViewController?){ let storyboard = UIStoryboard(name: "Main", bundle: nil) let home = storyboard.instantiateViewController(withIdentifier: "signIn") as! SignInVC home.previousViewController = viewController let navigationController = UINavigationController(rootViewController: home) self.window?.rootViewController = navigationController }