黒毛和牛モモバラ切り落し100g298円

iPhoneアプリを作ってます。リリースノートとかごにょごにょとか用ブログです。

sysctlの呼び出し方

iOSに限らず最近の*NIXでシステム情報を取り出す時はsysctl()を使用するのが普通のようですが、使い方を適当にしか理解しておらず「あれどうするんだったっけ?」状態になったので調べてみました。

まず基本的な使い方は、int *型のname引数に取得したい情報のmib(Management Information Base)を配列で渡します。例として"hw.machine"を取得する場合は以下のようになります。

int mib[2] = { CTL_HW, HW_MACHINE };
size_t size;
char *machine;

if (sysctl(mib, 2, NULL, &size, NULL, 0) == -1) {
    /* エラー処理 */
}
machine = malloc(size);
if (machine == NULL) {
    /* エラー処理 */
}
if (sysctl(mib, 2, machine, &size, NULL, 0) == -1) {
    /* エラー処理 */
}
printf("machine: %s\n", machine);
free(machine);

"hw.machine"からmibの配列{ CTL_HW, HW_MACHINE }への変換は脳内変換の他、sysctlnametomib()でも行えます。

int mib[2];
size_t miblen, size;
char *machine;

/* sysctlnametomibで変換 */
miblen = 2;
if (sysctlnametomib("hw.machine", mib, &miblen) == -1) {
    /* エラー処理 */
}

/* 以下は前の例と同じ */
if (sysctl(mib, 2, NULL, &size, NULL, 0) == -1) {
    /* エラー処理 */
}
machine = malloc(size);
if (machine == NULL) {
    /* エラー処理 */
}
if (sysctl(mib, 2, machine, &size, NULL, 0) == -1) {
    /* エラー処理 */
}
printf("machine: %s\n", machine);
free(machine);

またsysctlbyname()を使うことでmibの変換を完全にライブラリに任せることもできます。

size_t size;
char *machine;

if (sysctlbyname("hw.machine", NULL, &size, NULL, 0) == -1) {
    /* エラー処理 */
}
machine = malloc(size);
if (machine == NULL) {
    /* エラー処理 */
}
if (sysctlbyname("hw.machine", machine, &size, NULL, 0) == -1) {
    /* エラー処理 */
}
printf("machine: %s\n", machine);
free(machine);

性能的なことを考えると、"hw.machine"のようにサイズの取得と値の取得で2回呼び出す必要のある場合はsysctl()を使った方が良いと思いますが、intや構造体の値を取得する場合は(1回の呼び出しで済むので)sysctlbyname()を使って可読性を上げた方が良いと思います。