2017-07-05 35 views
2

在SO的幫助下,我編寫了一個應用程序,用於顯示Swift中所有打開的TCP/UDP連接。 在接下來的步驟中,我想獲得打開連接的過程(幾乎和lsof一樣)。在errno 12中獲取所有打開的文件以獲得處理結果=內存不足

因爲lsof是一個開源的,我可以寫下面的代碼獲得所有的進程打開的文件:

橋接標頭:

#include <mach/mach_types.h> 
#include <mach/vm_param.h> 
#include <mach/host_info.h> 
#include <mach/task_info.h> 
#include <mach/thread_info.h> 
#include <mach/vm_region.h> 
#include <libproc.h> 

#include <sys/proc_info.h> 
#include <sys/kdebug.h> 
#include <sys/msgbuf.h> 

(我不認爲所有的包括是需要,但至少現在編譯)。

for app in NSWorkspace.shared().runningApplications 
    { 
     let pid = app.processIdentifier 

     var tai = proc_taskallinfo() 
     let size = MemoryLayout<proc_bsdinfo>.size 
     var result = proc_pidinfo(pid, PROC_PIDTASKALLINFO, 0, &tai, Int32(size)) 
     let fileCount: Int32 = Int32(tai.pbsd.pbi_nfiles) 

     if result <= 0 
     { 
      if errno == ENOMEM 
      { 
       Swift.print("Out of memory.") 
      } 
      Swift.print(errno) 
      continue 
     } 

     var fid = proc_fdinfo() 
     let fdInfoSize = MemoryLayout<proc_fdinfo>.size 
     result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, &fid, Int32(fdInfoSize) * fileCount) 

     if result <= 0 
     { 
      Swift.print("Error. No Files?") 
     } 
     else 
     { 
      Swift.print("Files found.") 
     } 
    } 

的代碼是由C移植到斯威夫特3.原來的C代碼如下所示:

int nb; 
struct proc_taskallinfo tai; 
... 
nb = proc_pidinfo(pid, PROC_PIDTASKALLINFO, 0, &tai, sizeof(tai)); 

當我運行我的代碼,我得到的錯誤號12(內存不足)。爲什麼?

P.S.我知道第二個proc_pidinfo也會失敗,因爲返回一個指向proc_fdinfo數組的指針,而不是一個指向單個結構體的指針,但是一次一步。這是關於errno 12.

+1

從您的代碼中使用C函數不符合C標記。 – Olaf

+1

不應該是'let size = MemoryLayout .size'? 'proc_bsdinfo'從哪裏來? –

+0

是的。是的,它應該是...... –

回答

2

有兩個錯誤。首先,它應該是

let size = MemoryLayout<proc_taskallinfo>.size 

二,proc_pidinfo(pid, PROC_PIDLISTFDS, ...)需要一個緩衝 與空間proc_fdinfofileCount的結構,不僅僅是 一個一個:

var fid = Array(repeating: proc_fdinfo(), count: Int(fileCount)) 
let fdInfoSize = MemoryLayout<proc_fdinfo>.stride 
result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, &fid, Int32(fdInfoSize) * fileCount) 
+0

現在,它的工作。謝謝! –

1

下面是最終代碼來獲得TCP套接字。不幸的是,它不可能在沙盒應用程序中使用代碼:

for app in NSWorkspace.shared().runningApplications { 
    let pid = app.processIdentifier 

    var tai = proc_taskallinfo() 
    let size = MemoryLayout<proc_taskallinfo>.size 
    var result = proc_pidinfo(pid, PROC_PIDTASKALLINFO, 0, &tai, Int32(size)) 
    let fileCount: Int32 = Int32(tai.pbsd.pbi_nfiles) 

    if result <= 0 { 
     continue 
    } 

    var fid = Array(repeating: proc_fdinfo(), count: Int(fileCount)) 
    let fdInfoSize = MemoryLayout<proc_fdinfo>.stride 
    result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, &fid, Int32(fdInfoSize) * fileCount) 

    if result <= 0 { 
     Swift.print("Error PROC_PIDLISTFDS.") 
    } 
    else { 
     for i in 0.. < Int(result)/fdInfoSize { 
      let fdp = fid[i] 

      if fdp.proc_fdtype == UInt32(PROX_FDTYPE_SOCKET) { 
       var si = socket_fdinfo() 
       let sizeSi = MemoryLayout<socket_fdinfo>.size 
       result = proc_pidfdinfo(pid, fdp.proc_fd, PROC_PIDFDSOCKETINFO, &si, Int32(sizeSi)) 

       if result <= 0 { 
        Swift.print("Error PROC_PIDFDSOCKETINFO: " + errno.description) 
       } 
       else { 
        if si.psi.soi_kind == Int32(SOCKINFO_TCP) { 
         Swift.print("TCP Socket") 
        } 
       } 
      } 
     } 
    } 
} 
+1

我假設'對於我在0 ..

+0

我編輯了我的答案,謝謝你的提示。 –