Pipe Named Fifo

7,434

You're only sending sizeof(float) bytes, which is only a substring of depthstring, whose actual size is strlen(depthstring)+1, not sizeof(float).

One thing you could do is eliminate the conversion to and from a string. Since both processes reading a named FIFO are on the same machine (no, FIFOs don't work over NFS), you can assume that a float is represented the same way in both processes. Therefore:

int talker(float depthright)
 {
   int fd;
   const char * myfifo = "/tmp/myfifo";

   mkfifo(myfifo, 0666);           /* create the FIFO (named pipe) */
   fd = open(myfifo, O_WRONLY/* | O_NONBLOCK*/);
   write(fd, &depthright, sizeof(depthright) );    

   /* close FIFO and delete fifo names from file system */
   close(fd);
   /* Don't delete the FIFO yet. The reader may not have opened
    * it yet.
    */

   return 0;
}

And then:

int main()
 {    
  int fd;
  const char * myfifo = "/tmp/myfifo";

    while(1)
    {
        //READ actual depth fifo
        fd = open(myfifo, O_RDONLY | O_NONBLOCK);
        float depth;
        read(fd, &depth, sizeof(depth));
        // Close read buffers now, since we open it with
        // each iteration. Waiting until after the loop
        // will result in only the last fd being closed.

        // Furthermore, there's a tight limit on how many
        // FDs you can have open at once.
        close(fd);    
        printf("\ndepth actual: %4.2f", depth);
        // Without this, libc may hold the output in a buffer
        // until the next float is read.
        fflush(stdout);
    }    
     /* NOT REACHED. The compiler may actually delete this code, since
      *  it can prove that this part will never be executed.
      */ 
     unlink(myfifo); 
     return 0;
  }
Share:
7,434

Related videos on Youtube

Calorified
Author by

Calorified

Updated on September 18, 2022

Comments

  • Calorified
    Calorified over 1 year

    I am implementing a named pipe to write and read data between two processes in cpp. The first process acquires a feature point from an image in real time while the second reads this feature point. It works fine but after a couple of data exchanges between the two processes, the talker code freezes. I know I need to close a pipe in order to be able to read from it and when I tried to close the file descriptor in the talker code outside a while loop, the listener file could not access new values of the variable. I can't find a way around it at the moment. What could I possibly be missing?

    Here's a MCVE of a function that writes a variable to a fifo file:

    #include <fcntl.h>
    #include <sys/stat.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <opencv2/opencv.hpp>
    
    /*Function Prototypes*/
    void(cv::Mat frame);    
    int(talker);
    
     int talker(float depthright)
     {
       int fd;
       char depthstring[1024];    
       sprintf(depthstring, "%4.4f", depthright);
    
       char * myfifo = "/tmp/myfifo";
    
       mkfifo(myfifo, 0666);           /* create the FIFO (named pipe) */
       fd = open(myfifo, O_WRONLY/* | O_NONBLOCK*/);       
       write(fd, depthstring, sizeof(depthright) );    
    
       /* close FIFO and delete fifo names from file system */
       close(fd);
       unlink(myfifo); 
    
       return 0;
    }
    
    int main( int argc, char* argv[] )
    {
     cv::Mat frame;
    //convert frame to grayscale, equalize histogram of grayed frame
    //detect faces and then detect eyes; acquire eye depth values as depthright
     talker(depthright);     //call fifo talker funtion
    return 0;
     }
    

    The listener is below:

    int main()
     {    
      int fd;
      char * myfifo = "/tmp/myfifo";
      char buf[1024];
    
        while(1)
        {
            //READ actual depth fifo
            fd = open(myfifo, O_RDONLY | O_NONBLOCK);
            read(fd, buf, MAX_BUF);
            float depth = strtof(buf, NULL);
            printf("\ndepth actual: %4.2f", depth);              
        }    
    
         //Close read buffers
         close(fd);
    
         return 0;
      }
    
    • G-Man Says 'Reinstate Monica'
      G-Man Says 'Reinstate Monica' almost 9 years
      We prefer Minimal, Complete, [and] Verifiable Examples (MCVEs) here (see also Short, Self-Contained, Correct (Compilable), Example (SSCCE).  Your example is neither complete nor compilable inasmuch it doesn’t show how talker() is invoked — specifically, how is it getting called more than once — so we have no way of understanding how “it works fine” for “a couple of data exchanges”, and, accordingly, no good way to understand how it “freezes”.
    • G-Man Says 'Reinstate Monica'
      G-Man Says 'Reinstate Monica' almost 9 years
      Please don’t post code that fails to do the bare minimum, obvious error checking.  Your talker() routine creates and destroys the FIFO, so obviously it doesn’t always exist.  And yet your main() code says fd = open(myfifo, O_RDONLY | O_NONBLOCK) without checking for error (ENOENT), and then calls read(fd, buf, MAX_BUF) with a fd that might be -1.  And, even if you got the FIFO open, since it’s open in non-blocking mode, read can return 0 to indicate that no data are available (or it can return a partial message).
    • Calorified
      Calorified almost 9 years
      How do you use ENOENT for error checking?
    • Throw Away Account
      Throw Away Account almost 9 years
      @Calorified, you check the return value of each system call. Read the man page (man 2 read for the read function, for example. Syscalls are in section 2 of the manual, while library calls are in section 3) to see which return value means an error for each system or library call. Usually, 0 = success, -1 = error. If the return value indicates an error, you can check the variable errno (defined in <errno.h>) to see why there's an error. If a file failed to open because it didn't exist, errno will equal ENOENT.
  • G-Man Says 'Reinstate Monica'
    G-Man Says 'Reinstate Monica' almost 9 years
    Actually, since fd is opened in O_NONBLOCK mode, read(fd, buf, MAX_BUF) will never block.  Even if it weren’t in O_NONBLOCK mode, it wouldn’t block until it receives MAX_BUF bytes; it would only block until it received one byte.
  • Calorified
    Calorified almost 9 years
    Furthermore, there's a tight limit on how many. What is this limit, please?
  • Throw Away Account
    Throw Away Account almost 9 years
    @G-Man, whoops, I didn't notice that he didn't have O_NONBLOCK commented out there.
  • Throw Away Account
    Throw Away Account almost 9 years
    @Calorified, the limit is defined somewhere in /proc/sys/, I can't remember where exactly. It can vary from system to system, and you can change it if you're root. There also seems to be a per-process setting you can modify with setrlimit (or ulimit -n from bash).