Linux:为啥内核有的变量没有初始化就敢直接使用?

一口Linux
关注

3)宏展开

将对宏的调用展开成相对应的宏定义

关于宏定义还有很多其他的知识点,本文暂不深入展开。

四、如何快速展开复杂的宏定义?

linux内核中通常有很多宏定义,非常的复杂,对于初学者来说,经常会一头雾水,那如何快速理解宏定义呢?

一口君教你一个非常方便的方法,让你直接看透宏定义,我们以上述代码为例:

第一步将要展开的宏先拷贝到c文件中,然后把所有用到的宏定义都拷贝到该文件中;内核中很多的宏都是嵌套的,把嵌套的宏定义都一起拷贝到文件中;此外内核很多的宏会由条件编译决定,从而导致有多种定义方式,如果不确定,就把条件编译一起拷贝过来,

如该例所示,MAX_NUMNODES 就被嵌套了多级,最终宏CONFIG_NODES_SHIFT在内核中没有检索到,所以该宏没有定义。

文件如下:123.c

1
 2
 3 #ifdef CONFIG_NODES_SHIFT
 4 #define NODES_SHIFT     CONFIG_NODES_SHIFT
 5 #else
 6 #define NODES_SHIFT     0
 7 #endif
 8
 9
10                                                                                                                  
11 #define MAX_NUMNODES    (1 << NODES_SHIFT)
12
13
14
15
16 #if MAX_NUMNODES > 1
17 #define for_each_node_state(__node, __state)
18         for_each_node_mask((__node), node_states[__state])
19 #else
20 #define for_each_node_state(node, __state)
21         for ( (node) = 0; (node) == 0; (node) = 1)
22 #endif
23
24
25
26
27 #define for_each_online_node(node) for_each_node_state(node, N_ONLINE)
28
29
30 static int __build_all_zonelists(void *data)
31 {  
32     int nid;
33     int cpu;
34     pg_data_t *self = data;
35
36    
37
38     for_each_online_node(nid) {
39         pg_data_t *pgdat = NODE_DATA(nid);
40
41         build_zonelists(pgdat);
42         build_zonelist_cache(pgdat);
43     }
44 }
第二步

使用以下命令,展开宏定义,

gcc -E

-E的含义是,编译预处理该文件,但是不去生成汇编代码,只把文件中的宏定义以及包含的头文件替代,并不会去检查语法正确与否。

结果如下:

peng@ubuntu:~/test$ gcc 123.c -E
# 1 "123.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "123.c"
# 28 "123.c"
static int __build_all_zonelists(void *data)

int nid;
int cpu;
pg_data_t *self = data;
for ( (nid) = 0; (nid) == 0; (nid) = 1) {
 pg_data_t *pgdat = NODE_DATA(nid);
 build_zonelists(pgdat);
 build_zonelist_cache(pgdat);

由结果可知,nid是被赋值为0的。

五、练习

我们来做一个练习,展开一下内核的waite_event()这个宏

拷贝用到所有宏定义到c文件中。

wait.c

1
 2 #define ___wait_event(wq, condition, state, exclusive, ret, cmd)    
 3     ({                                  
 4      __label__ __out;                      
 5      wait_queue_t __wait;                      
 6      long __ret = ret;                      
 7      
 8      INIT_LIST_HEAD(&__wait.task_list);            
 9      if (exclusive)                        
10      __wait.flags = WQ_FLAG_EXCLUSIVE;          
11      else
12      {
13       code                          
14      __wait.flags = 0;                  
15      
16      for (;;) {                        
17      long __int = prepare_to_wait_event(&wq, &__wait, state);
18      
19      if (condition)                        
20      break;                    
21      
22      if (___wait_is_interruptible(state) && __int) {        
23      __ret = __int;                
24          if (exclusive) {              
25              abort_exclusive_wait(&wq, &__wait,
26                      state, NULL);  
27                  goto __out;                
28          }                      
29      break;                    
30      }                          
31      
32          cmd;                          
33      }                              
34      finish_wait(&wq, &__wait);                
35          __out: __ret;                              
36      })
37     }
38
39
40
41
42 #define TASK_UNINTERRUPTIBLE    2
43
44
45 #define __wait_event(wq, condition)                
46     (void)___wait_event(wq, condition, TASK_UNINTERRUPTIBLE, 0, 0,  
47             schedule())
48
49

声明: 本文由入驻OFweek维科号的作者撰写,观点仅代表作者本人,不代表OFweek立场。如有侵权或其他问题,请联系举报。
侵权投诉

下载OFweek,一手掌握高科技全行业资讯

还不是OFweek会员,马上注册
打开app,查看更多精彩资讯 >
  • 长按识别二维码
  • 进入OFweek阅读全文
长按图片进行保存