Ocaml:FIFO 读取不正确

标签 ocaml fifo mkfifo

好的,所以我正在使用 FIFO,并且我正在尝试构建一个小型库以在将来的程序中使用。

它应该能够创建一个命名管道,读取它并在其中写入。

我能够执行所有这些功能,但它无法正确读取。问题如下:

如果我说它应该读取大小为 10 个字符的缓冲区,那么只有当我写入超过 10 个字符时它才会正确打印,例如:

写入=“0123456789”->读取=“” 写入=“012345678910111213”->读取=“”,“10111213”

我对代码进行了更多尝试,并对异常“with”进行了小调试。 如果读取失败,就会存在此异常...它的作用是:关闭、等待、重新启动,最后返回 0(什么也没有)

然后我有一个 if 仅当字符数仅大于 0 时才正确,否则它将打印“空”

所以,发生的事情是: 写入=“0123456789”->读取=“空” 写入=“012345678910111213”->读取=“空”,“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 ();;

我想要一些光,它杀死了我......

谢谢

最佳答案

我认为您不需要非阻塞 IO,至少对于您的初始测试而言是如此。你实际上希望你的读者阻塞,直到有人准备好写作。但是,您也可能不想为每次读取重新打开管道,因为每次都会等待写入器。如果您确实想为每次读取重新打开管道,那么您也应该将其关闭。在我对代码的测试中,程序一直运行,直到用完所有可用的文件描述符。

编辑:如果您要求非阻塞 I/O,您的测试程序基本上会轮询(消耗 CPU 周期)等待输入显示。在开始看到任何数据之前,您会看到任意数量的 0 长度读取。这似乎就是你所报告的内容。如果您一直打开和关闭管道,并且在一段时间内没有读取器或写入器打开管道,则可能会丢失数据。

对于初始测试,您真正想要做的(我很确定)是为正常(阻塞)IO 打开管道一次,并使其在读取器中永远打开(直到测试结束)。这应该确保您看到所有数据。成功后您可以尝试一些变体。

作为附带评论,我认为许多人最终认为命名管道的语义过于挑剔。他们最终改用 Unix 域流套接字。

关于Ocaml:FIFO 读取不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13811583/

相关文章:

list - 在 ocaml 中构建整数列表

file-io - 为什么命名管道的只读打开会阻塞?

c++ - 如何在 Linux 中获取命名管道(FIFO)的剩余缓冲区大小

ruby - 在 Ruby 中创建命名管道

compiler-errors - OCaml 中的递归函数返回未绑定(bind)值错误

dictionary - 在 OCaml 中使用 Map.update

list - 如何在 OCaml 中将字符列表转换为字符串?

c - 如何在 C 中将一个字符中的两个数字相加?

c - 如果使用 IOCP 进行基本信号传输,传递给 CreateIoCompletionPort 的句柄是什么?

c - 客户端服务器实现的命名管道-服务器如何区分来自同一客户端的两个请求