Как программно получить UID из PID в OSX с помощью C ++? - PullRequest
3 голосов
/ 23 июня 2011

Учитывая pid, я хочу найти владельца процесса (как uid). Есть ли способ получить это в OSX (или любой Unix) с помощью C ++?

Google не помог. «PS» может это сделать; поэтому я предполагаю, что должен быть способ получить его программно.

Ответы [ 5 ]

4 голосов
/ 24 ноября 2013

Решение от Indhu помогло мне в пути, поэтому я хотел бы опубликовать свой собственный.

UID из PID с чистым 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;
}

Без избыточного выделения, без циклов.

3 голосов
/ 23 июня 2011

Источник команды ps показывает, что есть функция с именем get_proc_stats, определенная в proc / readproc.h , которая (среди прочего) возвращает 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 () функции для получения идентификатора.

2 голосов
/ 23 июня 2011

Нет портативного способа сделать это. В Mac OS вы должны использовать плохо документированные sysctl интерфейсы: см. этот предыдущий вопрос stackoverflow . (Как отмечали другие комментаторы, в Linux вы можете использовать proc. Во FreeBSD вы должны иметь возможность использовать kvm_getfiles, хотя это не доступно в Mac OS.)

Лучше всего использовать источник для ps от Apple в качестве отправной точки для сбора данных о процессе, и тогда вы сможете использовать getpwuid(3), как только получите UID.

2 голосов
/ 23 июня 2011

Вы можете посмотреть на , как это делает ps .Похоже, он использует функцию kvm_getprocs .

Однако он гораздо более переносим (вы сказали «любой unix», но, например, Linux и Solaris выглядят как /proc).файловая система - и другие unixes могут иметь разные API), чтобы просто анализировать вывод ps (например, ps -o user= -p (pid), чтобы исключить любой посторонний вывод), чем делать какие-либо специфичные для системы процессы

1 голос
/ 04 августа 2011

Наконец-то нашел способ программно сделать это, не разбирая вывод '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' вместо итерации по всему процессу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...