【问题标题】:Common lisp read from FIFO with timeoutCommon lisp 从 FIFO 读取超时
【发布时间】:2016-12-23 18:11:37
【问题描述】:

所以我有一些类似的代码

(let ((file (open cur-fifo :if-does-not-exist :create)))
  (format t "~A~%" (read-line file nil))
  (close file))

据我所知,这可以正常工作,但如果没有数据写入 cur-fifo,这将无限期阻塞。如果在约 0.1 秒左右无法读取数据,我希望读取超时并返回 NIL。

在 SBCL 1.1.18 上运行,在 64 位 Gentoo Linux 上运行

【问题讨论】:

    标签: common-lisp fifo sbcl


    【解决方案1】:

    FIFO model

    当你open 一个fifo 特殊设备(用于读取)时,系统调用阻塞除非有一个

    • fifo 已被(另一个)进程打开以进行写入或
    • 您将O_ASYNC 传递给open(2) - 除非您使用低级包sb-posix,否则您可能无法在实现中执行此操作

    当您成功打开 fifo 时,您的 read(2) 调用将阻塞,直到您的交易对手(打开 fifo 进行写入,这可能是同一个 lisp 进程)写入 那里有东西。

    普通的 Lisp

    您正在寻找的是listen(另请参阅with-open-file):

    (with-open-file (fifo "my-fifo" :if-does-not-exist :create)
      (when (or (listen fifo)
                (progn (sleep 0.1)
                       (listen fifo)))
        (format t "Read [~A]~%" (read-line fifo))))
    

    调试

    请注意,并非所有 CL 供应商都同样支持特殊设备处理。 如果上述方法不起作用,请用 REPL 做一些实验:打开 fifo,查看 listen 返回的内容,在此处写一些内容,查看 listen 现在报告的内容,等等。

    如果listen 仍然返回nil,即使您已经在管道中写入了一些内容,这可能意味着您的 CL 无法将该文件识别为特殊设备。您可能需要将一些特定于实现的参数传递给open,例如:buffering nil 或其他东西(试试(describe 'open))。

    【讨论】:

    • 如果这在代码中不明显,我正在读取的文件是一个 FIFO(即一个命名管道,使用 mkfifo 创建)
    • @KahrKunne:请查看我的编辑。请编辑您的问题以添加供应商详细信息。
    • 请注意,在尝试打开空 FIFO 时阻塞的是 OPEN,而不是 READ-LINE。我从来没有使用过 FIFO,所以我对它们并不熟悉,但我认为除了在单独的线程中读取它之外没有任何办法。
    • @jkiiski:这取决于 CL 实现(以及open 的实现特定选项)...
    • 使用供应商详细信息编辑问题。一些实验表明,如果没有任何东西连接到 FIFO,它确实是 OPEN 阻塞。再想一想,这并不奇怪——FIFO 与其说是真正的“文件”,不如说它是两个程序之间的连接;当管道没有连接到任何东西时,能够OPEN 管道是没有意义的。多线程现在并不适合我的程序流程,所以我将尝试不同的 IPC 方法,而不是 FIFO
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-24
    • 1970-01-01
    相关资源
    最近更新 更多