好的,所以我正在使用FIFO,我正在尝试构建一个小型库,以便在将来的程序中使用。
它应该能够创建一个命名管道,读取并写入其中。
我能够完成所有这些功能,但它无法正确读取。问题如下:
如果我说它应该是读取大小为10个字符的缓冲区,那么只有在我写了超过10个字符时它才能正确打印,例如:
write =“0123456789” - >读=“” write =“012345678910111213” - > reads =“”,“10111213”
我尝试了更多代码,并在异常“with”上进行了一次小调试。 如果读取失败,则存在此异常...它的作用是:解除,等待,重启,最后返回0(无)
然后我有一个if,只有当字符数大于0时才会正确,否则会打印“空”
所以,发生的事情是: write =“0123456789” - > reads =“empty” write =“012345678910111213” - > reads =“empty”,“10111213”
所以在前10个字符中,他说读取失败了,但是他将它们从FIFO中删除了。为什么呢?
对不起,如果有点混乱。这是代码:
计划阅读:
let fifo_name = "la_fila";;
(*define the length of the buffer*)
let buflen = 2;;
let main () =
Printf.printf "Hello! Any readers? ...\n";
flush stdout;
while true do
print_string ("I've read \"" ^ bufferRead fifo_name buflen ^ "\" from the fifo!\n");
flush stdout
done;;
(* run it *)
bufferCreate fifo_name;;
let _ = main ();;
这是BufferLibrary:
(* Buffer Functions *)
let bufferCreate name =
try Unix.mkfifo name 0o664 with
Unix.Unix_error(n,f,arg) -> Printf.printf "%s(%s) : %s\n" f arg
(Unix.error_message n);;
let bufferRead name size =
let frd = Unix.openfile name [Unix.O_RDONLY;Unix.O_NONBLOCK] 0o644 in
let rec aux () =
let nothing = flush_all ()
in
let buffer = String.create size in
let n = try (Unix.read frd buffer 0 size) with
Unix.Unix_error(n,f,arg) -> begin (); aux (); 0; end
in
if n > 0 then String.sub buffer 0 n else "empty"
in
aux ();;
(*(String.sub buffer 0 n)*)
let bufferWrite name str =
let length = String.length str in
let fwr = Unix.openfile name [Unix.O_WRONLY] 0o644 in
Unix.write fwr str 0 length;;
修改
open Buffers;;
let fifo_name = "la_fila";;
let main () =
Printf.printf "CUCKOO! any consumer down there? ...\n";
flush stdout;
Printf.printf "cuckoo! Here comes a consumer! \n";
let rec reget () =
Printf.printf "-type something for it\n";
flush stdout;
let str = read_line() (*here it blocks*) in
bufferWrite fifo_name str;
reget () in
reget ();;
(* run it *)
bufferCreate fifo_name;;
main ();;
我会喜欢一些光,它会杀了我......
谢谢
答案 0 :(得分:3)
我认为你不想要非阻塞IO,至少不是你的初始测试。你实际上希望你的读者阻止,直到有人准备写。但是你也可能不想为每次读取重新打开管道,因为每次都会等待作者。如果您确实想要为每次读取重新打开管道,那么您也应该关闭它。在我对代码的测试中,程序会一直运行,直到它耗尽所有可用的文件描述符。
编辑:如果您要求非阻塞I / O,您的测试程序基本上是轮询(烧毁CPU周期),等待输入显示。在开始查看任何数据之前,您将看到一些任意数量的0长度读取。这似乎就是你所报道的。如果在没有读取器或写入器打开管道的时间段内,您可能会一直打开和关闭管道。
你真正想要做的初步测试(我很确定)是为正常(阻塞)IO打开一次管道并在读者中永远打开它(直到测试结束)。这应该确保你看到所有的数据。您可以尝试使用后的变体。
作为旁注,我认为很多人最终都认为命名管道的语义太过于挑剔。他们最终使用的是Unix域流套接字。