我可以使用sysctl与用户一起检索进程列表吗? [英] Can I use `sysctl` to retrieve a process list with the user?
问题描述
我需要一种为Mac上的所有用户(使用Cocoa)检索所有正在运行的进程的方法.我找到了一个使用sysctl检索过程的实现,但是我还需要运行中的用户.这是我要获取流程列表的一部分,但是有没有办法修改它以包括用户?
I am in need of a way to retrieve all running processes for all users on a Mac (using Cocoa). I found an implementation to retrieve the process using sysctl, but I also need the running user. This is a snipping of what I've got to get the process list, but is there a way to modify it to include the user as well?
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)返回的进程列表是结构kinfo_proc的数组.如果您阅读kinfo_proc的声明,则会看到它具有一个struct eproc类型的kp_eproc成员,该成员又具有一个struct _ucred类型的e_ucred成员,该成员又具有一个uid_t类型的cr_uid成员,代表了有效的用户ID.这个过程.
Note that the process list returned by sysctl(3) is an array of struct kinfo_proc. If you read kinfo_proc’s declaration, you’ll see that it has a kp_eproc member of type struct eproc, which in turn has an e_ucred member of type struct _ucred, which in turn has a cr_uid member of type uid_t, representing the effective user id of that process.
这意味着您可以使用链条
This means that you can use the chain
.kp_eproc.e_ucred.cr_uid
获取有效用户的ID.例如:
to obtain the id of the effective user. For example:
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):
If you want to convert the user id to a user name, you can use getpwuid(3) or its reentrant/thread-safe variant, 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和相应的用户名:
Here’s a sample program that lists all processes with their corresponding pids, effective uids and corresponding usernames:
#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;
}
这篇关于我可以使用sysctl与用户一起检索进程列表吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!