获取进程的所有打开文件导致 errno 12 = Out of Memory
Getting all open files for process results in errno 12 = Out of Memory
在 SO 的帮助下,我编写了一个应用程序,显示 Swift 中所有打开的 TCP/UDP 连接。
在下一步中,我想获得打开连接的进程(几乎与 lsof 一样)。
由于 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 移植到 Swift 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.
有两个错误。首先,应该是
let size = MemoryLayout<proc_taskallinfo>.size
其次,proc_pidinfo(pid, PROC_PIDLISTFDS, ...)
需要一个缓冲区
为 fileCount
类型的 proc_fdinfo
结构留出空间,而不仅仅是
一个:
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)
这是获取 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")
}
}
}
}
}
}
在 SO 的帮助下,我编写了一个应用程序,显示 Swift 中所有打开的 TCP/UDP 连接。 在下一步中,我想获得打开连接的进程(几乎与 lsof 一样)。
由于 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 移植到 Swift 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.
有两个错误。首先,应该是
let size = MemoryLayout<proc_taskallinfo>.size
其次,proc_pidinfo(pid, PROC_PIDLISTFDS, ...)
需要一个缓冲区
为 fileCount
类型的 proc_fdinfo
结构留出空间,而不仅仅是
一个:
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)
这是获取 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")
}
}
}
}
}
}