container_ofマクロ


Rev.1を表示中。最新版はこちら

container_ofマクロは、オブジェクトが汎用的な属性と、個々オブジェクトに特化して管理される属性を有する場合で、汎用的属性を特化属性のメンバーとし、それぞれの別の構造体で管理させるも、汎用オブジェクト属性から個別オブジェクト属性を参照可能とするマクロです。代表的な運用としてオブジェクトをリスト管理するリストノードとして使われます。

下記サンプルは、procファイルのinodeからファイルを有するプロセスID等を取得する、struct proc_inodeのカーネル実装イメージのサンプルです。
container.c
#include <stdio.h>
#include <stddef.h>

#define container_of(ptr, type, member) ({                      \
       const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
       (type *)( (char *)__mptr - offsetof(type,member) );})

struct inode {
       int     fd;
};

struct proc_inode {
       int             pid;
       struct  inode   vfs_inode;
};

void    main()
{
       struct  proc_inode      proc_inode;
       struct  inode           *inode;

       inode = &proc_inode.vfs_inode;
       inode->fd=123;
       proc_inode.pid=456;

       get_pid(inode);
}

int     get_pid(struct inode *inode)
{
       printf("   file ID:%d\n", inode->fd);
       printf("process ID:%d\n", container_of(inode, struct proc_inode, vfs_inode)->pid);
       return 0;
}
実効結果
[root@localhost test]# ./a.out
   file ID:123
process ID:456

補足

サンプルのcontainer_ofマクロは以下の様に展開されます。typeof()は引数のstructを定義し、従って、*__mptrは(struct proc_inode *)0)->vfs_inodeの型であるstruct inodeのポインタ変数という事です。そのアドレスからstruct proc_inodeのメンバーとしてのvfs_inodeのstruct proc_inode内の位置を差し引く事で、proc_inodeのアドレスを取得します。
const typeof( ((struct proc_inode *)0)->vfs_inode ) *__mptr = (inode); 
(struct proc_inode *)( (char *)__mptr - offsetof (struct proc_inode, vfs_inode)

inodeからproc_inodeを取得は、PROC_I()でcontainer_ofマクロを展開するだけです。
struct proc_inode {
       struct pid *pid;
       int fd;
       union proc_op op;
       struct proc_dir_entry *pde;
       struct ctl_table_header *sysctl;
       struct ctl_table *sysctl_entry;
       void *ns;
       const struct proc_ns_operations *ns_ops;
       struct inode vfs_inode;
};

static inline struct proc_inode *PROC_I(const struct inode *inode)
{
       return container_of(inode, struct proc_inode, vfs_inode);
}

最終更新 2015/10/03 17:59:34 - north
(2015/10/03 17:59:34 作成)


検索

アクセス数
3575020
最近のコメント
コアダンプファイル - sakaia
list_head構造体 - yocto_no_yomikata
勧告ロックと強制ロック - wataash
LKMからのファイル出力 - 重松 宏昌
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
Adsense
広告情報が設定されていません。