Mkfifo в GNU Octave

Я еще не нашел полный пример использования mkfifo() функционировать онлайн. Я могу сделать FIFO так:

mkfifo("file",777)

Но когда я fopen() этот файл, октава просто висит. Как правильно создавать, ставить в очередь и удалять байты из mkfifo объект?

Я хотел бы создать в Octave память fifo в памяти (на диске тоже хорошо), читать и писать ее из того же скрипта Octave. Мой проект работает в режиме реального времени, и поэтому мне нужен буфер, чтобы я мог заполнять и истощать тот же сценарий Octave. Я искал библиотеку fifo с нулевыми результатами. Даже простое создание вектора, нажатие и выталкивание будут соответствовать моим потребностям. Я попробовал это сам, но сталкиваюсь с проблемами проектирования объектно-ориентированного программирования, потому что Octave не позволяет передавать по ссылке или по указателям.

2 ответа

Решение

Класс fifo работает, но только до определенного размера. Максимальный размер в байтах 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));

Есть два вопроса. Во-первых: mkfifo ожидает mode как целое число с основанием 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 не соединится.

Другие вопросы по тегам