簡體   English   中英

如何使用c ++以編程方式從osx中的pid獲取uid?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM