我正在尝试获取MacOS上的pid列表。librpoc.h 包含此函数签名,但我找不到任何文档:
int proc_listpids(uint32_t type, uint32_t typeinfo, void *buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
我在Swift中尝试了以下示例代码:
let arr = UnsafeMutableRawPointer.allocate(byteCount: 5000 * MemoryLayout<Int32>.stride, alignment: MemoryLayout<Int32>.alignment)
let count = proc_listpids(UInt32(PROC_ALL_PIDS), 0, arr, Int32(5000 * MemoryLayout<Int32>.stride));
print("count \(count)")
let pointer = arr.assumingMemoryBound(to: Int32.self)
let pids = Array(UnsafeMutableBufferPointer(start:pointer, count:Int(count)))
let slice = pids[0..<Int(count)]
for i in 0..<Int(count) {
print("index:\(i) pid:\(slice[i])")
}
最初我认为count
是找到的pid的数量。但是输出显示了更多的元素:
count 2020
index:0 pid:7727
index:1 pid:7726
index:2 pid:7723
index:3 pid:7722
index:4 pid:7721
index:5 pid:7717
...
index:502 pid:94
index:503 pid:1
index:504 pid:0
index:505 pid:0
index:506 pid:0
...
index:2013 pid:0
index:2014 pid:0
index:2015 pid:0
index:2016 pid:0
index:2017 pid:0
index:2018 pid:0
index:2019 pid:0
因此,如何解释proc_listpids
实际返回的数字是令人困惑的?
1条答案
按热度按时间oalqel3c1#
问题
proc_listpids
(和许多其他libproc.h
API)返回结果将具有的总缓冲区大小 * 以字节为单位 *。所以结果2020
是2020
字节,这正好足够存储505
Int32
s(当然,每个4字节),这意味着最后一个有效索引是504
。为什么返回size而不是count?
这只是我的推测,但我怀疑这是因为它使API便于在C中使用,在C中,此结果可能会直接传递给
malloc
。如果它们返回的是计数而不是字节数,则调用方必须自己进行转换。由于许多libproc API可以返回几种不同结构中的一种,因此使用错误结构的
sizeof
(对于您标记的特定类型的请求)可能会导致缓冲区太小(存在缓冲区溢出漏洞的风险)或太大(存在缓冲区下溢漏洞的风险)。工作示例
下面的代码片段显示了对
proc_listpids
的工作调用:如果使用
proc_listallpids
,事情会变得简单一些,这只是这种情况下的一个方便 Package 器(源代码):一些注意事项:
proc_listpids
之间启动,那么缓冲区将太小而无法容纳它。proc_listpids
的结果作为对大小的初始猜测,然后添加一些额外的值以考虑可能出现的任何新进程。Array.init(unsafeUninitializedCapacity:initializingWith:)
为Swift Array分配缓冲区,并直接初始化它,而无需任何中间分配或复制。malloc
,误用会导致巨大的问题。额外
如果你发现自己调用了许多不同的libproc API,我发现定义一个helper来抽象掉这段舞蹈的一部分(比如这些计数计算、整数转换、Assert等)是很有用的: