Macのシステムコール

Mac OS XでPOSIX以外のシステムコールについての情報が中々無かったので、ここに文書化しておく。http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/ このページといくつかのオープソースのソースコードを参考にした。

Load Average を取得

Load averageはhost_load_info構造体のaverun[]というメンバーに格納される。avenrunには5,15,60秒間でのload averageが格納されている。

#include <mach/host_info.h>
#define CPU_STATE_USER     0
#define CPU_STATE_SYSTEM   1
#define CPU_STATE_IDLE     2

struct host_load_info
{
       integer_t        avenrun[3];
       integer_t    mach_factor[3];
};
typedef struct host_load_info* host_load_info_t;

この構造体を用いて有効な値を取得する時には次のhost_info関数を使う

#include <mach/host_info.h>
kern_return_t   host_info
                (host_t                                    host,
                 host_flavor_t                           flavor,
                 host_info_t                          host_info,
                 mach_msg_type_number_t         host_info_count);

hostは情報を得たいhostをさしてるhost_t構造体。flavorは取得する情報の種類を表す。Load averageを取得するときはHOST_LOAD_INFOと指定。
正常に動作したときはhost_infoに値が格納される。尚、この値はLOAD_SCALEという大きさでスケールされている。host_info_countは入力時にはhost_infoの確保しているメモリの大きさ、正常に動作したときは返り値としてのhost_infoの大きさが格納されている。

また、プログラムを実行するマシンに対応したhost_t構造体を得るときは次の関数を使う。

#include <mach/host_info.h>
host_name_port_t   mach_host_self( void );

以下はサンプルコード。

/* load.c 60秒間で平均を取ったload averageを標準出力に表示する。 */

#include <mach/host_info.h>
/* LOAD_SCALE が定義されている */
#include <mach/processor_info.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
  struct host_load_info hl;
  mach_msg_type_number_t count = HOST_LOAD_INFO_COUNT;
  kern_return_t error = host_statistics(mach_host_self(),HOST_LOAD_INFO,(host_info_t)&hl,&count);
  double res = (double)(hl.avenrun[2])/(double)(LOAD_SCALE);
  printf("%lf\n",res);
  return 0;
}

総メモリ量を取得

次のhost_basic_info構造体を用いる。

#include <mach/host_info.h>
struct host_basic_info
{
       integer_t            max_cpus;
       integer_t          avail_cpus;
       vm_size_t         memory_size;
       cpu_type_t           cpu_type;
       cpu_subtype_t     cpu_subtype;
};

前エントリのhost_info関数をflavorをHOST_BASIC_INFOにして実行すると、memory_sizeに総メモリ量が格納される。

/* 総メモリ量を標準出力に表示 */
#include <mach/host_info.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
  struct host_basic_info host;
  mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT;
  host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&host, &count);
  printf("%d\n",host.memory_size);
  return 0;
}

空きメモリ量の取得

空きメモリ量を取得する際にはvm_statistics構造体を用いる。

#include <mach/vm_statistics.h>
struct vm_statistics
{
       integer_t       free_count;
       integer_t       active_count;
       integer_t       inactive_count;
       integer_t       wire_count;
       integer_t       zero_fill_count;
       integer_t       reactivations;
       integer_t       pageins;
       integer_t       pageouts;
       integer_t       faults;
       integer_t       cow_faults;
       integer_t       lookups;
       integer_t       hits;
};

typedef struct vm_statistics* vm_statistics_t;

この構造体のfree_countに空きメモリのページ数が格納される。尚、mach/vm_statistics.hはmach/host_info.hを読み込むと自動的に読み込まれる。
有効な値を取得する為には次のhost_statistics関数を用いる。

#include <mach/host_info.h>
kern_return_t   host_statistics
                (host_priv_t                          host_priv,
                 host_flavor_t                           flavor,
                 host_info_t                          host_info,
                 mach_msg_type_number_t         host_info_count);

host_privは統計情報を取りたいhostを示す。プログラムを実行するマシンの情報を得たいときはmach_host_self()関数を用いる。flavorは取得したい情報を示す。この場合はHOST_VM_INFOを指定する。正常に動作したときはhost_info
に値が格納される。host_info_countは入力時にはhost_infoの確保しているメモリの大きさ、正常に動作したときは返り値としてのhost_infoの大きさが格納されている。
以下はサンプルコード。

/* 空きメモリ量を標準出力に表示する */
#include <mach/host_info.h>
#include <mach/mach_init.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
  struct vm_statistics vm_info;
  mach_msg_type_number_t count = HOST_VM_INFO_COUNT;
  host_statistics(mach_host_self(),HOST_VM_INFO,(host_info_t)&vm_info,&count);
  printf("%d\n",vm_info.free_count*vm_page_size);
  return 0;
}