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 не соединится.