Skip to content

Instantly share code, notes, and snippets.

@macshome
Last active May 8, 2024 08:48
Show Gist options
  • Save macshome/c18bd88a6b8973bd1e5bfaea738f739e to your computer and use it in GitHub Desktop.
Save macshome/c18bd88a6b8973bd1e5bfaea738f739e to your computer and use it in GitHub Desktop.
Swift Playground to get all running processes on macOS
import Darwin
func getProcessList() {
// Requesting the pid of 0 from systcl will return all pids
var mib = [CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0]
var bufferSize = 0
// To find the needed buffer size you call sysctl with a nil results pointer.
// This sets the size of the buffer needed in the bufferSize pointer.
if sysctl(&mib, UInt32(mib.count), nil, &bufferSize, nil, 0) < 0 {
perror(&errno)
return
}
// Determine how many kinfo_proc struts will be returned.
// Using stride rather than size will take alligment into account.
let entryCount = bufferSize / MemoryLayout<kinfo_proc>.stride
// Create our buffer to be filled with the list of processes and allocate it.
// Use defer to make sure it's deallocated when the scope ends.
var procList: UnsafeMutablePointer<kinfo_proc>?
procList = UnsafeMutablePointer.allocate(capacity: bufferSize)
defer { procList?.deallocate() }
// Now we actually perform our query to get all the processes.
if sysctl(&mib, UInt32(mib.count), procList, &bufferSize, nil, 0) < 0 {
perror(&errno)
return
}
// Simply step through the returned bytes and lookup the data you want.
// If the pid is 0 that means it's invalid and should be ignored.
for index in 0...entryCount {
guard let pid = procList?[index].kp_proc.p_pid,
pid != 0,
let comm = procList?[index].kp_proc.p_comm else {
continue
}
// p_comm returns the first 16 characters of the process name as a tuple of CChars.
// An easy way to convert it to to an array of CChars is with a Mirror.
//
// If you want the full names you can make another sysctl request for the KERN_PROCARGS2
// mib for each pid.
let name = String(cString: Mirror(reflecting: comm).children.map(\.value) as! [CChar])
print("PID: \(pid), Name: \(name)")
}
}
getProcessList()
@macshome
Copy link
Author

Swift playground code to get all the active processes using sysctl. Mostly for learning how to use some POSIX stuff in Swift.

@x13a
Copy link

x13a commented May 8, 2024

There are higher level functions for this like proc_listpids, proc_name than using sysctl. They are available in proc library. I have wrapped them some time ago: libproc-swift

For those who are looking for KERN_PROCARGS2, here it is: syscall-swift

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment