Linuxドライバ_LDD3メモ_カーネルにおけるデータの型
カーネルにおけるデータの型
標準のCのデータ型は、アーキテクチャによってサイズが違います。
jiffyを用いて時間を計算する場合には、必ずHz(1秒ごとのタイマ割り込み数)を用いて時間をスケーリングしましょう。
メモリを操作する場合には、1メモリページがPAGE_SIZEバイトであり、4KBではありません。
バイトオーダー:
・インクルードファイル<asm/byteorder.h>は、
CPUのバイトオーダーに従って、「__BIG_ENDIAN」と「__LITTLE_ENDIAN」のどちらかを定義します。
・#ifdef __LITTLE_ENDIAN条件文の固まりをコーディングしてもよいのですが、
Linuxカーネルはバイトオーダーの変換を扱うマクロセットを定義しています。
マクロ例: cpu_to_le32、le32_to_cpu、be64_to_cpu、le16_to_cpusなど。ポインタの場合は、cpu_to_le32pなど。
データアラインメント:
・多くのアーキテクチャではアラインされていないデータの転送を試みると、例外が発生します。
例外ハンドラでデータ転送を処理すると、処理速度が極端に落ちることになります。
・Linuxでアラインされていないデータにアクセスするときは、下記マクロを使います。
get_unaligned(ptr);
put_unaligned(val, ptr);
・アラインメントに関連する別の問題は、プラットフォーム間におけるデータ構造体の移植性です。
・コンパイラは自動的に構造体に詰め物を挿入して、
対象のCPU上での性能を上げるために全てのフィールドのアラインを揃える点にも注意してください。
ポインタとエラー値:
void *ERR_PTR(long error); //ポインタ型を返す関数は、この関数でエラー値を返すことができます。
long IS_ERR(const void *ptr); //返されたポインタがエラーコードかどうかをテストできます
long PTR_ERR(const void *ptr); //実際にエラーコードを取り出す
リンクリスト:
カーネル開発者は、汎用的に使える双方向の環状リンクリストを実装しています。
リストを操作する場合には、この機能を使うことをお勧めします。
でも、1つのリストを並行して操作する場合には、自分でロックの仕組みを実装する必要があります。
struct list_head { struct list_head *next, *prev; }; //リスト構造体
INIT_LIST_HEAD(&todo_list); //リスト初期化
list_add(struct list_head *new, struct list_head *head); //リスト操作
list_add_tail(struct list_head *new, struct list_head *head);
list_del(struct list_head *entry);
list_del_init(struct list_head *entry);
list_move(struct list_head *entry, struct list_head *head);
list_move_tail(struct list_head *entry, struct list_head *head);
list_for_each(struct list_head *cursor, struct list_head *list)
など。。。
浙公网安备 33010602011771号