我需要获取一些有关在Mac OSX上运行进程的信息(PID,UID,GID,进程名称)。我试过了proc_pidinfo。对于我自己的流程,它可以正常工作。但是,对于其他用户拥有的进程,将返回0。没有此功能的文档,但是根据Internet上的信息,应该返回写入提供的缓冲区的字节数。在其他用户的进程上调用此函数将返回0,这意味着未提供任何信息。
例:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <libproc.h>
int main(int argc, char *argv[])
{
pid_t pid;
struct proc_bsdinfo proc;
if (argc == 2)
pid = atoi(argv[1]);
else
pid = getpid();
int st = proc_pidinfo(pid, PROC_PIDTBSDINFO, 0,
&proc, PROC_PIDTBSDINFO_SIZE);
if (st != PROC_PIDTBSDINFO_SIZE) {
fprintf(stderr, "Cannot get process info");
return 1;
}
printf(" pid: %d\n", (int)proc.pbi_pid);
printf("ppid: %d\n", (int)proc.pbi_ppid);
printf("comm: %s\n", proc.pbi_comm);
printf("name: %s\n", proc.pbi_name);
printf(" uid: %d\n", (int)proc.pbi_uid);
printf(" gid: %d\n", (int)proc.pbi_gid);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
运行此程序将产生:
$ ./pidinfo
pid: 30519
ppid: 8434
comm: pidinfo
name: pidinfo
uid: 501
gid: 20
$ ./pidinfo 1
Cannot get process info
$ sudo ./pidinfo 1
pid: 1
ppid: 0
comm: launchd
name: launchd
uid: 0
gid: 0
Run Code Online (Sandbox Code Playgroud)
这很奇怪,因为我可以从获得所有这些信息ps(1)。但是后来我检查了OSX ps和topOSX上的两者都是SUID二进制文件,这与proc_pidinfo行为是一致的:
$ ls -l `which ps` `which top`
-rwsr-xr-x 1 root wheel 51008 5 maj 08:06 /bin/ps
-r-sr-xr-x 1 root wheel 87952 5 maj 08:05 /usr/bin/top
Run Code Online (Sandbox Code Playgroud)
但是,活动监视器无需SUID即可工作。
因此,我的问题是,为什么proc_pidinfo只提供有关我自己的流程的信息?我可以使其提供有关其他过程的信息吗?如果没有,如何在不解析ps(1)输出的情况下获取此信息?
您可以使用 :
int proc_listpids(uint32_t type, uint32_t typeinfo, void *buffer, int buffersize);
Run Code Online (Sandbox Code Playgroud)
组合到proc_pidinfo以获得许多其他pids信息,例如:
#include <unistd.h>
#include <stdlib.h>
#include <mach/mach.h>
#include <libproc.h>
#include <mach/mach_time.h>
#include <sys/sysctl.h>
#include <mach-o/ldsyms.h>
#include <stdio.h>
void procpid(pid_t pid)
{ struct proc_bsdinfo proc;
int st = proc_pidinfo(pid, PROC_PIDTBSDINFO, 0, &proc, PROC_PIDTBSDINFO_SIZE);
printf("name: %s\n", proc.pbi_name);
}
void pidlist(void)
{ int bufsize = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0);
pid_t pids[2 * bufsize / sizeof(pid_t)];
bufsize = proc_listpids(PROC_ALL_PIDS, 0, pids, sizeof(pids));
size_t num_pids = bufsize / sizeof(pid_t);
int i = 0;
while (i < num_pids)
{ printf("pid[%d]::%d\n", i, pids[i]);
procpid(pids[i]);
printf("\n-------------------------------\n\n");
i += 1; }}
int main(void)
{ pidlist();
return(42); }
Run Code Online (Sandbox Code Playgroud)
我发现 macOS Mojave(版本 10.14.4)有struct proc_bsdshortinfo,它是struct proc_bsdinfo. 您可以使用 SUID 代替 .SUID 来获取其他用户的进程struct proc_bsdinfo。
嗯,我不知道它从哪个版本可用。
编辑:它至少从 macOS 10.10.5 (Yosemite) 开始可用。
再次编辑:它可能从 Mac OS X 10.7 (Lion) 开始可用,因为 tmux 使用struct proc_bsdshortinfoif__MAC_10_7定义。见这里。
例子:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <libproc.h>
int main(int argc, char *argv[])
{
pid_t pid;
struct proc_bsdshortinfo proc;
if (argc == 2)
pid = atoi(argv[1]);
else
pid = getpid();
int st = proc_pidinfo(pid, PROC_PIDT_SHORTBSDINFO, 0,
&proc, PROC_PIDT_SHORTBSDINFO_SIZE);
if (st != PROC_PIDT_SHORTBSDINFO_SIZE) {
fprintf(stderr, "Cannot get process info\n");
return 1;
}
printf(" pid: %d\n", (int)proc.pbsi_pid);
printf("ppid: %d\n", (int)proc.pbsi_ppid);
printf("comm: %s\n", proc.pbsi_comm);
//printf("name: %s\n", proc.pbsi_name);
printf(" uid: %d\n", (int)proc.pbsi_uid);
printf(" gid: %d\n", (int)proc.pbsi_gid);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
该程序打印:
$ ./pidinfo
pid: 3025
ppid: 250
comm: pidinfo
uid: 501
gid: 20
$ ./pidinfo 1
pid: 1
ppid: 0
comm: launchd
uid: 0
gid: 0
Run Code Online (Sandbox Code Playgroud)