First off, I know that similar questions have been asked, but the answers provided haven't been very helpful so far (they all recommend one of the following options).
I have a user application that needs to determine if a particular process is running. Here's what I know about the process:
root
)launchd
(pid 1)I've tried several ways to get this, but none have worked so far. Here's what I've tried:
Running ps
and parsing the output. This works, but it's slow (fork
/exec
is expensive), and I'd like this to be as fast as possible.
Using the GetBSDProcessList
function listed here. This also works, but the way in which they say to retrieve the process name (accessing kp_proc.p_comm
from each kinfo_proc
structure) is flawed. The resulting char*
only contains the first 16 characters of the process name, which can be seen in the definition of the kp_proc
structure:
#define MAXCOMLEN 16 //defined in param.h struct extern_proc { //defined in proc.h ...snip... char p_comm[MAXCOMLEN+1]; ...snip... };
Using libProc.h to retrieve process information:
pid_t pids[1024]; int numberOfProcesses = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0); proc_listpids(PROC_ALL_PIDS, 0, pids, sizeof(pids)); for (int i = 0; i < numberOfProcesses; ++i) { if (pids[i] == 0) { continue; } char name[1024]; proc_name(pids[i], name, sizeof(name)); printf("Found process: %s\n", name); }
This works, except it has the same flaw as GetBSDProcessList
. Only the first portion of the process name is returned.
Using the ProcessManager function in Carbon:
ProcessSerialNumber psn; psn.lowLongOfPSN = kNoProcess; psn.highLongOfPSN = 0; while (GetNextProcess(&psn) == noErr) { CFStringRef procName = NULL; if (CopyProcessName(&psn, &procName) == noErr) { NSLog(@"Found process: %@", (NSString *)procName); } CFRelease(procName); }
This does not work. It only returns process that are registered with the WindowServer (or something like that). In other words, it only returns apps with UIs, and only for the current user.
I can't use -[NSWorkspace launchedApplications]
, since this must be 10.5-compatible. In addition, this only returns information about applications that appear in the Dock for the current user.
I know that it's possible to retrieve the name of running processes (since ps
can do it), but the question is "Can I do it without forking and exec'ing ps
?".
Any suggestions?
EDIT
After doing a lot more research, I've been unable to find a way to do this. I found this SO question, which referred to this C file in a python module. This was really useful in trying to use the KERN_PROCARGS
values in a sysctl
call.
However, Python module code seemed to be derived from the source to ps
, which I found here. ps
can somehow get the executable path of every running process, but my best efforts to extract how its doing this have been unsuccessful. There's a function in print.c
called getproclline
that seems to be doing the magic, but when I run the same code from within my own command line tool, I'm unable to retrieve the process executable for any processes other than my own.
I'll keep experimenting, but without more conclusive evidence, it looks like @drawnonward's answer is the most correct so far.
EDIT (a long time later)
Thanks to the answer pointed to by Quinn Taylor, I've found something that works. It gets the executable path of each process, and then I can just grab the last path component to get the actual process name.
#import <sys/proc_info.h> #import <libproc.h> int numberOfProcesses = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0); pid_t pids[numberOfProcesses]; bzero(pids, sizeof(pids)); proc_listpids(PROC_ALL_PIDS, 0, pids, sizeof(pids)); for (int i = 0; i < numberOfProcesses; ++i) { if (pids[i] == 0) { continue; } char pathBuffer[PROC_PIDPATHINFO_MAXSIZE]; bzero(pathBuffer, PROC_PIDPATHINFO_MAXSIZE); proc_pidpath(pids[i], pathBuffer, sizeof(pathBuffer)); if (strlen(pathBuffer) > 0) { printf("path: %s\n", pathBuffer); } }
The most common way to list processes currently running on your system is to use the command ps (short for process status). This command has a lot of options that come in handy when troubleshooting your system. The most used options with ps are a, u and x.
Task Manager can be opened in a number of ways, but the simplest is to select Ctrl+Alt+Delete, and then select Task Manager. In Windows, first click More details to expand the information displayed. From the Processes tab, select Details to see the process ID listed in the PID column. Click on any column name to sort.
To list currently running processes, use the ps , top , htop , and atop Linux commands. You can also combine the ps command with the pgrep command to identify individual processes.
In this quick article, we've explored how to get the name and the command line of a given PID in the Linux command line. The ps -p <PID> command is pretty straightforward to get the process information of a PID. Alternatively, we can also access the special /proc/PID directory to retrieve process information.
What about this answer to a related question? https://stackoverflow.com/a/12274588/120292 This purports to get the full path for a process by the pid, and you can grab just the last path component.
The only complete list of running processes is provided by 2 above, asking the kernel. Getting the actual name of the process is not straight forward. In a nutshell, you look up the pid in any other source you can find until you get a match.
For some processes, the following will work:
ProcessSerialNumber psn; CFStringRef name = NULL; status = GetProcessForPID( inPID , &psn ); if ( noErr == status ) CopyProcessName( &psn , &name );
For some processes, you can look up the pid in the results of [[NSWorkspace sharedWorkspace] launchedApplications]
by NSApplicationProcessIdentifier
. Available with 10.2 and later. Most, but maybe not all, items in this list will be the same as CopyProcessName above.
For some processes, you can look up the process arguments and get the full path from the first argument. Similar to getting the original list, but using KERN_PROCARGS or KERN_PROCARGS2 as the second mib value. This is what ps
is doing.
For some processes, you are stuck with the 16 character p_comm.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With