gpt4 book ai didi

macos - 我可以使用 `sysctl` 检索用户的进程列表吗?

转载 作者:行者123 更新时间:2023-12-02 08:40:58 32 4
gpt4 key购买 nike

我需要一种方法来检索 Mac 上所有用户的所有正在运行的进程(使用 Cocoa)。我找到了一个使用 sysctl 检索进程的实现,但我还需要运行用户。这是我获取进程列表的截图,但是有没有办法修改它以包含用户?

int             err;
kinfo_proc * result;
bool done;

static const int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 };
size_t length;

// a valid pointer procList holder should be passed
assert( procList != NULL );
// But it should not be pre-allocated
assert( *procList == NULL );
// a valid pointer to procCount should be passed
assert( procCount != NULL );

*procCount = 0;

result = NULL;
done = false;

do
{
assert( result == NULL );

// Call sysctl with a NULL buffer to get proper length
length = 0;
err = sysctl((int *)name,(sizeof(name)/sizeof(*name))-1,NULL,&length,NULL,0);
if( err == -1 )
err = errno;

// Now, proper length is optained
if( err == 0 )
{
result = malloc(length);
if( result == NULL )
err = ENOMEM; // not allocated
}

if( err == 0 )
{
err = sysctl( (int *)name, (sizeof(name)/sizeof(*name))-1, result, &length, NULL, 0);
if( err == -1 )
err = errno;

if( err == 0 )
done = true;
else if( err == ENOMEM )
{
assert( result != NULL );
free( result );
result = NULL;
err = 0;
}
}
} while ( err == 0 && !done );

// Clean up and establish post condition
if( err != 0 && result != NULL )
{
free(result);
result = NULL;
}

*procList = result; // will return the result as procList
if( err == 0 )
*procCount = length / sizeof( kinfo_proc );

assert( (err == 0) == (*procList != NULL ) );

return err;

最佳答案

注意sysctl(3)返回的进程列表是一个struct kinfo_proc数组。如果你读过 kinfo_proc 的声明,你会发现它有一个 struct eproc 类型的 kp_eproc 成员,而它又有一个 struct _ucred 类型的 e_ucred 成员,而 struct _ucred 又有一个 uid_t 类型的 cr_uid 成员,代表有效用户 id该过程。

这意味着您可以使用该链

.kp_eproc.e_ucred.cr_uid

获取有效用户的id。例如:

for (int i = 0; i < procCount; i++) {
printf("pid=%d, uid=%d\n",
procList[i].kp_proc.p_pid,
procList[i].kp_eproc.e_ucred.cr_uid);
}

如果要将用户 ID 转换为用户名,可以使用 getpwuid(3) 或其可重入/线程安全变体 getpwuid_r(3):

for (int i = 0; i < procCount; i++) {
struct passwd *user = getpwuid(procList[i].kp_eproc.e_ucred.cr_uid);
char *username = user ? user->pw_name : "getpwuid() failed";
printf("pid=%d, user=%s\n",
procList[i].kp_proc.p_pid,
username);
}
<小时/>

下面是一个示例程序,列出了所有进程及其相应的 pid、有效 uid 和相应的用户名:

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <pwd.h>

int main(void) {
int err = 0;
struct kinfo_proc *proc_list = NULL;
size_t length = 0;

static const int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 };

// Call sysctl with a NULL buffer to get proper length
err = sysctl((int *)name, (sizeof(name) / sizeof(*name)) - 1, NULL, &length, NULL, 0);
if (err) goto ERROR;

// Allocate buffer
proc_list = malloc(length);
if (!proc_list) goto ERROR;

// Get the actual process list
err = sysctl((int *)name, (sizeof(name) / sizeof(*name)) - 1, proc_list, &length, NULL, 0);
if (err) goto ERROR;

int proc_count = length / sizeof(struct kinfo_proc);

// use getpwuid_r() if you want to be thread-safe

for (int i = 0; i < proc_count; i++) {
uid_t uid = proc_list[i].kp_eproc.e_ucred.cr_uid;
struct passwd *user = getpwuid(uid);
char *username = user ? user->pw_name : "user name not found";

printf("pid=%d, uid=%d, username=%s\n",
proc_list[i].kp_proc.p_pid,
uid,
username);
}

free(proc_list);

return EXIT_SUCCESS;

ERROR:
perror(NULL);
free(proc_list);
return EXIT_FAILURE;
}

关于macos - 我可以使用 `sysctl` 检索用户的进程列表吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7729245/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com