【问题标题】:Piping in C++ system calls failingC++ 系统调用中的管道失败
【发布时间】:2017-03-13 22:06:24
【问题描述】:

我有以下硬件问题:

阅读管道系统调用的手册页。已提供 2 个部分完成的计划来帮助 教你管子。

对于本实验,您将创建与实验 5(x-5、x/5 等)相同的输出。这次你使用 管道虽然。由于管道具有用于进程控制的内置机制,因此您只需要使用 2 个进程, 每个循环 5 次(而不是每次循环都创建一个新进程)。等待然后将不起作用 这个实验室。如果您需要帮助控制进程顺序,请尝试使用系统调用 sleep()。 以下是将打印到屏幕/终端的示例输出。

下面是一个示例输出:

x = 19530
迭代 1
子代:x = 19525
父代:x = 3905
迭代 2
子代:x = 3900
父代:x = 780
迭代 3
子代:x = 775
父代:x = 155
迭代 4
子代:x = 150
父代:x = 30
迭代 5
子代: x = 25
父级:x = 5

我的输出如下:

x = 19530

父读取失败
迭代 0
孩子,读取失败

我在下面有以下代码,但由于某种原因,我的系统调用在父进程和子进程的循环开始时一直返回负 1,我不明白为什么。谁能解释一下?我在 Ubuntu 16.04 linux 上。

// Pipe practice
#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
#include<sys/types.h>
#include<iostream>
#include<fcntl.h>
using namespace std;

int main()
{

    int x = 19530; // Original input
    size_t XSIZE = sizeof(x); // sizeo of the original input
    cout << "x = " << x << endl << endl; // first line of test output

    int child[2]; // for child pipe
    int parent[2]; // for parent pipe
    pid_t ID; // for fork() later
    ssize_t check; // ssize_t type for error checking

// opening the pipes, error handling
    if ((pipe(child)) < 0)
    { // child pipe
        cout << "Child has no pipe\n";
        return 1;
    }

    if ((pipe(parent)) < 0)
    { // parent pipe
        cout << "Parent has no pipe\n";
        return 1;
    }
// initial write to parent pipe
    if ((check = write(parent[1], &x, XSIZE)) <= 0)
    { // swap first 2 params q
        cout << "Pre-write failed\n";
        return 1;
    }

    ID = fork(); // forking, each fork will have two loops which iterate 5 times passing values back and forth
    if (ID < 0)
    {
        cout << "Fork failed \n"; // error handling for fork
        return 1;
    }

    else if (ID == 0)
    { // child does x = x-5
        for (int i = 0; i < 5; i++)
        {
            check = 0; // sets check to 0 each time to prevent error
            cout << "ITERATION " << i << endl;
            if ((check = read(parent[1], &x, XSIZE)) < 0)
            { // read the new value of x into x from parent[1]
                cout << "Child, read failed \n";
                return 1;
            }
            x = x - 5; // do the subtraction
            if ((check = write(child[1], &x, XSIZE)) < 0)
            { // write the new value into child[1] for piping for parent
                cout << "Child, write failed \n";
                return 1;
            }
            cout << "Child : x = " << x << endl;
        }
    }

    else
    { // parent does x = x/5
        for (int i = 0; i < 5; i++)
        {
            check = 0; // again, error prevention
            if ((check = read(child[1], &x, XSIZE)) < 0)
            { // read new x value from child[1]
                cout << "Parent read failed \n";
                return 1;
            }
            x = x / 5; // do division
            if ((check = write(parent[1], &x, XSIZE)) < 0)
            {
                cout << "Parent write failed \n"; // write new value to parent[1] for piping back to child
                return 1;
            }
            cout << "Parent : x = " << x << endl << endl;
        }
    }
    return 0;
}

编辑 现在我的输出如下:

x = 19530

迭代 1
子代:x = 19525
迭代 2
子代:x = 3900
迭代 3
父代:x = 3905

父级:x = 780

子级:x = 775
迭代 4
父级:x = 155

子级:x = 150
迭代 5父母:x = 30

孩子:x = 25
父母:x = 5

【问题讨论】:

  • 那里有很多系统调用,老霍斯。关心扩展哪些系统调用让您感到痛苦?
  • @user4581301 当然,我已将其编辑到我的问题中。但特别是循环内的调用。 read() 都返回 -1。我不明白为什么会这样。

标签: c++ linux system-calls


【解决方案1】:

您对管道的工作方式感到困惑。 pipe 返回两个文件描述符。第一个(索引 0)是读取端,第二个(索引 1)是写入端。

所以调用如下:

 check = read(parent[1], &x, XSIZE)

总是会失败,因为他们试图从写端读取。要修复,只需更改索引:

 check = read(parent[0], &x, XSIZE)

您需要在尝试使用 child[1] 阅读时执行相同操作

【讨论】:

  • 这解决了我的问题,但现在迭代计数已经满了,请参见上文。
  • 这解决了我的问题,但现在迭代计数已经满了,请参见上文。基本上,迭代计数与其他两个打印语句的打印顺序不同。我认为这是因为它不依赖于读写调用。知道如何使用它吗?
  • 没关系!我解决了!非常感谢您对pipe 的解释,我永远无法解决这个错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-29
  • 2015-02-21
  • 1970-01-01
  • 2021-08-09
  • 1970-01-01
相关资源
最近更新 更多