【问题标题】:Unix Processes PIPEUnix进程管道
【发布时间】:2016-04-24 12:42:26
【问题描述】:

我有以下任务要做:

乒乓球。两个进程将进行乒乓球比赛。 第一个进程将生成一个介于 5000 和 15000 之间的随机数,并将其发送给另一个进程。 此过程将减去一个随机值(介于 50 和 1000 之间)并将该数字发回, 进程之间的聊天将使用管道通道实现。 当值低于零时,游戏结束。 每个进程都会打印接收到的值。

所以我写了以下代码:

#include <stdio.h>
#include <time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
    int p[2];
    int a, n;

    pipe(p);
    int pid = fork();
    if (pid == 0)
    {
        int r = 0;
        srand(time(NULL));
        while ( r < 50 || r > 1000)
        {
            r = rand();
        }

        if ((a=read(p[0], &n, sizeof(int)))==-1)
            perror("Error read pipe:");

        printf("Process 2 recived %d\n", a);
        a = a - r;

        close(p[0]); close(p[1]);
    }
    else if (pid > 0)
    {
        srand(time(NULL));
        while ( n < 5000 || n > 15000) {
            n = rand();
        }

        while (n > 0)
        {
            printf("Process 1 recived %d\n", n);
            if (write(p[1], &n, sizeof(int))==-1) 
                perror("Error write pipe:");

            wait(0);
        }
    }
    return 0;
}

当它被执行时,它进入一个无限循环,打印"Process 1 received 4",我不知道为什么。

我创建了另一个管道,现在它正确打印了第一个接收到的值,但是从第二个过程开始,它发生了同样的事情

Process 1 recived 9083
Process 2 recived 4
Process 1 recived 4
and infinite loop

【问题讨论】:

  • 请不要更新问题中的代码。
  • 请注意,这两个随机数序列几乎可以保证是相同的(如果其中一个进程恰好在时间 T 执行 time(NULL) 而另一个在时间 T +1,但大多数情况下他们都会在时间 T 执行它)。一个简单的解决方法是使用time(NULL) + pid 代替time(NULL)

标签: c unix process


【解决方案1】:

我给你一个更正的程序,在 cmets 中有解释:

#include <stdio.h>
#include <time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
    int p[2];
    int p2[2];
    int a, n;

    pipe(p);
    pipe(p2);
    int pid = fork();
    if (pid == 0)
    {
        close(p[1]); // not writing in p, so closing p[1] immediately
        close(p2[0]); // not reading in p2, so closing p2[0] immediately

        srand(time(NULL));

        do {
            if ((a = read(p[0], &n, sizeof(int)))==-1)
                perror("Error read pipe:");

            if (a == 0) // nothing read means all processes have closed p[1]
                n = 0;
            else
                printf("Process 2 recived %d\n", n);

            int r = 50 + rand() % 950; // Only need one random number, and need one different each time
            n -= r;
            if (n > 0)
            {
                if(write(p2[1], &n, sizeof(int))==-1)
                    perror("Error write pipe:");
            }
        } while (n > 0);

        close(p[0]); close(p2[1]);
        exit(0); // or return(0) - as pointed out by Stian
    }
    else if (pid > 0)
    {
        close(p[0]); // not reading in p, so closing p[0] immediately
        close(p2[1]); // not writing in p2, so closing p2[1] immediately

        srand(time(NULL) + pid); // Adding pid so that processes each use a different seed
        n = rand() % 10000 + 5000; // Only need one random number

        while (n > 0)
        {
            if (write(p[1], &n, sizeof(int))==-1) 
                perror("Error write pipe:");

            // wait(0); Wrong use of wait()
            if ((a = read(p2[0], &n, sizeof(int)))==-1)
                perror("Error read pipe:");

            if (a == 0) // nothing read means all processes have closed p2[1]
                n = 0;
            else
                printf("Process 1 recived %d\n", n);

            int r = 50 + rand() % 950;
            n -= r;
        }

        close(p[1]); close(p2[0]);
    }

    wait(NULL); // Better use of wait(). Still not perfect, you need to check return value.
    return 0;
}

【讨论】:

  • 子进程完成后应该调用_exit,否则会等待
  • @StianSkjelstad:由于孩子没有自己的孩子,wait() 将立即返回 -1errno == EAGAIN,除了(无害的)系统之外,这不是问题拨打了本可以避免的电话。
  • @JonathanLeffler 确实,不是错误,只是不必要的调用,我不喜欢它们...
  • 你的代码从父进程中的n中减去随机值,为什么?
  • @gamamen2 这就是我在你的作业中所理解的,但如果你不同意我的观点,当然不要这样做。重要的是您要了解如何使用这两个管道,以便进程可以通信。按照你的想法调整我的答案。
【解决方案2】:

你需要两个管道。每个方向一个

【讨论】:

  • 像是给孩子的烟斗和给父亲的烟斗?
  • 管道是单向数据流。一个管道应该由父级写入并由子级读取,第二个管道则相反
  • 我又做了一个管道,但仍然出现无限循环,你能看看编辑吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-01
  • 2013-08-15
  • 2011-08-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多