【问题标题】:Getting Common Lisp Process ID on Linux在 Linux 上获取 Common Lisp 进程 ID
【发布时间】:2018-10-12 23:06:31
【问题描述】:

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

【问题讨论】:

  • 这必须使用特定于实现的扩展。标准 CL 没有这样的东西。
  • 你可以试试osicat(osicat-posix:getpid)
  • 在 CCL 上:(ccl::getpid)。要查找其他实现:(apropos "pid").

标签: linux common-lisp pid


【解决方案1】:

Common Lisp 规范中没有任何内容可以实现这一点。进程 ID 过于依赖实现。

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

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

【讨论】:

    【解决方案2】:

    有一种(基本上)可移植的方式来做到这一点。 CL 提供读取文件的功能,可以观察到当前进程的 pid 在 /proc/self/status 中(/proc/self 也是进程 pid 的符号链接,但我认为没有可移植的读取链接)。

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

    Pid: 439
    

    所以你可以解析文件来提取它。

    但是一旦你有了 pid,没有系统调用或/proc 怪异,你就无能为力了

    【讨论】:

    • /proc/self/status 实际显示的是什么?哪个程序的PID?我想pidof sbcl是程序号,不是吗?
    • 在 Linux 中有一个由内核(不在磁盘上)支持的文件系统,称为 procfs。它包含每个正在运行的进程的一个文件夹,文件self 是当前进程文件夹的符号链接(每个进程对此文件的看法不同)
    • hm ...但是如果我使用 shell 命令从 sbcl 中调用 - 那么它就不一定是 sbcl 的 pid,不是吗?
    • 我不明白你的意思。如果您在 lisp 中打开文件,那么您可以找到打开文件的 lisp 进程的 pid。如果您使用cat /proc/self/status,那么您会发现分配给cat 的pid。
    • @coredump 在我的回答讨论中已经回答了这个问题。您对/proc/self/status 的提示确实是获取进程pid 的关键。但是如果你会这样做cat /proc/self/status,它会给出 cat 而不是 sbcl 的 pid。
    【解决方案3】:

    最终解决方案(主要由 @Dan Robertson 和 @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”编号(每个程序对它的看法不同)。谢谢 Don,因为这解决了查找程序 PID 的问题(如果机器上独立运行多个 lisp 程序,shell 中的pidof sbcl 会给出几个数字。 调用外部程序已经过时了,如果我们从 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
    

    【讨论】:

    • 您可以使用(ppcre:split :whitespace-char-class output) 来处理任意数量的pid。
    • 嘿@coredump 谢谢!我在问自己如何处理任意数量的 pid!非常感谢!
    • 当你运行一个外部程序时,你正在创建一个新进程!你得到的pid是来自grep的pid。见:(with-open-file (in #P"/proc/self/status") (loop for line = (read-line in nil) while line when (ppcre:scan "^Pid" line) do (print line)))
    • 啊是的......所以从 cl 中打开/扫描文件是必要的 - 然后来自pidof sbcl 的多个 pid 将被过时......谢谢@coredump 和@Dan Robertson!我想我现在明白了 - 如何扫描它...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-20
    • 2020-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多