问题
I'm working with named pipes (fifo) to communicate between python and MATLAB. The MATLAB code to read from the pipe is functional but it hangs if nothing has been written to the fifo. I would prefer it would gracefully timeout when no data is available.
If the pipe exists (in bash):
$ mkfifo pipe_read
but has no data the MATLAB open command:
>> fid = fopen('pipe_read', 'r');
hangs until data is available:
$ echo "test data" >> pipe_read
Rather than blocking forever I would like fopen
to return a file-id that indicates an error (i.e. similar to -1 as it does when the file does not exist) if there is no data available.
Could there be a solution similar to the asynchronous reads available in the commands for writing and reading to serial instruments: http://www.mathworks.com/help/matlab/ref/readasync.html ?
Or possibly fopen
could be embedded into a matlab timer object that enables a timeout?
This has been asked before but without an answer: Matlab read from named pipe (fifo)
回答1:
I'm pretty sure the issue is not actually with Matlab's fopen
, but the underlying open
system call. Generally, the use of a pipe or FIFO only makes sense when there exists both a reader and a writer, and so, by default, open(2)
will block until the other end of the FIFO has been opened as well.
I don't think it will work to embed the fopen
call in any other Matlab object. As far as I'm aware, the only way to circumvent this is to write your own version of fopen
, as a specialized Mex function. In this case, you can make a call to open(2)
with the O_NONBLOCK
flag or
'd with whatever read/write flag you'd like. But digging around in man 2 open
, under the ERRORS
section, you can see that ENXIO
is returned if "O_NONBLOCK
and O_WRONLY
are set, the file is a FIFO, and no process has it open for reading". That means you need to make sure that Python has opened the FIFO for reading before Matlab tries to open for writing (or vice versa).
As a final point, keep in mind that Matlab's fopen
returns a handle to a file descriptor. Your Mex function should probably mirror that, so you can pass it around to fread
/fscanf
/etc without issues.
回答2:
In Linux, a system call with timeout
would do the trick. For example:
timeout = 5; % timeout in seconds
pipe = 'pipe_read';
[exit_code,str] = system(sprintf('timeout %ds cat %s', timeout, pipe));
switch(exit_code);
case 0; doSomething(str); % found data
case 124; doTimeout(); % timedout
end
MacOS has gtimeout
which I assume is similar.
来源:https://stackoverflow.com/questions/25583670/matlab-read-from-fifo-with-fopen-timeout