给定一个pid,我想找到进程的所有者(作为uid)。有没有办法在使用C ++的osx(或任何unix)中获取它?
谷歌没有帮助。 'ps'能够做到;所以我认为应该有一种方法来编程。答案 0 :(得分:4)
Indhu的解决方案帮助了我,所以我想发布自己的。
来自PID的UID与纯C:
#include <sys/sysctl.h>
uid_t uidFromPid(pid_t pid)
{
uid_t uid = -1;
struct kinfo_proc process;
size_t procBufferSize = sizeof(process);
// Compose search path for sysctl. Here you can specify PID directly.
const u_int pathLenth = 4;
int path[pathLenth] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
int sysctlResult = sysctl(path, pathLenth, &process, &procBufferSize, NULL, 0);
// If sysctl did not fail and process with PID available - take UID.
if ((sysctlResult == 0) && (procBufferSize != 0))
{
uid = process.kp_eproc.e_ucred.cr_uid;
}
return uid;
}
没有多余的分配,没有循环。
答案 1 :(得分:3)
ps命令的源代码显示在proc/readproc.h中定义了一个名为get_proc_stats
的函数,其中(除其他外)返回real user name(UID)
&amp;对于给定的pid,Effective user name(EUID)
。
您需要安装libproc-dev
才能获得此功能。然后你就可以做到:
#include <proc/readproc.h>
void printppid(pid_t pid)
{
proc_t process_info;
get_proc_stats(pid, &process_info);
printf("Real user of the process[%d] is [%s]\n", pid, process_info.ruser);
}
使用gcc the-file.c -lproc
编译。
拥有真实用户名后,您可以使用getpwnam()和getgrnam()函数来获取uid。
答案 2 :(得分:2)
您可以查看how ps does it。看起来它使用kvm_getprocs函数。
然而,它更便携(你说“任何unix”,但是例如Linux和Solaris的方式是查看/proc
文件系统 - 而其他unix可能有不同的API)来解析输出ps(ps -o user= -p (pid)
,例如,消除任何无关的输出),而不是任何特定于系统的过程内容
答案 3 :(得分:2)
没有可行的方法来做到这一点。在Mac OS上,您必须使用记录不良的sysctl
接口:请参阅this previous stackoverflow question。 (正如其他评论者指出的那样,在Linux上你可以使用proc。在FreeBSD上,你应该可以使用kvm_getfiles
,虽然这在Mac OS上不可用。)
您最好的选择是使用Apple ps
的来源作为获取流程数据的起点,然后一旦您拥有了uid,就可以使用getpwuid(3)
。
答案 4 :(得分:1)
最后找到了一种以编程方式执行此操作的方法,而无需解析'ps'的输出
uint getUidUsingSysctl(uint pid)
{
struct kinfo_proc *sProcesses = NULL, *sNewProcesses;
int aiNames[4];
size_t iNamesLength;
int i, iRetCode, iNumProcs;
size_t iSize;
iSize = 0;
aiNames[0] = CTL_KERN;
aiNames[1] = KERN_PROC;
aiNames[2] = KERN_PROC_ALL;
aiNames[3] = 0;
iNamesLength = 3;
iRetCode = sysctl(aiNames, iNamesLength, NULL, &iSize, NULL, 0);
/* allocate memory and populate info in the processes structure */
do
{
iSize += iSize / 10;
sNewProcesses = (kinfo_proc *)realloc(sProcesses, iSize);
if (sNewProcesses == 0)
{
if (sProcesses)
free(sProcesses);
/* could not realloc memory, just return */
return -1;
}
sProcesses = sNewProcesses;
iRetCode = sysctl(aiNames, iNamesLength, sProcesses, &iSize, NULL, 0);
} while (iRetCode == -1 && errno == ENOMEM);
iNumProcs = iSize / sizeof(struct kinfo_proc);
for (i = 0; i < iNumProcs; i++)
{
if (sProcesses[i].kp_proc.p_pid == pid)
{
return sProcesses[i].kp_eproc.e_ucred.cr_uid;
}
}
/* clean up and return to the caller */
free(sProcesses);
return -1;
}
注意:可能有更好的方法来获取'kinfo_proc'而不是遍历所有过程。