在Darwin/OSX中以编程方式确定进程信息

15

我有一个带有以下成员函数的类:


/// 调用者进程ID
virtual pid_t Pid() const = 0; 

/// 物理内存大小(单位:KB)
virtual uint64_t Size() const = 0;  

/// 进程占用的常驻内存大小
virtual uint64_t Rss() const = 0; 

/// 进程使用的CPU百分比
virtual double PercentCpu() const = 0; 

/// 进程使用的内存百分比
virtual double PercentMemory() const = 0; 

/// 当前进程中的线程数
virtual int32_t Lwps() const = 0; 

这个类的职责是返回调用者的进程信息。物理内存大小可以通过sysctl调用轻松确定,PID也很简单,但是除此之外的调用一直困扰着我,除了调用ps或top上的popen并解析输出 - 这是不可接受的。非常感谢任何帮助。

要求:
在g++ 4.0上编译
无obj-c
OSX 10.5


2
请描述为什么您想创建一个执行此操作的类。大多数在Mac OS X上运行的软件不需要关心您所描述的任何内容。此外,在开发Mac OS X应用程序时,“无Objective-C”不是一个合理的策略。 - Chris Hanson
5个回答

14

进程信息来自于 pidinfo:

cristi:~ diciu$ grep proc_pidinfo /usr/include/libproc.h

int proc_pidinfo(int pid, int flavor, uint64_t arg,  void *buffer, int buffersize);

CPU负载来自host_statistics

cristi:~ diciu$ grep -r host_statistics /usr/include/

/usr/include/mach/host_info.h:/* host_statistics() */

/usr/include/mach/mach_host.defs:routine host_statistics(

/usr/include/mach/mach_host.h:/* Routine host_statistics */

/usr/include/mach/mach_host.h:kern_return_t host_statistics

更多细节,请查看 toplsof 的源代码,它们都是开源的(你需要注册成为苹果开发者,但是免费的):

https://opensource.apple.com/source/top/top-111.20.1/libtop.c.auto.html

后续编辑: 所有这些接口都与特定版本相关,因此在编写生产代码时需要考虑这一点(libproc.h):

/*
 * This header file contains private interfaces to obtain process information.
 * These interfaces are subject to change in future releases.
 */

7

既然你说不用Objective-C,那我们就排除掉大部分的MacOS框架。

你可以使用getrusage()来获取CPU时间,它会给出分配给你的进程的用户和系统CPU时间总量。要获得CPU百分比,你需要每秒快照一次getrusage的值(或者任何你想要的粒度)。

#include <sys/resource.h>

struct rusage r_usage;

if (getrusage(RUSAGE_SELF, &r_usage)) {
    /* ... error handling ... */
}

printf("Total User CPU = %ld.%ld\n",
        r_usage.ru_utime.tv_sec,
        r_usage.ru_utime.tv_usec);
printf("Total System CPU = %ld.%ld\n",
        r_usage.ru_stime.tv_sec,
        r_usage.ru_stime.tv_usec);

在getrusage结构中有一个RSS字段,但在MacOS X 10.5中似乎始终为零。Michael Knight几年前写了一篇关于如何确定RSS的博客文章。

你能否解释一下如何在Cocoa中获取正在运行进程的内存使用情况? - Amit Khandelwal

2
您可以使用以下代码来处理Mac OS中的信息:
void IsInBSDProcessList(char *name)    { 
  assert( name != NULL); 
  kinfo_proc *result; 
  size_t count = 0; 
  result = (kinfo_proc *)malloc(sizeof(kinfo_proc)); 
  if(GetBSDProcessList(&result,&count) == 0) { 
    for (int i = 0; i < count; i++) { 
      kinfo_proc *proc = NULL; 
      proc = &result[i]; 
      }
  } 
  free(result);
}

kinfo_proc结构包含有关进程的所有信息,例如进程标识符(pid)、进程组、进程状态等。


1

我认为大多数这些值都可以在Mach API中找到,但是我已经有一段时间没有在那里研究了。或者,您可以查看“ps”或“top”命令的源代码,看看它们是如何实现的。


0

大部分信息可以从GetProcessInformation()获取。

顺便问一下,为什么要使用虚拟方法来返回进程范围的信息?

这仅适用于CARBON,不适用于cocoa。


请注意,GetProcessInformation() 是一个 Win32 API 函数,而不是 OP 所谈论的 Mac OS X。 - Ben Hoyt
实际上,@benhoyt的链接指向包含名为GetProcessInformation()的函数的Apple文档,但它是一个框架的一部分。 - Shane Holloway
2
GetProcessInformation() 是一个 Mac 调用,但它不测量 CPU 使用率。此外,它已经被弃用。它是来自 Mac 工具箱时代旧的进程管理器的一部分(在 MacOS X 之前)。我不建议在 MacOS X 上使用它。它返回的信息甚至不相关,例如有关进程内存的信息。这是来自 MacOS 9 和更早版本的概念,当时它没有现代虚拟内存。应用程序只直接访问计算机的一个单个内存分区(并且可以修改彼此的内存,而不考虑权限)。不要使用它。 - brant

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接