【C言語】cpu_set_tデータ構造体とCPU_SETマクロの使い方を教えて!
こういった悩みにお答えします.
本記事の信頼性
- リアルタイムシステムの研究歴12年.
- 東大教員の時に,英語でOS(Linuxカーネル)の授業.
- 2012年9月~2013年8月にアメリカのノースカロライナ大学チャペルヒル校(UNC)コンピュータサイエンス学部で客員研究員として勤務.C言語でリアルタイムLinuxの研究開発.
- プログラミング歴15年以上,習得している言語: C/C++,Python,Solidity/Vyper,Java,Ruby,Go,Rust,D,HTML/CSS/JS/PHP,MATLAB,Verse(UEFN), Assembler (x64,ARM).
- 東大教員の時に,C++言語で開発した「LLVMコンパイラの拡張」,C言語で開発した独自のリアルタイムOS「Mcube Kernel」をGitHubにオープンソースとして公開.
- 2020年1月~現在はアメリカのノースカロライナ州チャペルヒルにあるGuarantee Happiness LLCのCTOとしてECサイト開発やWeb/SNSマーケティングの業務.2022年6月~現在はアメリカのノースカロライナ州チャペルヒルにあるJapanese Tar Heel, Inc.のCEO兼CTO.
- 最近は自然言語処理AIとイーサリアムに関する有益な情報発信に従事.
- (AI全般を含む)自然言語処理AIの論文の日本語訳や,AIチャットボット(ChatGPT,Auto-GPT,Gemini(旧Bard)など)の記事を50本以上執筆.アメリカのサンフランシスコ(広義のシリコンバレー)の会社でプロンプトエンジニア・マネージャー・Quality Assurance(QA)の業務委託の経験あり.
- (スマートコントラクトのプログラミングを含む)イーサリアムや仮想通貨全般の記事を200本以上執筆.イギリスのロンドンの会社で仮想通貨の英語の記事を日本語に翻訳する業務委託の経験あり.
こういった私から学べます.
C言語を独学で習得することは難しいです.
私にC言語の無料相談をしたいあなたは,公式LINE「ChishiroのC言語」の友だち追加をお願い致します.
私のキャパシティもあり,一定数に達したら終了しますので,今すぐ追加しましょう!
独学が難しいあなたは,元東大教員がおすすめするC言語を学べるオンラインプログラミングスクール5社で自分に合うスクールを見つけましょう.後悔はさせません!
目次
cpu_set_tデータ構造体
cpu_set_tデータ構造体は,CPU集合を表現します.
CPU集合は,どのCPUが何の操作を許可しているのかをビットマップ(CPU ID毎に操作の許可を0と1で表現)の配列として管理します.
cpu_set_tデータ構造体の定義は,以下になります.
ここで,__cpu_maskはアーキテクチャ依存ですが,unsigned long(64ビットOSでは8バイト)の可能性が高いです.
1 2 3 4 5 6 7 8 9 |
/* Size definition for CPU sets. */ #define __CPU_SETSIZE 1024 #define __NCPUBITS (8 * sizeof (__cpu_mask)) /* Data structure to describe CPU mask. */ typedef struct { __cpu_mask __bits[__CPU_SETSIZE / __NCPUBITS]; } cpu_set_t; |
参考までに,__cpu_maskとcpu_set_tのバイトサイズをsizeof演算子で表示するコードは以下になります.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ #define _GNU_SOURCE #include <stdio.h> #include <sched.h> int main(void) { printf("sizeof(__cpu_mask) = %zu\n", sizeof(__cpu_mask)); printf("sizeof(cpu_set_t) = %zu\n", sizeof(cpu_set_t)); return 0; } |
私のPC(Intel64ビットCPU,Ubuntu 22.04 LTS)での実行結果は以下になります.
__cpu_maskは8バイト,cpu_set_tは128バイト(__CPU_SETSIZE / __NCPUBITS = 1024 / (8 * 8) = 16)であることがわかります.
1 2 3 4 |
$ gcc __cpu_mask.c $ a.out sizeof(__cpu_mask) = 8 sizeof(cpu_set_t) = 128 |
CPU_SETマクロ
cpu_set_tデータ型構造体はビットマスクとして実装されています.
しかし,このデータ構造体はその実装を意識せずに扱うべきです.
そこで,CPU集合のすべての操作は,以下のCPU_SET等のマクロを利用します.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
void CPU_ZERO(cpu_set_t *set); void CPU_SET(int cpu, cpu_set_t *set); void CPU_CLR(int cpu, cpu_set_t *set); int CPU_ISSET(int cpu, cpu_set_t *set); int CPU_COUNT(cpu_set_t *set); void CPU_AND(cpu_set_t *destset, cpu_set_t *srcset1, cpu_set_t *srcset2); void CPU_OR(cpu_set_t *destset, cpu_set_t *srcset1, cpu_set_t *srcset2); void CPU_XOR(cpu_set_t *destset, cpu_set_t *srcset1, cpu_set_t *srcset2); int CPU_EQUAL(cpu_set_t *set1, cpu_set_t *set2); cpu_set_t *CPU_ALLOC(int num_cpus); void CPU_FREE(cpu_set_t *set); size_t CPU_ALLOC_SIZE(int num_cpus); void CPU_ZERO_S(size_t setsize, cpu_set_t *set); void CPU_SET_S(int cpu, size_t setsize, cpu_set_t *set); void CPU_CLR_S(int cpu, size_t setsize, cpu_set_t *set); int CPU_ISSET_S(int cpu, size_t setsize, cpu_set_t *set); int CPU_COUNT_S(size_t setsize, cpu_set_t *set); void CPU_AND_S(size_t setsize, cpu_set_t *destset, cpu_set_t *srcset1, cpu_set_t *srcset2); void CPU_OR_S(size_t setsize, cpu_set_t *destset, cpu_set_t *srcset1, cpu_set_t *srcset2); void CPU_XOR_S(size_t setsize, cpu_set_t *destset, cpu_set_t *srcset1, cpu_set_t *srcset2); int CPU_EQUAL_S(size_t setsize, cpu_set_t *set1, cpu_set_t *set2); |
- CPU_ZERO(set):set をクリアする.集合には何もCPUが含まれない状態となる.
- CPU_SET(cpu, set):setにcpuを追加する.cpuがsetに含まれていれば0以外を返し,含まれない場合は0を返します.
- CPU_CLR(cpu, set):setからcpuを削除する.
- CPU_ISSET(cpu, set):cpuがsetのメンバであるかを検査する.
- CPU_COUNT(set):setに含まれるCPU数を返す.
cpu引数を指定する場合,その引数でマクロを利用してはいけません.
なぜなら上記のマクロは引数を複数回評価する可能性があるからです.
以下のマクロは,CPU集合同士の論理操作を行います.
- CPU_AND(destset, srcset1, srcset2):集合srcset1とsrcset2の積集合をdestsetに格納する.
- CPU_OR(destset, srcset1, srcset2):集合srcset1とsrcset2の和集合をdestsetに格納する.
- CPU_XOR(destset, srcset1, srcset2):集合srcset1とsrcset2のXORをdestsetに格納する.
- CPU_EQUAL(set1, set2):2つのCPU集合が全く同じCPUを含んでいるかを検査する.2つのCPU集合が等しければ0以外を返し,等しくない場合は0を返します.
※ここで,CPU_AND,CPU_OR,CPU_XROマクロでは,元の集合のいずれかがdestsetとして利用される可能性があることに注意して下さい.
CPU集合の大きさを動的に割り当てることがあるため,以下のマクロでCPU集合の割り当てと解放を行います.
- CPU_ALLOC(num_cpus):0からnum_cpus-1までの範囲のCPUを保持するのに十分な大きさのCPU集合を割り当てます.成功すると割り当てたメモリ領域の先頭アドレス(ポインタ)を返し,失敗するとNULLを返します.
- CPU_ALLOC_SIZE(num_cpus):0からnum_cpus-1までの範囲のCPUを保持するのに必要なCPU集合の大きさをバイト数で返します.このマクロが返す値は,後述のCPU_*_S()マクロのsetsize引数として利用できます.
- CPU_FREE(set):前にCPU_ALLOC()で割り当てられた CPU集合setを解放します.
名前が"_S"で終わるマクロは"_S"なしの同じ名前のマクロと同等です.
これらのマクロは"_S"なしのものと同じ動作をしますが,動的に割り当てられた大きさがsetsizeバイトのCPU集合に対して操作をする点が異なります.
また,これらのマクロはLinux固有であることに注意して下さい.
cpu_set_tデータ構造体とCPU_SETマクロの使い方
cpu_set_tデータ構造体とCPU_SETマクロの使い方を紹介します.
以下のコードで利用するマクロは以下になります.
- CPU_ISSET
- CPU_ALLOC
- CPU_ALLOC_SIZE
- CPU_ZERO_S
- CPU_SET_S
- CPU_FREE
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ #define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <sched.h> void print_cpu_isset(int cpu, cpu_set_t *cpusetp) { if (CPU_ISSET(cpu, cpusetp)) { printf("CPU %d is set.\n", cpu); } else { printf("CPU %d is not set.\n", cpu); } } int main(int argc, char *argv[]) { cpu_set_t *cpusetp; size_t size; int num_cpus; if (argc != 2) { fprintf(stderr, "Usage: %s <num-cpus>\n", argv[0]); exit(1); } num_cpus = atoi(argv[1]); if ((cpusetp = CPU_ALLOC(num_cpus)) == NULL) { perror("CPU_ALLOC"); exit(2); } size = CPU_ALLOC_SIZE(num_cpus); printf("size = %zu\n", size); CPU_ZERO_S(size, cpusetp); print_cpu_isset(0, cpusetp); CPU_SET_S(0, size, cpusetp); print_cpu_isset(0, cpusetp); CPU_FREE(cpusetp); return 0; } |
実行結果は以下になります.
1 2 3 4 5 6 7 |
$ gcc cpu_set_t.c $ a.out 1 size = 8 CPU 0 is not set. CPU 0 is set. $ a.out -100 CPU_ALLOC: Cannot allocate memory |
まとめ
cpu_set_tデータ構造体とCPU_SETマクロの使い方を紹介しました.
CPU_SETマクロはCPU集合を操作するために利用します.
cpu_set_tデータ構造体とCPU_SETマクロは,以下の記事で利用しています.
C言語を独学で習得することは難しいです.
私にC言語の無料相談をしたいあなたは,公式LINE「ChishiroのC言語」の友だち追加をお願い致します.
私のキャパシティもあり,一定数に達したら終了しますので,今すぐ追加しましょう!
独学が難しいあなたは,元東大教員がおすすめするC言語を学べるオンラインプログラミングスクール5社で自分に合うスクールを見つけましょう.後悔はさせません!