如何使用c ++以编程方式从os中的pid获取uid?

时间:2011-06-23 16:45:48

标签: c++ macos unix process

给定一个pid,我想找到进程的所有者(作为uid)。有没有办法在使用C ++的osx(或任何unix)中获取它?

谷歌没有帮助。 'ps'能够做到;所以我认为应该有一种方法来编程。

5 个答案:

答案 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'而不是遍历所有过程。