Linux的内核编译用O0是编译不过的

最近在ATF的升级过程中遇到了一个编译问题,最后是通过编译优化解决的,然后一百度这个优化全是在Linux中的。于是就借着Linux编译优化来学学。

内容来自 宋宝华老师: 关于Linux编译优化几个必须掌握的姿势

1、编译选项和内核编译

首先我们都知道,Linux内核如果用O0编译,是无法编译过的,Linux的内核编译,要么是O2,要么是Os,这点从Linux的Makefile里面可以看出:

在这里插入图片描述
当选择了

CONFIG_CC_OPTIMIZE_FOR_SIZE

它会是Os,否则就是O2。

那么这两个是什么?

其实O2和Os,都是一些优化选项的集合:

gcc -c -Q -O2 --help=optimizers > /tmp/O2-opts

gcc -c -Q -Os --help=optimizers > /tmp/Os-opts

前者倾向于基于速度的优化,后者倾向于基于size更小的优化。对比二者的开关选项:

meld /tmp/O2-opts |VS| /tmp/Os-opts

发现差异小的可怜:

在这里插入图片描述
在这里插入图片描述
O2和Os都使能了inline small函数和called once的函数,但是O2里面-finline-functions是关闭的,而Os里面是开的

O2里面optimize-strlen是开的,Os里面这个选项是关闭的。

相关选项的含义可以通过**"man gcc"看出(有问题,找男人)**,譬如man gcc后检索inline-functions:

在这里插入图片描述
从O0到O1,O2,O3,是一个开启的优化选项逐步加大的过程:

在这里插入图片描述

kernel用O0编译不过,是因为kernel本身也没有想用O0能够编译过,它的设计里面包含了编译会优化的假想。下面我们用一个简单的例子来说明。

举个栗子

一个简单的例子

下面的代码:

在这里插入图片描述
O0编译会报如下错,说f()函数没有定义:

$ gcc -O0 cc.c
cc.c:1:13: warning: ‘f’ used but never defined [enabled by default]

 void f(void);

             ^

/tmp/ccTwwtHG.o: In function `main':

cc.c:(.text+0x19): undefined reference to `f'

collect2: error: ld returned 1 exit status

但是用O2编译,则没有问题:

$ gcc -O2 cc.c

原因在于,O2编译,它意识到a==1,所以if(a>2),它不会成立,所以f()没有定义也没有关系。

把代码稍微改一下后:

O2这个时候也不行了:

$ gcc -O2 cc.c
/tmp/ccXiyBHn.o: In function `main':

cc.c:(.text.startup+0x7): undefined reference to `f'

collect2: error: ld returned 1 exit status

所以,通过这个例子,大家可以看出来为什么同样的代码,用O2就可以过,用O0就过不了。内核里面有许多类似设想编译器会进行优化的代码。(那可以可以的利用这个东西)

避免优化

由于编译的优化,有些函数(比如小函数和全工程里面只被一个人调用的函数)虽然没有显示地写成inline,但是编译器优化为inline了,这给调试造成了一些麻烦,因为找不到这个函数对应的symbol了。

这个时候,我们可以显示地写明某些函数我们不想inline:
在这里插入图片描述
否则,上面2个函数,即便你代码里面没有写inline,由于O2和Os使能了相关的inline选项,也可能被编译器自动inline掉,如果我们想拒绝inline,可以通过noline来标识。

在全局已经使能O1, O2, O3, Os的情况下,某个单独的函数我们不想做任何的优化,可以用__attribute__((optimize(“O0”)))来修饰这个函数,比如我们把上述用O2可以编译过的代码进行如下修改:

在这里插入图片描述
重新用O2编译:

$ gcc -O2 cc.c
/tmp/cc8M338p.o: In function `main':

cc.c:(.text+0x19): undefined reference to `f'

collect2: error: ld returned 1 exit status

总结的话

下面给几条实践指南:

尽量不要尝试用O0去编译内核,这不符合真实的工程实践,也不太被主流Linux社区所支持;内核依赖O2/Os去做较多的优化;

追求你的代码在O2的情况下,仍然是正确的,代码要经得起编译优化;比如O0工作正常,而O2不正常,应该尽可能从自身找原因,分析汇编;

如果在全局优化的情况下,想针对某个局部避免优化,可以尝试用noinline,attribute((optimize(“O0”)))等进行外科手术式地调整。

版权声明:本文为CSDN博主「Linux阅码场」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/juS3Ve/article/details/82455491

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值