Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Named pipes linux

I made 2 threads, one has to read the other has to write. But i get undefined behaviour, sometimes i can read 1 line, sometimes 1000. It does not make alot of sense to me.

What i do is the following: 1. i create a fifo with mkfifo() in main.cpp 2. i start 2 threads, one that reads, the other writes. reader.cpp, writer.cpp

In those threads, every loop i open the fifo and i close it, because it wont work if i only do that once outside the loop, which i find also strange.

I have been looking for good examples but i found none.

My questions is simple, how can i make the fifo (Reader) wait for incoming data and read it when it is available. It should be able to run at 4Mhz.

I hope that somebody can help me out because this is the 3rd day i am breaking my head on this. If it matters im using Qt 4.8.

EDIT: I found the solution to my problem:

main.cpp

#include <QtCore/QCoreApplication>
#include "reader.h"
#include "writer.h"
#include <sys/types.h>  // mkfifo
#include <sys/stat.h>   // mkfifo
#include <fcntl.h>

int main(int argc, char *argv[]) {

    QCoreApplication a(argc, argv);

    int fifo = mkfifo("/tmp/fifo", S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);

    Reader r;
    Writer w;
    r.start();
    w.start();

    return a.exec();
}

writer.h

#ifndef WRITER_H
#define WRITER_H

#include <QThread>
#include <stdio.h>
#include <iostream>
#include <errno.h>
#include <string.h>
#include <fcntl.h>

class Writer : public QThread {

    Q_OBJECT

public:
    explicit Writer(QObject *parent = 0);

private:
    void run();

};

#endif // WRITER_H

reader.h

#ifndef READER_H
#define READER_H

#include <QThread>
#include <stdio.h>
#include <iostream>
#include <errno.h>
#include <string.h>
#include <fcntl.h>

class Reader : public QThread {

    Q_OBJECT

public:
    explicit Reader(QObject *parent = 0);

private:
    void run();

};

#endif // READER_H

writer.cpp

#include "writer.h"

char * phrase = "Stuff this in your pipe and smoke it\n";

using namespace std;

Writer::Writer(QObject *parent) : QThread(parent) {}

void Writer::run() {

    int num, fifo;
    if ((fifo = open("/tmp/fifo", O_WRONLY)) < 0) {
       printf("%s\n", strerror(errno));
       return;
    }
    while (true) {

        if ((num= write(fifo, phrase, strlen(phrase)+1)) < 0) {
            printf("ERROR: %s\n", strerror(errno));
        }
    }
    close(fifo);

}

reader.cpp

#include "reader.h"

using namespace std;

Reader::Reader(QObject *parent) : QThread(parent) {}

void Reader::run() {

    int num, fifo;
    char temp[38];
    if ((fifo = open("/tmp/fifo", O_RDONLY)) < 0) {
        printf("%s\n", strerror(errno));
        return;
    }
    while (true) {
        if ((num = read(fifo, temp, sizeof(temp))) < 0) {
            printf("%s\n", strerror(errno));
        }
        printf("In FIFO is %d %s \n", num, temp);
    }
    close(fifo);
}
like image 338
fonZ Avatar asked Sep 25 '12 11:09

fonZ


2 Answers

The basic read() and write() functions make no promise to read or write all available data.

You need something like:

int tot = 0;
while (tot < sizeof(temp))
{
    num = read(fifo, temp + tot, sizeof(temp) - tot);
    if (num < 0)
        break;
    tot += num;
}

And the same for write.

like image 65
Joel Klinghed Avatar answered Sep 28 '22 18:09

Joel Klinghed


I met the same problem when periodically opened and closed a single pipe. Re-creation of pipe (in reader process, when EOF is met) will be a solution.

like image 39
Pavel Ognev Avatar answered Sep 28 '22 17:09

Pavel Ognev