[英]How to programatically get uid from pid in osx using c++?
給定一個pid,我想找到進程的所有者(作為uid)。 有沒有辦法在使用C ++的osx(或任何unix)中獲取它?
谷歌沒有幫助。 'ps'能夠做到; 所以我認為應該有一種方法來編程。
來自Indhu的解決方案幫助了我,所以我想發布自己的。
PID與純C的UID:
#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;
}
沒有多余的分配,沒有循環。
ps命令的源代碼顯示在proc / readproc.h中定義了一個名為get_proc_stats
的函數,其中(除其他外)返回給定pid的real user name(UID)
和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。
你可以看看ps是如何做到的 。 看起來它使用kvm_getprocs函數。
但是,它更便攜(你說“任何unix”,但是例如Linux和Solaris的方式是查看/proc
文件系統 - 而其他unix可能有不同的API)來解析ps的輸出( ps -o user= -p (pid)
,例如,消除任何無關的輸出),而不是任何系統特定的進程
沒有一種可移植的方式來做到這一點。 在Mac OS上,您必須使用記錄不佳的sysctl
接口:請參閱此前一個stackoverflow問題 。 (正如其他評論者指出的那樣,在Linux上你可以使用proc。在FreeBSD上,你應該可以使用kvm_getfiles
,雖然這在Mac OS上不可用。)
最好的辦法是使用Apple的ps
源作為獲取過程數據的起點,然后一旦你擁有了uid就可以使用getpwuid(3)
。
終於找到了一種以編程方式執行此操作而無需解析'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'而不是遍歷所有進程。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.