在Linux上获取通用Lisp进程ID

时间:2018-10-12 23:06:32

标签: linux common-lisp pid

我想知道是否有办法从Common Lisp的REPL中获取Linux的PID(进程ID)。也就是说,我想从流程本身的REPL知道SBCL或Allegro流程的ID。

3 个答案:

答案 0 :(得分:7)

Common Lisp规范中没有实现此目的的东西。进程ID过于依赖于实现。

在SBCL中,SB-POSIX软件包为大多数POSIX系统调用提供了Lisp接口,因此您将使用(sb-posix:getpid)

在Allegro CL中,操作系统接口功能位于EXCL.OSI包中,因此您将使用(excl.ose:getpid)

答案 1 :(得分:4)

有一种(基本上)可移植的方法来执行此操作。 CL提供读取文件的功能,并且可以观察到当前进程的pid位于/proc/self/status中(而且/proc/self是指向该进程的pid的符号链接,但我认为没有可移植的读取链接)

具体来说,/proc/self/status是一个文本文件,其中包含如下一行:

Pid: 439

因此您可以解析文件以提取出来。

但是一旦有了pid,没有系统调用或/proc怪异

答案 2 :(得分:3)

最终解决方案(在很大程度上由@Dan Robertson's和@coredump-谢谢!)

实际上@Dan Robertson给出了完整的答案-我回想起来。 这个答案只是他所说的实现。所以给他点!

(ql:quickload "CL-PPCRE") ;; for regex parsing

(defun get-this-pid ()
  "Return PID of this current lisp process."
  (with-open-file (in #P"/proc/self/status")
    (loop for line = (read-line in nil)
      while line
      when (ppcre:scan "^Pid" line)
        do (return (car
            (ppcre:all-matches-as-strings "\\d+" 
                              line))))))

;; to get current process id, call:
(get-this-pid) ;
;; returns for me at the moment using sbcl "12646"
;; this is correct as closing of all other sbcl processes
;; and doing "pidof sbcl" in the shell showed.

正如@Don Robertson所指出的,文件/proc/self/status显示了打开其“ PID”编号的程序(每个程序对它的看法都不相同)。谢谢唐,因为这解决了在计算机上独立运行多个Lisp程序时,在外壳中真正找到程序PID(pidof sbcl的PID会给出多个数字的问题。 调用外部程序已过时,如果我们从cl内部打开该文件,就像@coredump指出的那样。

其他程序的PID号

;; Thanks to @coredump - who suggested to use 
;; `ppcre:split :whitespace-char-class` for capturing arbitrary numbers
;; in the answer string - I added a test for integer-string-p to clean
;; non-numberic values after split.

(ql:quickload "CL-PPCRE")

(defun integer-string-p (string)
  "Does string constist only of '01234567890' characters?"
  (reduce (lambda (x y) (and x y))
      (mapcar (lambda (c) (member c (coerce "1234567890" 'list)))
          (coerce string 'list))))

(defun extract-integers-from-string (s)
  "Return integer-words of s."
  (let ((l (ppcre:split :whitespace-char-class s)))
    (remove-if-not #'integer-string-p l)))

(defun pid-numbers (program-name)
  "Return PID numbers of a program in current machine."
  (let ((pid-line (with-output-to-string (out)
            (external-program:run "pidof" (list program-name)
                      :output out))))
    (extract-integers-from-string pid-line)))

;; call it
(pid-numbers "sbcl")
(pid-numbers "firefox")

;; * (pid-numbers "sbcl")
;; ("16636" "12346")
;; * (pid-numbers "firefox") 
;; ("24931" "19388" "19122" "10800" "10745") ; yeah I have many open :D