叉子、管道和锉刀操作

Fork, pipe and file operations

本文关键字:操作 管道 叉子      更新时间:2023-10-16

我有一个管道,可以在派生程序中的两个进程之间进行通信。它是用pipe()调用创建的-http://linux.die.net/man/2/pipe。在我想执行一些文件操作之前,一切都很顺利。

此代码有效:

pipe.writeBuffer(message.c_str(), message.length());
ofstream file;
file.open(name.c_str(), ios::app);
file << "stringData";    // put some data to file (many times)

但这不是:

ofstream file;
file.open(name.c_str(), ios::app);
pipe.writeBuffer(message.c_str(), message.length());
file << "stringData";    // put some data to file (many times)

在第二个例子中,没有"file<<someStream"的影响——我得到的是空文件。这是怎么回事?文件描述符有问题吗?管道使用fd[0]-输入和fd[1]-输出。也许fstream也使用相同的输出文件处理程序?

以下是"工作"示例:http://pastebin.com/gJ4PbHvy

#include <sys/types.h>
#include <cstdlib>
#include <unistd.h>
#include <iostream>
#include <fstream>
#define maxSize 64
using namespace std;
class Pipe
{
    public:
        Pipe()
        {
            pipe(fdesc);
        }
        ~Pipe() {}
        void writeBuffer(const char* message, size_t length)
        {
            close(fdesc[0]);
            write(fdesc[1], message, length);
        }
        void readBuffer()
        {
            char buffer[maxSize];
            close(fdesc[1]);
            size_t result = read(fdesc[0], &buffer, sizeof(buffer));
            cout << buffer << endl;
        }
    private:
        int fdesc[2];
};
class Writer
{
    public:
        Writer(Pipe &obj)
        {
            pipe = obj;
        }
        ~Writer()
        {}
        void entry()
        {
            std::string name = "./myFile";
            ofstream file;
            file.open(name.c_str(), ios::app);
            std::string message = "hello world";
            pipe.writeBuffer(message.c_str(), message.length()+1);
            if (file.is_open())
            {
                file << "Hello World!" << endl;
                file.close();
            }
            else
            {
                perror("file.is_open()");
            }
            sleep(1);
        }
    private:
        Pipe pipe;
};

class Reader
{
    public:
        Reader(Pipe &obj)
        {
            pipe = obj;
        }
        ~Reader()
        {}

        void entry()
        {
            pipe.readBuffer();
            sleep(1);
        }
     private:
        Pipe pipe;
};
int main(int argc, char *argv[])
{
    Pipe pipe;
    Reader reader(pipe);
    Writer writer(pipe);
    pid_t pid = fork();
    if (pid == -1) 
    {
        perror("fork");
        exit(EXIT_FAILURE);
    }
    if (pid == 0) 
    {    
        // child process
        while(1)
            reader.entry();
    } 
    else 
    {
        // parent process
        while(1)
            writer.entry();
    }
}

对于发布的程序,所描述的获取空文件的问题是不可再现的,因为每次运行时,它都会将一行Hello World!写入myFile,但这仍然显示了错误,因为您打算每秒写入一行。原因是writeBuffer()中的close(fdesc[0]):虽然在编写器过程中关闭管道的读取端一次是正确的,但每次调用writeBuffer()时都这样做是不正确的,因为在第一个close()之后,文件描述符可能(在目前的情况下,确实)被另一个文件(这里是文件ofstream file)重用,这是在它关闭而不是(已经关闭的)管道之后,从而不能将任何内容写入文件中。修复:安排你的程序只关闭管道末端一次,例如通过更改

            close(fdesc[0]);

            if (0 <= fdesc[0]) close(fdesc[0]), fdesc[0] = -1;