GNU Octave 中的 Mkfifo

Mkfifo in GNU Octave

我还没有找到在线使用 mkfifo() 功能的完整示例。我可以像这样制作 fifo:

mkfifo("file",777)

但是当我 fopen() 这个文件时,Octave 挂起。从 mkfifo 对象创建、排队和出队字节的正确方法是什么?

我想在 Octave 中创建一个内存中的 fifo(在磁盘上也可以)并从同一个 Octave 脚本中读取和写入它。我的项目是 运行 实时的,所以我需要一个缓冲区,以便我可以从同一个 Octave 脚本中填充和排出。我搜索了一个结果为零的 fifo 库。即使只是创建一个向量并推入和弹出也能满足我的需要。我自己尝试过,但我 运行 陷入面向对象的编程设计问题,因为 Octave 不允许通过引用或指针传递。

有两个问题。第一:mkfifo 期望模式为以 10 为底的整数,如果你写“777”你认为是八进制,以 8 为底。第二:mkfifo 使用 umask 将权限修改为 (mode & ~umask) (参见 man 3)

例如:

fn=tempname
[ERR, MSG] = mkfifo (fn, base2dec("744", 8))
stat(fn)
fn = /tmp/oct-83UCBR
ERR = 0
MSG = 
ans =

  scalar structure containing the fields:

dev =  2053
ino =  3408172
mode =  4580
modestr = prwxr--r-- 
nlink =  1
uid =  1000
gid =  1000
rdev = 0
size = 0
atime =    1.4311e+09
mtime =    1.4311e+09
ctime =    1.4311e+09
blksize =  4096
blocks = 0

如您所见,modestr 现在是 prwxr--r-- 正如您对八进制 744 的期望

现在可以打开FIFO的一端了:

fid = fopen (fn, "r")

当然这会阻塞直到 fifo 的另一端连接。

fifo class 有效,但仅限于特定大小。 fifo 的最大字节数可以通过 运行:

找到
cat /proc/sys/fs/pipe-max-size
1048576

下面是我为内存中的 fifo 编写的代码。它相当粗糙,但效果很好:

1; % Prevent Octave from thinking that this is a function file

global fifoCount fifoSamples fifoFiles fifoFids fifoDataType
fifoSamples = zeros(0);
fifoCount = 0;
fifoFiles = cell(1);
fifoFids  = zeros(0);
fifoDataType = 'single';
fifoDataTypeSize = 4;
fifoMaxBytes = 1048576; % this is operating system enforced, changing here will not help

function [] = o_fifo_write(index, data)
    global fifoCount fifoSamples fifoFiles fifoFids fifoDataType

    wrcount = fwrite(fifoFids(index), data, fifoDataType);

    [sz,~] = size(data);

    fifoSamples(index) = fifoSamples(index) + sz;

    if( sz ~= wrcount )
        disp(sprintf('o_fifo_write was given %d samples but wrote %d', sz, wrcount));
    end

    if( ~iscolumn(data) )
        disp('data must be columnar in o_fifo_write');
    end
end

function [data] = o_fifo_read(index, count)
    global fifoCount fifoSamples fifoFiles fifoFids fifoDataType

    [data, rdcount] = fread(fifoFids(index), count, fifoDataType);

    [sz,~] = size(data);

    fifoSamples(index) = fifoSamples(index) - sz;

    if( sz ~= rdcount || sz ~= count )
        disp(sprintf('in o_fifo_read %d %d %d should all be the same', sz, rdcount, count));
    end
end

function [avail] = o_fifo_avail(index)
    global fifoCount fifoSamples fifoFiles fifoFids fifoDataType

    avail = fifoSamples(index);
end

function index = o_fifo_new()
    global fifoCount fifoSamples fifoFiles fifoFids fifoDataType

    fifoCount = fifoCount + 1;
    index = fifoCount;

    fifoSamples(index) = 0;
    fifoFiles{index} = tempname;
    [ERR, MSG] = mkfifo(fifoFiles{index}, base2dec('744',8));
    fifoFids(index)  = fopen(fifoFiles{index}, 'a+');
%     fcntl(fifoFids(index), F_SETFL, O_NONBLOCK);  % uncomment to avoid hangs when trying to overfill fifo
end


% ---- usage -----

txfifo = o_fifo_new();
disp(o_fifo_avail(txfifo));
o_fifo_write(txfifo, [1.243 pi 2*pi 4/3*pi]');
disp(o_fifo_avail(txfifo));
disp(o_fifo_read(txfifo, 4));
disp(o_fifo_avail(txfifo));