owa*_*agh 7 sbcl common-lisp shared-memory memory-mapped-files
正如问题所说的那样.我想使用共享内存在两个lisp进程之间进行通信.有关如何做到这一点的任何指示?
我可以在clozure中看到一些关于这样做的教程: -
http://ccl.clozure.com/manual/chapter4.7.html
有人能指点我用类似的库来用sbcl做这个吗?
对于可移植实现,您可能希望使用该osicat库,该库为osicat-posix包中的许多POSIX调用提供CFFI包装.
在http://wandrian.net/2012-04-07-1352-mmap-files-in-lisp.html(由Nicolas Martyanoff撰写)中有一篇非常好的短篇文章,其中包含使用它的代码.
为了保留这一点,我主要从那里引用:
映射文件是通过打开文件
osicat-posix:open,读取文件大小fstat,然后调用来完成的mmap.一旦文件被映射,我们可以关闭文件描述符,不再需要它了.
(defun mmap-file (path)
(let ((fd (osicat-posix:open path (logior osicat-posix:o-rdonly))))
(unwind-protect
(let* ((size (osicat-posix:stat-size (osicat-posix:fstat fd)))
(addr (osicat-posix:mmap (cffi:null-pointer) size
(logior osicat-posix:prot-read)
(logior osicat-posix:map-private)
fd 0)))
(values addr size))
(osicat-posix:close fd))))
Run Code Online (Sandbox Code Playgroud)
mmap-file函数返回两个值:内存映射的地址及其大小.
取消映射这块内存就完成了
osicat-posix:munmap.让我们添加一个宏来安全地映射和取消映射文件:
(defmacro with-mmapped-file ((file addr size) &body body)
(let ((original-addr (gensym "ADDR-"))
(original-size (gensym "SIZE-")))
`(multiple-value-bind (,addr ,size)
(mmap-file ,file)
(let ((,original-addr ,addr)
(,original-size ,size))
(unwind-protect
(progn ,@body)
(osicat-posix:munmap ,original-addr ,original-size))))))
Run Code Online (Sandbox Code Playgroud)
此宏mmap是给定文件,并将两个给定变量绑定到其地址和大小.然后,您可以使用计算地址指针cffi:inc-pointer并访问文件内容cffi:mem-aref.您可能希望围绕此构建自己的包装器来表示文件的格式(例如,UTF-8中的纯文本).
(与上面链接的帖子相比,我删除了包含osicat-posix:munmap到具有完全相同签名和效果的另一个函数,因为它对我来说似乎是多余的.)
有sbcl捆绑的低级mmap函数:
CL-USER> (apropos "MMAP")
SB-POSIX:MMAP (fbound)
; No value
CL-USER> (describe 'sb-posix:mmap)
SB-POSIX:MMAP
[symbol]
MMAP names a compiled function:
Lambda-list: (ADDR LENGTH PROT FLAGS FD OFFSET)
Derived type: (FUNCTION (T T T T T T)
(VALUES SYSTEM-AREA-POINTER &OPTIONAL))
Inline proclamation: INLINE (inline expansion available)
Source file: SYS:CONTRIB;SB-POSIX;INTERFACE.LISP.NEWEST
; No value
Run Code Online (Sandbox Code Playgroud)
您必须使用显式地址算术来使用它,如在C.