Pipe Named Fifo
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;
}
Related videos on Youtube
Calorified
Updated on September 18, 2022Comments
-
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' almost 9 yearsWe 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' almost 9 yearsPlease 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 yourmain()
code saysfd = open(myfifo, O_RDONLY | O_NONBLOCK)
without checking for error (ENOENT), and then callsread(fd, buf, MAX_BUF)
with afd
that might be-1
. And, even if you got the FIFO open, since it’s open in non-blocking mode,read
can return0
to indicate that no data are available (or it can return a partial message). -
Calorified almost 9 yearsHow do you use ENOENT for error checking?
-
Throw Away Account almost 9 years@Calorified, you check the return value of each system call. Read the man page (
man 2 read
for theread
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 variableerrno
(defined in<errno.h>
) to see why there's an error. If a file failed to open because it didn't exist,errno
will equalENOENT
.
-
-
G-Man Says 'Reinstate Monica' almost 9 yearsActually, since
fd
is opened inO_NONBLOCK
mode,read(fd, buf, MAX_BUF)
will never block. Even if it weren’t inO_NONBLOCK
mode, it wouldn’t block until it receivesMAX_BUF
bytes; it would only block until it received one byte. -
Calorified almost 9 yearsFurthermore, there's a tight limit on how many. What is this limit, please?
-
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 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 withsetrlimit
(orulimit -n
from bash).