ã¯ããã«
æ¬è¨äºã¯é»åæ¸ç±çãããã¾ãã
linuxã«ã¼ãã«ã¯Cè¨èªã®ãã¯ããé§ä½¿ãã¦æ¸ããã¦ãã¾ãããããã®ãã¡ãåã£ããã¯ãã«ãªãã¿ã®ç¡ã人ã«ã¯åè¦ã§ã¯æå³ãããããªã&ããã£ã¦ã¿ãã°é¢ç½ãã§ããããã®ãããã¤ãç´¹ä»ãããã¾ãã対象èªè ã¯ãCè¨èªã®ã¦ã¼ã¶ã ããã©ãããã¯ãã¯å®æ°å®ç¾©ãããã«ãã使ããªãã¨ããã©ã¤ããªãã¯ãã¦ã¼ã¶ã§ãã
ãã¯ãã使ç¨ããå ´æã«ä¾åããã¨ã©ã¼ãé²ã
次ã®ãã¯ãã¯ãäºã¤ã®å¼ãæ°ã®å¤ãç½®æããã ãã®åç´ãªãã®ã§ãã
#define swap(a, b) \ do { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0)
注ç®ãã¹ãã¯ãã¯ãã®å®ç¾©å
¨ä½ãå²ãã§ããdo { ... } while (0)
ã¨ãã表è¨ã§ããåè¦ã®äººã«ã¯ä½ã®ãã¨ãããããªãã¨æãã¾ããèããããæãåç´ãªå®ç¾©ããé¡ã£ã¦ããªããã®ãããªå®ç¾©ã«ããã¨ããã®ããè¦ã¦ã¿ã¾ãããã
ãã®ãã¯ãã®do {} whileæã®ãããã¯ãå¤ãããã¼ã¸ã§ã³ã®ãã¯ãã使ã£ã¦ã¿ã¾ãããã
#include <stdio.h> #define swap(a, b) \ typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; int main(void) { int a = 0, b = 1; swap(a, b); printf("%d %d\n", a, b); return 0; }
å®è¡ä¾ã示ãã¾ãã
$ make swap cc swap.c -o swap $ ./swap 1 0 $
ã¡ããã¨åãã¦ããããã«è¦ãã¾ããããããããã次ã®ãããªä½¿ãæ¹ã ã¨ãããã§ããããã
#include <stdio.h> #define swap(a, b) \ typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; int main(void) { int a = 0, b = 1; if (0) swap(a, b); printf("%d %d\n", a, b); return 0; }
ã³ã³ãã¤ã«ãã¾ãã
$ make swap2 cc swap2.c -o swap2 swap2.c: In function 'main': swap2.c:4:9: error: expected expression before 'typeof' typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; ^ swap2.c:10:3: note: in expansion of macro 'swap' swap(a, b); ^~~~ swap2.c:4:49: error: '__tmp' undeclared (first use in this function) typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; ... make: *** [swap2] Error 1 $
æå¾ å¤ã¯ifæã®ä¸ã®swap()ãã¯ãã¯å®è¡ããã«ç«¯æ«ä¸ã«"0 1Â¥n"ã¨ããåºåããããã¨ãããã®ã§ãããå®éã¯å±±ã»ã©ã¨ã©ã¼ãåºã¦ã³ã³ãã¤ã«ã失æãã¾ãããã½ã¼ã¹ãã³ã³ãã¤ã«ããã«ããªããã»ããµã ããããã¦åå ãæ¢ã£ã¦ã¿ã¾ãããã
$ cc -E swap2.c ... int main(void) { int a = 0, b = 1; if (0) typeof(a) __tmp = (a); (a) = (b); (b) = __tmp;; printf("%d %d\n", a, b); return 0; } $
ä¸è¦æ£ããããã«è¦ãã¾ãããå¶å¾¡æ§é ãæèãã¦æ´å½¢ãã¦ã¿ãã¨ãããããç¹ãããã£ã¦ãã¾ãã
int main(void) { int a = 0, b = 1; if (0) typeof(a) __tmp = (a); (a) = (b); (b) = __tmp;; printf("%d %d\n", a, b); return 0; }
swap()ãã¯ãå ã®3ã¤ã®å½ä»¤ã®ãã¡ãä¸è¡ç®ã®ä¸æå¤æ°__tmpã宣è¨ãã¦ããè¡ã¯ifæã®ä¸ã«ããã¾ããããã以å¤ã®2å½ä»¤ã¯ifæã®å¤ã«åºã¦ãã¾ã£ã¦ãã¾ããããã§ã¯ã¾ã¨ãã«åãã¯ããããã¾ãããããã«ãifæã®ä¸ã«å¤æ°å®£è¨ã®ã¿ã1è¡ç½®ããã¨ã¯è¨±ãããªãã®ã§ãä¸è¨ã³ã³ãã¤ã«ãã°ã®ä¸è¡ç®ã®ãããªã¨ã©ã¼ãåºã¦ãã¾ãã
ã§ã¯æ¬¡ã®ããã«ãã¯ãå®ç¾©ãåã«ãããã¯("{}")ã§å²ãã°ããã®ã§ã¯ãªãããã¨ãããããããã£ããããã¨æãã®ã§ã試ãã¦ã¿ã¾ãã
#include <stdio.h> #define swap(a, b) \ { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } int main(void) { int a = 0, b = 1; if (0) swap(a, b); printf("%d %d\n", a, b); return 0; }
$ make swap3 cc swap3.c -o swap3 $ ./swap3 0 1 $
ãã¡ãã¯ãã¾ãããã¾ããããããããã¯æ¬¡ã®ãããªã±ã¼ã¹ã§ã¯ãã¾ãããã¾ããã
#include <stdio.h> #define swap(a, b) \ { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } int main(void) { int a = 0, b = 1; if (0) swap(a, b); else printf("Always print this message¥n"); printf("%d %d\n", a, b); return 0; }
$ make swap4 cc swap4.c -o swap4 swap4.c: In function 'main': swap4.c:11:2: error: 'else' without a previous 'if' else ^~~~ <builtin>: recipe for target 'swap4' failed make: *** [swap4] Error 1 $
æå¾ å¤ã¯"Always print this messageÂ¥n"ã®å¾ã«"0 1Â¥n"ãåºåãããããªã®ã§ãããè¬ã®ã³ã³ãã¤ã«ã¨ã©ã¼ãçºçãã¾ãããããã«ã¤ãã¦ãããªããã»ããµã«ããå¦çå¾ã®ã½ã¼ã¹ãè¦ã¦ã¿ã¾ãããã
$ cc -E swap4.c ... # 6 "swap4.c" int main(void) { int a = 0, b = 1; if (0) { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; }; else printf("Always print this message¥n"); printf("%d %d\n", a, b); return 0; }
ããã»ã©ã¨åæ§ã«ãå¶å¾¡æ§é ãæèãã¦ã½ã¼ã¹ãæ´å½¢ãã¾ãã
int main(void) { int a = 0, b = 1; if (0) { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; }; # ... (1) else printf("Always print this message"); printf("%d %d\n", a, b); return 0; }
ãããããã«ããã®ã§ãããã½ã¼ã¹å ã®(1)ã®ã¨ããã§Cã®æ§æä¸ifæã¯å®çµãã¦ãã¾ãããããã£ã¦ãããã«ç¶ãelseç¯ã¯ã³ã³ãã¤ã©ããè¦ãã¨ifæç¡ãã«çªç¶åºã¦ããããã«è¦ãããããã¨ã©ã¼ãåºã¦ããã®ã§ããã
ãã®å ´åã¯swap(a,b);
ã®æ«å°¾ã®ã»ãã³ãã³ãçãã°ãã¾ãåä½ãã¾ãããããããã¯æããã«ç´æçã§ã¯ãªãã®ã§ããã®ãããªä½¿ãæ¹ã¯ã§ããã°é¿ãããã§ããä¸è¨ã®å½ä»¤åãåãªããããã¯ã§ã¯ãªã do {} while (0)ã§å²ãã°ããããå¯è½ã«ãªãã¾ããã³ã¼ãä¾ã¯åºãã¾ãããããã®å ´åã¯ä¸è¨ãã¹ã¦ã®å ´åã«ã¤ãã¦ãã¾ãåä½ãã¾ãã
ä¸è¨ã®ãããªããã¾ããããªãã±ã¼ã¹ããå ¨ã¦ç¥ããªãã¨ããªããªããã® do {} while (0) ã®æå³ã¯ç解ã§ããªãã¨æãã¾ããlinuxã«ã¼ãã«ä»¥å¤ã§ãé »åºã®Cãã¯ãã®ã¤ãã£ãªã ãªã®ã§ãè¦ãã¦ããã¦æã¯ãªãã¨æãã¾ãã
ã¸ã§ããªãã¯ããã°ã©ãã³ã°
ããã»ã©ã®swap()ã®ä¾ãããä¸åº¦è¦ã¦ã¿ã¾ãããã
#define swap(a, b) \ do { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0)
ããã¯ã¤ã³ã©ã¤ã³é¢æ°ã§å®è£ ãã¦ãåãããã«è¦ãã¾ãããå®éãã£ã¦ã¿ãã¨é¢åãªãã¨ããããã¾ãã以ä¸ã®ã³ã¼ããè¦ã¦ä¸ããã
static inline void swap(int *a, int *b) { int tmp = *a; *a = *b; *b = tmp; }
ããã¯ããã§åãã®ã§ãã(å¼æ°ã«å¤æ°ã§ãªãå¤æ°ã¸ã®ãã¤ã³ã¿ãæå®ããªãã¨ãããªãã¨ããã¯ç°ãªãã¾ã)ããã®swap()ã¯intã«ãã使ãã¾ãããå¥ã®åã«ã¤ãã¦ã¯å¥ã®swap()ãå®ç¾©ããå¿ è¦ãããã¾ããããããCã¯é¢æ°ã®ãªã¼ãã¼ãã¼ãæ©è½1ãç¡ããããè¤æ°ã®åã«å¯¾ããswap()ãåæã«å®ç¾©ãããå ´åã¯ãä¾ãã°æ¬¡ã®ããã«å®ç¾©ããå¿ è¦ãããã¾ãã
static inline void swap_int(int *a, int *b) { int tmp = *a; *a = *b; *b = tmp; } static inline void swap_double(double *a, double *b) { int tmp = *a; *a = *b; *b = tmp; }
å¼ã³åºãããã«ãã¡ãã¡ååãæå®ããå¿ è¦ãããä¸ã«ãåããããªæå³ã®ã³ã¼ããéè¤ãã¦æ¸ãå¿ è¦ãããã®ã§ä¿å®æ§ãé常ã«æªãã§ãããã¯ãã使ãã°ãã®ãããªåé¡ãé¿ãããã¾ããã¡ããã©C++ã®ãã³ãã¬ã¼ãã使ã£ãã¸ã§ããªãã¯ããã°ã©ãã³ã°ã®ãããªãã¨ãã§ãã¾ãã
ãã«ãã®è¨å®ã«å¿ãã¦ä½ãããªãé¢æ°/ãã¯ããå®ç¾©ãã
linuxã«ã¼ãã«ã§ã¯ãç¹å®ã®ãã«ãè¨å®ã«ããã¦ãç¹å®ã®é¢æ°ãä½ãããªãããã«å®ç¾©ãã¦ããç®æãå¤ã ããã¾ãã次ã«ç¤ºãå®éã®ã³ã¼ããè¦ã¦ã¿ã¾ãããã
... #if BITS_PER_LONG==32 && defined(CONFIG_SMP) #include <linux/seqlock.h> #define __NEED_I_SIZE_ORDERED #define i_size_ordered_init(inode) seqcount_init(&inode->i_size_seqcount) #else #define i_size_ordered_init(inode) do { } while (0) #endif ...
ãã®ã³ã¼ãæçã¯ãã±ã£ã¨è¦ããããããã§ãããè¨èã§èª¬æããã¨æ¬¡ã®ãããªãã¨ããã¦ãã¾ãã
- i_size_ordered_init()ã¨ãããã¯ããå®ç¾©ãã
- ãã«ã対象ã¢ã¼ããã¯ãã£ã®longã®ãµã¤ãºã32ã§ããããã¤ããã«ãããã»ããµç°å¢ã§ããã°seqcount_init()ãå¼ã¶
- ããã§ãªããã°ä½ãããªã
注ç®ãã¦ãããããã®ã¯i_size_ordered_init()ãã¯ãã®do { } while (0)
ã¨ããå®ç¾©ã§ããããã¯å
ç¨ã®ä¾ã®å¿ç¨ã§ããä½ãããªããé¢æ°/ãã¯ããå®ç¾©ãã¦ãã¾ãã
ãã®ãã¯ããå¼ã³åºãã¦ããç®æã§ãã¡ãã¡
... { ... #if BITS_PER_LONG==32 && defined(CONFIG_SMP) i_size_ordered_init(); #endif ... } ...
ãªã©ã¨ããããã¯ããã«ã³ã¼ãã®ä¿å®æ§ãé«ãã§ãã
ãªãã#define i_size_ordered_init(inode)
(ãã¯ãå®ç¾©ã空ã«ãã)ãã#define i_size_ordered_init(inode) {}
ãªã©ã¨ããå®ç¾©ã«ããã¨ãåè¿°ã®ãããªãã¾ãã¾ãªã³ã¼ãã¼ã±ã¼ã¹ãåå¨ãã¦ãã¾ãã¾ãã
å¼æ°ã®æååå
次ã¯ããã¯ãã®å¼æ°ãæååã«ããæ¹æ³ã«ã¤ãã¦å¦ãã§ã¿ã¾ããããä¾ã¨ãã¦ã以ä¸ã®linuxã«ã¼ãã«å ã®ã³ã¼ãã示ãã¾ãã
... #ifdef CONFIG_SCHED_DEBUG #define SCHED_WARN_ON(x) WARN_ONCE(x, #x) #else ... #endif ...
ããã§ã¯ç°¡åã®ããCONFIG_SCHED_DEBUGãå®ç¾©ããã¦ããã¨èãã¦ãSCHED_WARN_ON()ãã¯ããä½ããããã®ãªã®ããè¦ã¦ããã¾ãããã®ãã¯ãã¯ãã¹ã±ã¸ã¥ã¼ã©ã®ã³ã¼ãã®ä¸ã§ãã¹ã±ã¸ã¥ã¼ã©ãç°å¸¸ãªç¶æ ã§ãããã¨ã示ãæ¡ä»¶ãæºããã(æºããã¦ãã¾ã£ã)ã¨ãã«ã«ã¼ãã«ã®ãã°ã«ãã©ã®æ¡ä»¶æãæç«ãããã示ãè¦åã¡ãã»ã¼ã¸ã表示ããããã®ãã®ã§ãã
SCHED_WARN_ON()ã®ä¸ã§ä½¿ããã¦ããWARN_ONCE()ãã¯ãã¯ã第ä¸å¼æ°ã«æå®ãããæ¡ä»¶ãæºããããã¨ãã«ã第äºå¼æ°ã«æå®ããããããã°ç¨ã¡ãã»ã¼ã¸ãåºåãã¾ã2ã
SCHED_WARN_ON()ãç´ ç´ã«å®è£ ã使ç¨ãããã¨ããã¨æ¬¡ã®ããã«ãªãã¾ã(å®éã®ãã®ã¨ã¯ç°ãªãã¾ã)ã
#define SCHED_WARN_ON(x, msg) WARN_ONCE(x, msg) ... { ... SCHED_WARN_ON(number_of_runnanble_processes < 0, "number_of_runnable_processes < 0"); ... } ...
ããã§ä¸å¿ç®çãéæã§ããã®ã§ãããä¸è¦ãã¦ãããããã«ããªãã ãããµãã§ããåãããã¹ã("number_of_runnable_processes < 0")ãäºåæ¸ããªãã¦ã¯ãããªããããæ¸ãã®ãé¢åãªä¸ã«ãæ¡ä»¶ãå¤ããã¨ãã«ã¡ãã»ã¼ã¸ã®è¿½å¾ãå¿ãããããå¯è½æ§ããããä¿å®æ§ãæªãã§ãããããé¿ããã®ãCãã¯ãã®ãå¼ãæ°ã®æåååæ©è½ã§ãã
å¼æ°ã®æåååæ©è½ã¯ããã¯ãã®å¼æ°ã®åã«"#"ã¨ããæ¼ç®åãä»ãããã¨ã«ãã£ã¦å®ç¾ãã¾ãããã¨ãã°#define tokenize(a) #a
ã¨ãã¯ããå®ç¾©ããã¨ãtokenize(test)
ã¯"test"
ã¨è©ä¾¡ããã¾ããä¸è¨ã®å®éã®SCHED_WARN_ON()ã¯ããããå¿ç¨ãã¦ã第ä¸ãããã¦å¯ä¸ã®å¼æ°ã«æ¡ä»¶æã渡ããã¨ã§ãå½è©²æ¡ä»¶ãæºãããéã«ãæ¡ä»¶å¼ã示ãæååããã°ã«åºåã§ãã¾ãã
å®éã®ä½¿ç¨ä¾ã¯æ¬¡ã®éãã§ãã
... #define SCHED_WARN_ON(x) WARN_ONCE(x, #x) ... static inline struct cpuidle_state *idle_get_state(struct rq *rq) { SCHED_WARN_ON(!rcu_read_lock_held()); return rq->idle_state; } ...
cpuidle_state()é¢æ°ã®å®ç¾©ã¯ããªããã»ããµã«ãã£ã¦æ¬¡ã®ããã«å¤æããã¾ãã
static inline struct cpuidle_state *idle_get_state(struct rq *rq) { WARN_ONCE(!rcu_read_lock_held(), "!rcu_read_lock_held()"); return rq->idle_state; }
ä¸è¨ã®ç´ ç´ãªå®è£ ä¾ããã¯ããã«æ¸ãã®ã楽ã§ããã¤ä¿å®æ§ã®é«ãã³ã¼ãã«ãªããã¨ããããã¾ãã
ãã¼ã¯ã³ã®é£çµ
Cã®ãã¯ãå®ç¾©ã®ä¸ã§ã¯ã2ã¤ã®ãã¼ã¯ã³3ã®é£çµã«ãã£ã¦æ°ããªãã¼ã¯ã³ãçæã§ãã¾ããããã¯æååã®é£çµã¨ã¯å ¨ãç°ãªãã¾ãã以ä¸ã®ãµã³ãã«ã³ã¼ããããããã ããã
#define concat_token(a) \ static int func_##a(void) \ { \ return 0; \ } concat_token(foo) int main(void) { return func_foo(); }
å
é ã®concat_token()ãã¯ãã®å®ç¾©ã®ä¸ã®func_##a
ã¨ããç®æã«æ³¨ç®ãã¦ãã ãããããã¯"func_"ã¨ãããã¼ã¯ã³ã¨ãå¼æ°aã§ç¤ºãããã¼ã¯ã³ã®2ã¤ãé£çµãããã¼ã¯ã³ãä½ãã¨ããæå³ã§ããå¤åæå³ä¸æã ã¨æãã®ã§ãå®ä¾ãè¦ã¦ã¿ã¾ãããã
conat_token(foo)ãè©ä¾¡ããå ´åãfunc_##a
ã¯func_foo
ã«ãªãã¾ãããã®å¾ããã¯ãå
¨ä½ã®è©ä¾¡çµæã¯æ¬¡ã®ããã«ãªãã¾ãã
static int func_foo(void) \ { \ return 0; \ }
ã½ã¼ã¹å ¨ä½ãããªããã»ããµã«ããã¦ã¿ã¾ãããã
$ cc -E concat_token.c ... static int func_foo(void) { return 0; } int main(void) { return func_foo(); } $
func_foo()ã¨ããé¢æ°ãå®ç¾©ããã¦ãããã¨ããããã¾ããã¤ã¾ããã®ãã¯ãã¯ãå¼ãæ°ã«æå®ãããã¼ã¯ã³(ããã§ã¯"foo")ãå«ãé¢æ°ãå®ç¾©ãããã®ã§ãããã¨ããããã¾ãã
ããã ãã§ã¯ç¨éããããã«ããã®ã§ãlinuxã«ã¼ãã«å ã®ä½¿ç¨ä¾ãè¦ã¦ã¿ã¾ãããã
... #define EXT4_FEATURE_COMPAT_FUNCS(name, flagname) \ static inline bool ext4_has_feature_##name(struct super_block *sb) \ { \ return ((EXT4_SB(sb)->s_es->s_feature_compat & \ cpu_to_le32(EXT4_FEATURE_COMPAT_##flagname)) != 0); \ } \ static inline void ext4_set_feature_##name(struct super_block *sb) \ { \ EXT4_SB(sb)->s_es->s_feature_compat |= \ cpu_to_le32(EXT4_FEATURE_COMPAT_##flagname); \ } \ static inline void ext4_clear_feature_##name(struct super_block *sb) \ { \ EXT4_SB(sb)->s_es->s_feature_compat &= \ ~cpu_to_le32(EXT4_FEATURE_COMPAT_##flagname); \ } ...
ä¸è¦è¤éã§ãããå®ã¯ãã£ã¦ãããã¨ã¯åç´ã§ããããã¯ext4ãã¡ã¤ã«ã·ã¹ãã å ã®åæ©è½(mkfs.ext4(8)ãtune2fs(8)ã®-Oãªãã·ã§ã³ã«ãã£ã¦æå¹/ç¡å¹ãè¨å®)ã«é¢ããé¢æ°ãä¸æ¬å®ç¾©ããããã®ãã¯ãã§ãã第ä¸å¼æ°nameã示ãæ©è½ã«ã¤ãã¦ã第äºå¼æ°flagnameã«ãã£ã¦ç¤ºããã©ã°ãæä½ãããä¸é£ã®é¢æ°ãå®ç¾©ãã¾ãã
ä¾ãã°æ¬¡ã®ããã«ä½¿ç¨ãã¾ãã
EXT4_FEATURE_COMPAT_FUNCS(dir_prealloc, DIR_PREALLOC)
ããã¯æ¬¡ã®ããã«å±éããã¾ãã
... static inline bool ext4_has_feature_dir_prealloc(struct super_block *sb) \ { \ return ((EXT4_SB(sb)->s_es->s_feature_compat & \ cpu_to_le32(EXT4_FEATURE_COMPAT_DIR_PREALLOC)) != 0); \ } \ static inline void ext4_set_feature_dir_prealloc(struct super_block *sb) \ { \ EXT4_SB(sb)->s_es->s_feature_compat |= \ cpu_to_le32(EXT4_FEATURE_COMPAT_DIR_PREALLOC); \ } \ static inline void ext4_clear_feature_dir_prealloc(struct super_block *sb) \ { \ EXT4_SB(sb)->s_es->s_feature_compat &= \ ~cpu_to_le32(EXT4_FEATURE_COMPAT_DIR_PREALLOC); \ }
ä¸è¨3ã¤ã®é¢æ°ã®å®ç¾©ã¯ãããã次ã®éãã§ãã
- ext4_has_feature_dir_prealloc: å¼æ°sbã§æå®ããext4ãã¡ã¤ã«ã·ã¹ãã ãdir_preallocæ©è½4ãæã£ã¦ãããã©ãããå¤å®
- ext4_set_feature_dir_prealloc: åæ©è½ãæå¹å
- ext4_clear_feature_dir_prealloc: åæ©è½ãç¡å¹å
ä¸è¦3ã¤ã®é¢æ°ããã¯ãå ã§å®ç¾©ãããªã©ã¨ããåããã©ããã¨ãããã«ç´æ¥å®ç¾©ããã»ããç°¡åããã«è¦ãã¾ãããåããããªå®ç¾©ãä½åº¦ãç¶ããããªå ´åã«ãã®ãã¯ãã¯å¤§ããªå¨åãçºæ®ãã¾ããå®éãext4ã®dir_prealloc以å¤ã®æ§ã ãªæ©è½ã«ã¤ãã¦åæ§ãªå®ç¾©ãå¿ è¦ã§ãããããããã«ã¤ãã¦ä¸è¨ã®EXT4_FEATURE_COMPAT_FUNCS()ãã¯ã5ã§ä¸æ¬å®ç¾©ãã¦ãã¾ããããã«ãã£ã¦è¨å¤§ãªéã®æ©æ¢°çãªã¤ã¾ããªãã³ã¼ãã£ã³ã°ãæ¸ããã¾ãã
EXT4_FEATURE_COMPAT_FUNCS(dir_prealloc, DIR_PREALLOC) EXT4_FEATURE_COMPAT_FUNCS(imagic_inodes, IMAGIC_INODES) EXT4_FEATURE_COMPAT_FUNCS(journal, HAS_JOURNAL) EXT4_FEATURE_COMPAT_FUNCS(xattr, EXT_ATTR) EXT4_FEATURE_COMPAT_FUNCS(resize_inode, RESIZE_INODE) EXT4_FEATURE_COMPAT_FUNCS(dir_index, DIR_INDEX) EXT4_FEATURE_COMPAT_FUNCS(sparse_super2, SPARSE_SUPER2)
ãã¼ã¯ã³ã®é£çµã¯ä¸è¦ä¾¿å©ããã§ãããcscopeãªã©ã®ãã¼ã«ãããã¯ãã«ãã£ã¦çæãããå¤æ°ãé¢æ°ããã¾ãèªèãã¦ãããã«ãã½ã¼ã¹ã³ã¼ããªã¼ãã£ã³ã°ãé¢åã«ãªããªã©ã¨ããæ¬ ç¹ãããã¾ããcscopeãªã©ã使ã£ã¦é¢æ°ããã¯ãã®å®ç¾©ãæ¢ãã¦ãå ¨ãåºã¦ããªãã¨ããå ´åã¯ã##æ¼ç®åã使ã£ã¦å®ç¾©ããããã®ã§ãããã©ãããçã£ã¦ã¿ãã¨ããã¨æãã¾ãã
æ§é ä½ã®ãã£ã¼ã«ãããããããåãè¾¼ãã 親æ§é ä½ã¸ã®ãã¤ã³ã¿ãå¾ã
次ã«ç¤ºãã®ã¯ãããæ§é ä½ã®ãã£ã¼ã«ãããããããåãè¾¼ãã§ãã親æ§é ä½ã¸ã®ãã¤ã³ã¿ãå¾ããã¯ãã§ãã
/** * container_of - cast a member of a structure out to the containing structure * @ptr: the pointer to the member. * @type: the type of the container struct this is embedded in. * @member: the name of the member within the struct. * */ #define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );})
ptr(第ä¸å¼æ°)ãmember(第ä¸å¼æ°)ã¨ãããã£ã¼ã«ãåã§åãè¾¼ã¾ããtype(第äºå¼æ°)åã®ãã¼ã¿ã®ã¢ãã¬ã¹ãæ±ãã¾ããã¾ãã¯ãã©ããã£ã¦ãã®ãããªæ©è½ãå®è£ ãã¦ãããããããããç´è§£ãã¦ããã¾ãã
container_of()ã®ä¸ã«ããoffsetof()ã®å®ç¾©ã示ãã¾ã6ã
... #define offsetof(TYPE, MEMBER) ((size_t)&((TYPE *)0)->MEMBER) ...
ãã®ãã¯ãã«ãã£ã¦ãTYPE(第ä¸å¼æ°)ã§ç¤ºãããæ§é ä½ã®ä¸ã®MEMBER(第äºå¼æ°)ãã£ã¼ã«ãã®ãã¤ãåä½ã®ãªãã»ãããæ±ãããã¾ãããã®ãã¯ãã¯ãã¼ãçªå°ã«é ç½®ããTYPEåãã¼ã¿ã®ä¸ã®MEMBERãã£ã¼ã«ãã®ã¢ãã¬ã¹(ãsize_tåã«ãã£ã¹ããããã®)ã¯TYPEå ã®MEMBERã®ãªãã»ããã«çããã¨ããæ§è³ªãå©ç¨ãã¦ãã¾ããããã£ã¦ãã¾ãã°ç°¡åãªã®ã§ãããåè¦ã§ã¯ãã£ããæå³ä¸æã§å¼ãã¦ãã¾ãããããã¾ããã
ãããè¸ã¾ãã¦container_of()ã®å®ç¾©ãå度è¦ã¦ã¿ã¾ãããã
... #define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );})
ä¸è¡ç®ã¯ã¡ãã£ã¨åããã©ãè¦ãã¾ãããåã« mptrå¤æ°ã«ptr(第ä¸å¼æ°)ã代å
¥ãã¦ããã ãã§ããäºè¡ç®ã§ã¯ mptr(ããªãã¡ptr)ãããtypeå
ã®memberã®ãªãã»ãããå¼ãã¦ãã¾ããã¤ã¾ããããã§ptrã®åãè¾¼ã¿å
ã§ããtypeåã®ãã¼ã¿ãæ±ã¾ã£ã¦ãã¾ãã¨ãããã¨ã§ããä¸è¦ä¸è¡ç®ãçãã¦äºè¡ç®ã(type *)((char *)ptr - offsetof(type,member))
ã ãã«ããã°æ¸ã¿ããã«è¦ãã¾ãããä¸è¡ç®ã«ãã£ã¦ãptrã¨memberã®åã®å¯¾å¿ãåãã¦ããªãå ´åã«è¦åã¡ãã»ã¼ã¸ãåºãããã«ãªã£ã¦ãããæãã¬ãã°ãé²ããããã«ãªã£ã¦ãã¾ãã
ä¾ã«ãã£ã¦ãããã ãã§ã¯ä½ãå¬ããã®ãããããããªãã®ã§ãlinuxã«ã¼ãã«ã®ãã¡ã¤ã«ã·ã¹ãã ã®ã³ã¼ããå®ä¾ã¨ãã¦ç´¹ä»ãã¾ãã
linuxã«ã¼ãã«ã«ããã¦ããã¡ã¤ã«ã·ã¹ãã ã®ã³ã¼ãã¯Virtual File System層(以å¾VFS層ã¨è¨è¼)ã¨ããå ¨ãã¡ã¤ã«ã·ã¹ãã (ext4, XFS, Btrfsãªã©)å ±éã®ã³ã¼ãã¨ãåãã¡ã¤ã«ã·ã¹ãã åºæã®ã³ã¼ãã«åããã¦ãã¾ãããã¨ãã°å ¨ãã¡ã¤ã«ã·ã¹ãã ã«å ±éããinodeã«é¢ããæ å ±ã¯VFS層ã«åå¨ããstruct inodeã¨ããæ§é ä½ã«ãã£ã¦è¡¨ç¾ãã¾ããããã«å¯¾ãã¦ãåãã¡ã¤ã«ã·ã¹ãã ã¯ãèªèº«åºæã®inodeæ å ±ãå«ãæ§é ä½ãæã£ã¦ããããã®ä¸ã«struct inodeãåãè¾¼ãã§ãã¾ãã
Btrfsãä¾ã«ã¨ã£ã¦èª¬æããã¨ãbtrfsåºæã®inodeæ å ±ã¯struct btrfs_inodeæ§é ä½ã«æ ¼ç´ããã¾ãããã®ãã¡ãã¡ã¤ã«ã·ã¹ãã å ±éã®é¨åãã¤ã¾ãããã»ã©è¿°ã¹ãstruct inodeã¯ããã®æ§é ä½ã®ä¸ã®vfs_inodeã¨ãããã£ã¼ã«ãã¨ãã¦åãè¾¼ã¾ãã¦ãã¾ãã
... struct btrfs_inode { ... struct inode vfs_inode; }; ...
Btrfså ã®inodeã®å種æå»([cma]time)ãæ´æ°ããéã¯ãVFS層ããbtrfs_update_time()ã¨ããé¢æ°ãå¼ã°ãã¾ãã
static int btrfs_update_time(struct inode *inode, struct timespec *now, int flags) { struct btrfs_root *root = BTRFS_I(inode)->root; ... }
ãã®é¢æ°ã®ã¤ã³ã¿ã¼ãã§ã¤ã¹ã¯Btrfsãå«ãåã ã®ãã¡ã¤ã«ã·ã¹ãã ã§ã¯ãªãVFS層ã«ãã£ã¦å®ç¾©ããã¦ãã¾ãã®ã§ããã®å¼ãæ°ã«ãã£ã¦æ¸¡ãããinodeæ å ±ã¯å¿ ç¶çã«struct btrfs_inodeã§ã¯ãªããstruct inodeã«ãªãã¾ããããããBtrfsã¨ãã¦ã¯æå»ã®æ´æ°ã«ä¼´ã£ã¦å¾è ã ãã§ã¯ãªãåè ã®æ å ±ã使ã£ã¦å¦çãããå¿ è¦ãããã¾ãã
ã§ã¯ã©ãããã°ãããã¨ããã¨ãããã§container_of()ãç»å ´ãã¾ããbtrfs_update_time()åé ã®BTRFS_I()ã®ä¸ã§ãcontainer_of()ãå¼ã³åºããã¨ã«ãã£ã¦ãinode(第ä¸å¼æ°)ãvfs_inode(第ä¸å¼æ°)ã¨ãããã£ã¼ã«ãåã§åãè¾¼ãã§ããstruct btrfs_inode(第äºå¼æ°)ã®ã¢ãã¬ã¹ãæ±ãã¾ãã
static inline struct btrfs_inode *BTRFS_I(struct inode *inode) { return container_of(inode, struct btrfs_inode, vfs_inode); ... }
å¾ã¯æ±ããstruct btrfs_inodeã®ãã¼ã¿ã¸ã®ãã¤ã³ã¿ã使ã£ã¦ç²ã ã¨å¦çãããã ãã§ããå ·ä½çã«ã©ãããå¦çããããã¯æ¬æ¸ã®å¯¾è±¡ç¯å²å¤ãªã®ã§å²æãã¾ãã
ãªã¹ãæä½
linuxã«ã¼ãã«ã¯ããã®ä¸ã«struct list_headã¨ããæ§é ä½ã«ãã£ã¦ç®¡çããåæ¹åãªã¹ãã®å®è£ ãæã£ã¦ãã¾ãããã®ãªã¹ãã¯ä¾ã«ãã£ã¦ãCè¨èªã®ãã¯ããæ大éã«æ´»ç¨ãã¦å®è£ ããã¦ãã¾ãããã®ç¯ã§ã¯ãã®å®è£ ã«ã¤ãã¦æ±ãã¾ãã
ãªã¹ãã«ã¤ãã¦ã®åºæ¬çãªç¥èã¯ããææ°ã§ããå¥è¨äºã®"ãªã¹ãã®æ§é "ã¨ããç¯ã«æ¸ãã¦ãã¾ãã®ã§ããã¡ããåç §ãã¦ãã ãããçããåç´ãªã®ã§ãçæéã§èªããã¨æãã¾ãã
ãªã¹ããå¦çããããã®ãã¯ãã¯å¤ãããã¾ãããããã§ã¯ãã®ä¸ã§ãã¯ããæ´»ç¨ãã¦ããå¦çã«ã¤ãã¦2ã¤ç´¹ä»ãã¾ãã
ã¾ãã¯æå®ããstruct list_headã®ãã¼ã¿ããããããåãè¾¼ãã 親æ§é ä½ãæ±ããlist_entry()ãã¯ãã§ãã
/** * list_entry - get the struct for this entry * @ptr: the &struct list_head pointer. * @type: the type of the struct this is embedded in. * @member: the name of the list_head within the struct. */ #define list_entry(ptr, type, member) \ container_of(ptr, type, member)
ããã¯å®ç¾©ãèããã ãã§ãã³ã¨æ¥ãããããã¾ããããå é¨ã§container_of()ãå¼ã³åºãã¦ããã ãã§ããããã§ptr(第ä¸å¼æ°)ãmember(第ä¸å¼æ°)ã¨ãããã£ã¼ã«ãåã§åãè¾¼ãã§ããtypeåã®ãã¼ã¿ã¸ã®ãã¤ã³ã¿ãç²å¾ã§ãã¾ãã
ç¶ãã¦ããªã¹ãå ã®å ¨ã¨ã³ããªãé çªã«å¦çããlist_for_each_entry()ãã¯ããè¦ã¦ã¿ã¾ãã
/** * list_for_each_entry - iterate over list of given type * @pos: the type * to use as a loop cursor. * @head: the head for your list. * @member: the name of the list_head within the struct. */ #define list_for_each_entry(pos, head, member) \ for (pos = list_first_entry(head, typeof(*pos), member); \ &pos->member != (head); \ pos = list_next_entry(pos, member))
ãã®é¢æ°ã¯ãheadã§ç¤ºããããªã¹ãã®ä¸ã®å ¨è¦ç´ ã«ã¤ãã¦ãåè¦ç´ ãposã¨ããååã§åãåºããã¨ã«ãã£ã¦ããããã«å¯¾ãã¦å¦çããã¾ããããã§ãposã®ä¸ã§headã«å¯¾å¿ãããªã¹ãã¯memberã¨ãããã£ã¼ã«ãåã§åãè¾¼ã¾ãã¦ãã¾ãã
使ç¨ä¾ã示ãã¾ãããµã³ãã«ããã°ã©ã ã®ä»æ§ã¨ã½ã¼ã¹ã¯æ¬¡ã®éãã§ãã
ä»æ§:
- mylistã¨ãããªã¹ãããã
- mylistå ã®ã¨ã³ããªã¯intåã®nã¨ããååã®å¯ä¸ã®ãã¼ã¿ãæã¤
- mylist_show()ã¯ãmylistå ã®ãã¹ã¦ã®ã¨ã³ããªã«å¯¾ãã¦nãã«ã¼ãã«ãã°ã«åºåãã
static LIST_HEAD(mylist); struct mylist_entry { struct list_head list; int n; }; ... static void mylist_show(void) { struct mylist_entry *e; printk(KERN_ALERT "mylist: show contents\n"); list_for_each_entry(e, &mylist, list) { printk(KERN_ALERT "\t%d\n", e->n); } }
ä¸è¦é¢æ°ã®ããã«è¦ãã list_for_each_entry()ãã¯ããããããã¯ãçãã¦ãã®ä¸ã§å¦çããã¦ããã¨ããã®ã¯Cè¨èªãç¥ã£ã¦ããã°ç¥ã£ã¦ããã»ã©é©ãã¨æãã¾ãããåè¿°ã®ãããªãã¯ãå®ç¾©ããã¦ããã°ãã®ãããªè¸å½ãå¯è½ãªã®ã§ãã
linuxã«ã¼ãã«ã®ä¸ã«ã¯ä»ã«ã"for_each"ã¨ããæååãå«ãååã®é¡ä¼¼ã®ãã¯ããéæã«åºã¦ãã¾ãããã¨ãã°åã¨ã³ããªã®å¦çä¸ã«ã¨ã³ããªã®åé¤ãå¯è½ãªlist_for_each_safe()ãããã¾ããä»ã«ãããªã¹ãã¨ã¯å¥ã®ãã¼ã¿æ§é ã«ãé¡ä¼¼ããAPIãç¨æããã¦ãããã¨ãããã¾ããèå³ãããã°ãããããã®å®ç¾©ãè¦ã¦ã¿ãã¨é¢ç½ãã¨æãã¾ãã
ãããã«
æ¬è¨äºã¯å·çæç¹ã§èªåã®è³å ã«ãã¾ãã¾æ®ã£ã¦ãããã¯ãã«ã¤ãã¦æ¸ããã ããªã®ã§ãä»ã«ãé¢ç½ããã¯ãã¯ãããã§ãããã¨æãã¾ããæãåºãããã¾ã追è¨ããäºå®ã§ããèªè ã®ããããããããããç´¹ä»ãã¦ãããã¨ãããã®ãã¯ãã®æå³ãããããªããã ãã©ããªã©ããã¾ããããæãã¦ããã ããã¨ãä»å¾è¿½è¨ããããããã¾ããã
-
åãååã§å¥ã®å¼æ°ãæ»ãå¤ãæã¤é¢æ°ãå®ç¾©ã§ããæ©è½ãä¾ãã°swap(int a, int b)ã¨swap(double a, double b)ãå ±åã§ãããCã§ããããããã¨ããã¨ãååé¢æ°ã2ã¤å®ç¾©ããã¦ããã¨ããæ¨ã®ã³ã³ãã¤ã«ã¨ã©ã¼ãåºã¾ãã↩
-
æåã«æ¡ä»¶ãæºãããã¨ãã®ã¿åºåããã¾ããããæ ã«
_ONCE
ã¨ããååãä»ãã¦ãã¾ã)ã↩ -
ãã¼ã¯ã³ã¨ããè¨èãããããããªããã°ãããã§ã¯ãªãã¨ãªããã³ã³ãã¤ã©ã«å¤æ°åãé¢æ°åã¨è§£éãããæååã¨èãã¦ããã£ã¦ããã§ãã↩
-
ããã§ã¯æ©è½ãã®ãã®ã®æå³ã¯éè¦ã§ã¯ãªãã®ã§å²æ↩
-
ããæ£ç¢ºã«ã¯ãããã«å ãã¦EXT4_FEATURE_RO_COMPAT_FUNCS()ãã¯ããããã³EXT4_FEATURE_INCOMPAT_FUNCS()ãã¯ããç¨ããã↩
-
å®éã«ã¯ä¸è¨å®ç¾©ãç´æ¥ä½¿ãã®ã§ã¯ãªãã³ã³ãã¤ã©(é常gcc)çµã¿è¾¼ã¿ã®åçæ©è½ã使ãã®ã§ãããç解ãç°¡åã«ããããã«ãã¡ããä¾ã«ä½¿ãã¾ãã↩