linux-likely学习 背景 在日常的工作和学习中,经常发现likely和unlikely的使用,在通知链节点注册时,有如下函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 static int notifier_chain_register (struct notifier_block **nl, struct notifier_block *n) { while ((*nl) != NULL ) { if (unlikely((*nl) == n)) { WARN(1 , "notifier callback %ps already registered" , n->notifier_call); return -EEXIST; } if (n->priority > (*nl)->priority) break ; nl = &((*nl)->next); } n->next = *nl; rcu_assign_pointer(*nl, n); return 0 ; }
这里通过遍历节点和插入节点地址对比,防止程序运行时重复插入通知链节点。当然,重复插入这种情况下是非常少见的,因此编译器针对此进行了性能优化。
实现 1 2 3 # define likely(x) __builtin_expect(!!(x), 1) # define unlikely(x) __builtin_expect(!!(x), 0)
内核未见__builtin_expect
的实现,为编译器实现,称为内建函数,最后深入研究
原理 处理器的流水线处理,处理器在取指,执行等都是并行执行的,提前取指可以提高性能,但是提前取指是一个预测的过程,如果预测错误,会导致branch miss,需要重新取指(属于跳转取指,但是跳转取指是比较耗时的),这种情况反而会导致性能降低。
编译器可以针对代码情况进行取指优化,如果大部分情况都是A,即(likely(A)),那么将A情况下的指令取指提前到条件指令后面,如果大部分都不是A,即(unlikely(A)), 那么将其他情况的指令提前到条件指令后面。
实践 通过代码汇编指令对比检查优化逻辑,汇编有两种方式:
通过objdump进行汇编 gdb通过disassemble指令进行汇编 编译环境 需要确定kernel的编译环境打开了编译器优化
可以发现编译器优化等级为-O2
1 2 3 4 5 //Makefile $(info KBUILD_CFLAGS is $(KBUILD_CFLAGS)) ➜ 2-likely git:(master) ✗ make KBUILD_CFLAGS is -Wall ... -std=gnu89 ... -O2 ... -g -gdwarf-4
修改编译优化等级有两种方式
修改linux Makefile编译方式 1 2 3 4 5 6 7 ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE >>默认 KBUILD_CFLAGS += -O2 else ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE_O3 KBUILD_CFLAGS += -O3 else ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE KBUILD_CFLAGS += -Os
增加模块编译参数 1 2 EXTRA_CFLAGS = -Wall -g -O2
代码 在代码设计时,要注意三点
确保变量不能是定值,比如a = 1; if(likely(a == 1))
,因此选择使用进程号 要确保不同条件下的指令有明显差异,不能都是printk,不然只能看到汇编流程上je和jne的差异,因此选择a++和a–。 因为使用gdb通过disassemble指令进行汇编,因此需要汇编的函数需要导出symbol,可以通过nm
确认 test-A.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 MODULE_SRCS += likely.c MODULE_OBJS += $(wildcard *.o) \ $(wildcard *.ko) \ $(wildcard *.mod) \ $(wildcard *.mod.c) OUT_FILES += modules.order \ Module.symvers #$(info "OBJS is $(MODULE_OBJS)" ) obj-m += likely.o module -objs := likely.o#EXTRA_CFLAGS = -Wall -g -O2 >>这里也可以设置编译器优化等级 #The path of kernel code KDIR := /github/linux PWD ?= $(shell pwd) build: kernel_modules kernel_modules: make -C $(KDIR) M=$(PWD) modules #$(info EXTRA_CFLAGS is $(EXTRA_CFLAGS)) $(info KBUILD_CFLAGS is $(KBUILD_CFLAGS)) clean: rm -rf $(MODULE_OBJS) rm -rf $(OUT_FILES)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/sched.h> MODULE_LICENSE("Dual BSD/GPL" ); static struct task_struct *p ;static int a = 0 ;void test (void ) { if ((p->pid % 2 ) == 0 ) { a++; } else { a--; } } EXPORT_SYMBOL(test); void test_likely (void ) { if (likely((p->pid % 2 ) == 0 )) { a++; } else { a--; } } EXPORT_SYMBOL(test_likely); void test_unlikely (void ) { if (unlikely((p->pid % 2 ) == 0 )) { a++; } else { a--; } } EXPORT_SYMBOL(test_unlikely); static int likely_init (void ) { p = current; printk(KERN_ALERT "Hello, world\n" ); test(); test_likely(); test_unlikely(); return 0 ; } static void likely_exit (void ) { printk(KERN_ALERT "Goodbey, cruel world\n" ); } module_init(likely_init); module_exit(likely_exit);
objdump汇编 objdump汇编检查差异
-O2 -O2优化的情况下,unlikely将else的指令提前到条件指令后边
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 //-O2 ➜ 2-likely git:(master) ✗ objdump -d likely.ko likely.ko: 文件格式 elf64-x86-64 Disassembly of section .text: 0000000000000000 <test_likely>: 0: e8 00 00 00 00 callq 5 <test_likely+0x5> 5: 48 8b 05 00 00 00 00 mov 0x0(%rip),%rax c: f6 80 c0 05 00 00 01 testb $0x1 ,0x5c0(%rax) 13: 75 08 jne 1d <test_likely+0x1d> 如果不相等,那么跳转到1d, 即a-- 15: 83 05 00 00 00 00 01 addl $0x1 ,0x0(%rip) 1c: c3 retq 1d: 83 2d 00 00 00 00 01 subl $0x1 ,0x0(%rip) 24: c3 retq 25: 90 nop 26: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 2d: 00 00 00 0000000000000030 <test_unlikely>: 30: e8 00 00 00 00 callq 35 <test_unlikely+0x5> 35: 48 8b 05 00 00 00 00 mov 0x0(%rip),%rax 3c: f6 80 c0 05 00 00 01 testb $0x1 ,0x5c0(%rax) 43: 74 08 je 4d <test_unlikely+0x1d> 如果相等,那么跳转到4d, 即a++ 45: 83 2d 00 00 00 00 01 subl $0x1 ,0x0(%rip) 4c: c3 retq 4d: 83 05 00 00 00 00 01 addl $0x1 ,0x0(%rip) 54: c3 retq 55: 90 nop 56: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 5d: 00 00 00 0000000000000060 <test >: 60: e8 00 00 00 00 callq 65 <test +0x5> 65: 48 8b 05 00 00 00 00 mov 0x0(%rip),%rax 6c: f6 80 c0 05 00 00 01 testb $0x1 ,0x5c0(%rax) 73: 74 08 je 7d <test +0x1d> 75: 83 2d 00 00 00 00 01 subl $0x1 ,0x0(%rip) 7c: c3 retq 7d: 83 05 00 00 00 00 01 addl $0x1 ,0x0(%rip) 84: c3 retq 85: 90 nop 86: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 8d: 00 00 00 ...
-O0 不开默认编译优化的情况下,发现指令数目明显增多
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 000000000000002f <test>: 2f : e8 00 00 00 00 callq 34 <test+0x5 > 34 : 55 push %rbp 35 : 48 89 e5 mov %rsp,%rbp 38 : 48 8b 05 00 00 00 00 mov 0x0 (%rip),%rax # 3f <test+0x10 > 3f : 8b 80 c0 05 00 00 mov 0x5c0 (%rax),%eax 45 : 83 e0 01 and $0x1 ,%eax 48 : 85 c0 test %eax,%eax 4 a: 75 11 jne 5 d <test+0x2e > >>为假跳到5 d 4 c: 8b 05 00 00 00 00 mov 0x0 (%rip),%eax # 52 <test+0x23 > >>为真add 52 : 83 c0 01 add $0x1 ,%eax 55 : 89 05 00 00 00 00 mov %eax,0x0 (%rip) # 5b <test+0x2c > 5b : eb 0f jmp 6 c <test+0x3d > 5 d: 8b 05 00 00 00 00 mov 0x0 (%rip),%eax # 63 <test+0x34 > 63 : 83 e8 01 sub $0x1 ,%eax >>为假sub 66 : 89 05 00 00 00 00 mov %eax,0x0 (%rip) # 6 c <test+0x3d > 6 c: 90 nop 6 d: 5 d pop %rbp 6 e: c3 retq 000000000000006f <test_likely>: 6f : e8 00 00 00 00 callq 74 <test_likely+0x5 > 74 : 55 push %rbp 75 : 48 89 e5 mov %rsp,%rbp 78 : 48 8b 05 00 00 00 00 mov 0x0 (%rip),%rax # 7f <test_likely+0x10 > 7f : 8b 80 c0 05 00 00 mov 0x5c0 (%rax),%eax 85 : 83 e0 01 and $0x1 ,%eax 88 : 85 c0 test %eax,%eax 8 a: 0f 94 c0 sete %al 8 d: 0f b6 c0 movzbl %al,%eax 90 : 48 85 c0 test %rax,%rax 93 : 74 11 je a6 <test_likely+0x37 > 95 : 8b 05 00 00 00 00 mov 0x0 (%rip),%eax # 9b <test_likely+0x2c > 9b : 83 c0 01 add $0x1 ,%eax 9 e: 89 05 00 00 00 00 mov %eax,0x0 (%rip) # a4 <test_likely+0x35 > a4: eb 0f jmp b5 <test_likely+0x46 > a6: 8b 05 00 00 00 00 mov 0x0 (%rip),%eax # ac <test_likely+0x3d> ac: 83 e8 01 sub $0x1 ,%eax af: 89 05 00 00 00 00 mov %eax,0x0 (%rip) # b5 <test_likely+0x46 > b5: 90 nop b6: 5 d pop %rbp b7: c3 retq 00000000000000b 8 <test_unlikely>: b8: e8 00 00 00 00 callq bd <test_unlikely+0x5 > bd: 55 push %rbp be: 48 89 e5 mov %rsp,%rbp c1: 48 8b 05 00 00 00 00 mov 0x0 (%rip),%rax # c8 <test_unlikely+0x10 > c8: 8b 80 c0 05 00 00 mov 0x5c0 (%rax),%eax ce: 83 e0 01 and $0x1 ,%eax d1: 85 c0 test %eax,%eax d3: 0f 94 c0 sete %al d6: 0f b6 c0 movzbl %al,%eax d9: 48 85 c0 test %rax,%rax dc: 74 11 je ef <test_unlikely+0x37 > de: 8b 05 00 00 00 00 mov 0x0 (%rip),%eax # e4 <test_unlikely+0x2c > e4: 83 c0 01 add $0x1 ,%eax e7: 89 05 00 00 00 00 mov %eax,0x0 (%rip) # ed <test_unlikely+0x35> ed: eb 0f jmp fe <test_unlikely+0x46 > ef: 8b 05 00 00 00 00 mov 0x0 (%rip),%eax # f5 <test_unlikely+0x3d > f5: 83 e8 01 sub $0x1 ,%eax f8: 89 05 00 00 00 00 mov %eax,0x0 (%rip) # fe <test_unlikely+0x46> fe: 90 nop ff: 5 d pop %rbp 100 : c3 retq
-O1 -O1 的情况下指令明显变少,同时发现和-O2的打印基本一致,思考为什么?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 likely.ko: 文件格式 elf64-x86-64 Disassembly of section .text: 0000000000000000 <test>:hui bian 0 : e8 00 00 00 00 callq 5 <test+0x5 > 5 : 48 8b 05 00 00 00 00 mov 0x0 (%rip),%rax # c <test+0xc> c: f6 80 c0 05 00 00 01 testb $0x1 ,0x5c0 (%rax) 13 : 74 08 je 1 d <test+0x1d > 15 : 83 2 d 00 00 00 00 01 subl $0x1 ,0x0 (%rip) # 1 c <test+0x1c > 1 c: c3 retq 1 d: 83 05 00 00 00 00 01 addl $0x1 ,0x0 (%rip) # 24 <test+0x24 > 24 : c3 retq 0000000000000025 <test_likely>: 25 : e8 00 00 00 00 callq 2 a <test_likely+0x5 > 2 a: 48 8b 05 00 00 00 00 mov 0x0 (%rip),%rax # 31 <test_likely+0xc > 31 : f6 80 c0 05 00 00 01 testb $0x1 ,0x5c0 (%rax) 38 : 75 08 jne 42 <test_likely+0x1d > 3 a: 83 05 00 00 00 00 01 addl $0x1 ,0x0 (%rip) # 41 <test_likely+0x1c > 41 : c3 retq 42 : 83 2 d 00 00 00 00 01 subl $0x1 ,0x0 (%rip) # 49 <test_likely+0x24 > 49 : c3 retq 000000000000004 a <test_unlikely>: 4 a: e8 00 00 00 00 callq 4f <test_unlikely+0x5 > 4f : 48 8b 05 00 00 00 00 mov 0x0 (%rip),%rax # 56 <test_unlikely+0xc > 56 : f6 80 c0 05 00 00 01 testb $0x1 ,0x5c0 (%rax) 5 d: 74 08 je 67 <test_unlikely+0x1d > 5f : 83 2 d 00 00 00 00 01 subl $0x1 ,0x0 (%rip) # 66 <test_unlikely+0x1c > 66 : c3 retq 67 : 83 05 00 00 00 00 01 addl $0x1 ,0x0 (%rip) # 6 e <test_unlikely+0x24 > 6 e: c3 retq
gdb查看汇编 使用gdb来查看-O2下的模块汇编,同objdump显示一致
disassemble test 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 (gdb) disassemble test Dump of assembler code for function test: 0x0000000000000090 <+0>: callq 0x95 <test+5> 0x0000000000000095 <+5>: mov 0x0(%rip),%rax # 0x9c <test+12> 0x000000000000009c <+12>: testb $0x1,0x5c0(%rax) 0x00000000000000a3 <+19>: je 0xad <test+29> 0x00000000000000a5 <+21>: subl $0x1,0x0(%rip) # 0xac <test+28> 0x00000000000000ac <+28>: retq 0x00000000000000ad <+29>: addl $0x1,0x0(%rip) # 0xb4 <test+36> 0x00000000000000b4 <+36>: retq End of assembler dump. (gdb) disassemble test_likely Dump of assembler code for function test_likely: 0x0000000000000030 <+0>: callq 0x35 <test_likely+5> 0x0000000000000035 <+5>: mov 0x0(%rip),%rax # 0x3c <test_likely+12> 0x000000000000003c <+12>: testb $0x1,0x5c0(%rax) 0x0000000000000043 <+19>: jne 0x4d <test_likely+29> 0x0000000000000045 <+21>: addl $0x1,0x0(%rip) # 0x4c <test_likely+28> 0x000000000000004c <+28>: retq 0x000000000000004d <+29>: subl $0x1,0x0(%rip) # 0x54 <test_likely+36> 0x0000000000000054 <+36>: retq End of assembler dump. (gdb) disassemble test_unlikely Dump of assembler code for function test_unlikely: 0x0000000000000060 <+0>: callq 0x65 <test_unlikely+5> 0x0000000000000065 <+5>: mov 0x0(%rip),%rax # 0x6c <test_unlikely+12> 0x000000000000006c <+12>: testb $0x1,0x5c0(%rax) 0x0000000000000073 <+19>: je 0x7d <test_unlikely+29> 0x0000000000000075 <+21>: subl $0x1,0x0(%rip) # 0x7c <test_unlikely+28> 0x000000000000007c <+28>: retq 0x000000000000007d <+29>: addl $0x1,0x0(%rip) # 0x84 <test_unlikely+36> 0x0000000000000084 <+36>: retq End of assembler dump.
注意,gdb disassemble显示的都是symbol,需要EXPORT_SYMBOL导出,可以通过nm确认
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 ➜ 2 -likely git:(master) ✗ nm likely.ko 0000000000000000 b a00000000000000 d0 T cleanup_module U current_task U __fentry__ 0000000000000090 T init_module0000000000000005 r __kstrtabns_test0000000000000012 r __kstrtabns_test_likely0000000000000021 r __kstrtabns_test_unlikely0000000000000000 r __kstrtab_test0000000000000006 r __kstrtab_test_likely0000000000000013 r __kstrtab_test_unlikely0000000000000000 r __ksymtab_test000000000000000 c r __ksymtab_test_likely0000000000000018 r __ksymtab_test_unlikely00000000000000 d0 t likely_exit0000000000000090 t likely_init0000000000000018 r _note_80000000000000000 r _note_90000000000000008 b p U _printk 0000000000000060 T test0000000000000000 T test_likely0000000000000030 T test_unlikely0000000000000000 D __this_module0000000000000038 r __UNIQUE_ID_depends1210000000000000000 r __UNIQUE_ID_license172000000000000004 d r __UNIQUE_ID_name1190000000000000041 r __UNIQUE_ID_retpoline1200000000000000015 r __UNIQUE_ID_srcversion1220000000000000059 r __UNIQUE_ID_vermagic118
深入 gcc内建函数的实现流程 既然要追踪gcc内建函数的实现,可是对gcc架构并不熟悉,因此想通过gdb来调试。但是本地的gcc是不带symbol的,gcc源代码默认编译方式是-g
1 2 ➜ bin file /usr/bin/x86_64-linux-gnu-gcc-6 /usr/bin/x86_64-linux-gnu-gcc-6 : ELF 64 -bit LSB executable, x86-64 , version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64. so.2 , for GNU/Linux 2.6 .32 , BuildID[sha1]=3 d6f4ce69fccf03dec42b3eea2fbc14a23b10ea3, stripped
下载最新的gcc编译替代本地后调试发现如下异常,应该是不影响gcc编译过程调试的
怀疑内建函数使用中 有用到add_builtin_function-->build_builtin_function
,因此在此处设置断点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ➜ 2 -likely git:(master) ✗ gdb (gdb) file /usr/local/bin/lto-dump Reading symbols from /usr/local/bin/lto-dump...done. ... (gdb) b add_builtin_function Breakpoint 1 at 0x9d0280 : file ../../gcc/langhooks.cc, line 735. (gdb) make >>没有在断点处暂停,原因未知,继续追踪研究 KBUILD_CFLAGS is make -C /github/linux M=/github/linux-driver/2 -likely modules make[1]: Entering directory '/github/linux' warning: the compiler differs from the one used to build the kernel The kernel was built by: gcc (Ubuntu 6.5 .0 -2u buntu1~16.04 ) 6.5 .0 20181026 You are using : gcc (GCC) 12.0 .1 20220406 (experimental)
如果去匹配,那么需要重新用新的gcc来编译内核(同时也应该去编译模块),但是gcc版本太高也应该有问题,内核编译会失败,因此下载gcc 6.5.0版本编译带symbol的执行文件
1 2 3 4 5 6 7 8 9 wget https: xz -d gcc-6.5 .0 .tar.xz tar -xvf gcc-6.5 .0 .tar ./contrib/download_prerequisites >>安装依赖 mkdir gcc-build cd gcc-build ../configure -enable-languages=c,c++ -disable-multilib -enable-checking=release make install >>默认安装在/usr/local下,生成新的/usr/local/bin/gcc rm -rf /usr/bin/gcc 删除旧的软链接,可删可不删, which gcc都会指向新的
思考?gcc编译什么时会触发我设置的内建断点?编译模块likely.c生成likely.o吗?还是编译内核?或者还是gcc本身编译呢(不太可能,编译时内建代码部分?)
通过make编译模块没有触发断点,嗯…想办法直接执行对应的gcc命令
make编译模块生成.o 动态模块中make主要部分如下:
1 make -C $(KDIR) M=$(PWD) modules
等价于在linux 下执行
1 ➜ linux git:(master) ✗ make M=/github/linux-driver/2 -likely modules
根据依赖规则,找到对应的实际生成likely.o的gcc编译部分,调试时将S(Q)去掉,这样可以打印make语句
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 modules: modules_check $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost PHONY += modules_check modules_check: $(MODORDER) $(Q)$(CONFIG_SHELL) $(srctree)/scripts/modules-check.sh $< >>依赖$(MODORDER), 这个是什么? export extmod_prefix = $(if $(KBUILD_EXTMOD),$(KBUILD_EXTMOD)/) export MODORDER := $(extmod_prefix)modules.order >>$(MODORDER)是/github/linux-driver/2 -likely/modules.order,但是这个文件没有?这个依赖什么? $(MODORDER): descend @: descend: $(build-dirs) $(build-dirs): prepare $(info chejian make is $(MAKE) build is $(build) | $@) $(MAKE) $(build)=$@ \ single-build=$(if $(filter-out $@/, $(filter $@/%, $(KBUILD_SINGLE_TARGETS))),1 ) \ need-builtin=1 need-modorder=1 >>打印为make -f ./scripts/Makefile.build obj=/github/linux-driver/2 -likely \ single-build= \ need-builtin=1 need-modorder=1 >>进入scripts/Makefile.build执行编译,查找第一个目标 __build: $(if $(KBUILD_BUILTIN), $(targets-for -builtin)) \ $(if $(KBUILD_MODULES), $(targets-for -modules)) \ $(subdir-ym) $(always-y) $(info sholck test 2 $(KBUILD_BUILTIN) | $(targets-for -builtin) | $(KBUILD_MODULES) | $(targets-for -modules) | $(subdir-ym)| $(always-y)) @: endif >>打印确认只有$(targets-for -modules)这个依赖不为空 targets-for -modules := $(patsubst %.o, %.mod, $(filter %.o, $(obj-m))) >>确认targets-for -modules为/github/linux-driver/2 -likely/likely.mod >>查找.mod的依赖 $(obj)/%.mod: $(obj)/%$(mod-prelink-ext).o FORCE $(call if_changed,mod) >>查找.o的依赖 # Built-in and composite module parts $(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE $(if $(if -changed-cond),$(rule_cc_o_c),@:) $(call if_changed_rule,cc_o_c) $(info lynx if -changed-cond is $(if -changed-cond)) >>增加打印 $(info lynx rule_cc_o_c is $(rule_cc_o_c)) >>增加打印 $(call cmd,force_checksrc) >>函数调用,检查打印if_changed_rule函数实现 if_changed_rule = $(if $(if -changed-cond),$(rule_$(1 )),@:) >>确定实际的gcc命令为 gcc -Wp,-MMD,/github/linux-driver/2-likely/.likely.o.d -nostdinc -I./arch/x86/include -I./arch/x86/include/generated -I./include -I./arch/x86/include/uapi -I./arch/x86/include/generated/uapi -I./include/uapi -I./include/generated/uapi -include ./include/linux/compiler-version.h -include ./include/linux/kconfig.h -include ./include/linux/compiler_types.h -D__KERNEL__ -Wall -Wundef -Werror=strict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -fshort-wchar -fno-PIE -Werror=implicit-function-declaration -Werror=implicit-int -Werror=return-type -Wno-format-security -std=gnu11 -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx -m64 -falign-jumps=1 -falign-loops=1 -mno-80387 -mno-fp-ret-in-387 -mpreferred-stack-boundary=3 -mskip-rax-setup -mtune=generic -mno-red-zone -mcmodel=kernel -Wno-sign-compare -fno-asynchronous-unwind-tables -mindirect-branch=thunk-extern -mindirect-branch-register -fno-jump-tables -fno-delete-null-pointer-checks -Wno-frame-address -O2 --param=allow-store-data-races=0 -Wframe-larger-than=1024 -fstack-protector-strong -Wno-main -Wno-unused-but-set-variable -Wno-unused-const-variable -pg -mrecord-mcount -mfentry -DCC_USING_FENTRY -Wdeclaration-after-statement -Wvla -Wno-pointer-sign -Wno-maybe-uninitialized -fno-strict-overflow -fno-stack-check -fconserve-stack -Werror=date-time -Werror=incompatible-pointer-types -Werror=designated-init -g -gdwarf-4 -Wall -g -DMODULE -DKBUILD_BASENAME='"likely"' -DKBUILD_MODNAME='"likely"' -D__KBUILD_MODNAME=kmod_likely -c -o /github/linux-driver/2-likely/likely.o /github/linux-driver/2-likely/likely.c
gdb 调试gcc中运行该命令未见内建中断触发
1 2 3 4 5 6 7 8 9 10 11 12 ➜ linux git:(master) ✗ gdb (gdb) file gcc Reading symbols from gcc...done. (gdb) add-symbol-file /github/package/gcc-6.5 .0 /gcc-build/gcc/langhooks.o add symbol table from file "/github/package/gcc-6.5.0/gcc-build/gcc/langhooks.o" (y or n) y Reading symbols from /github/package/gcc-6.5 .0 /gcc-build/gcc/langhooks.o...done. (gdb) b add_builtin_function ... (gdb) run -Wp,-MMD,/github/linux-driver/2-likely/.likely.o.d -nostdinc -I./arch/x86/include -I./arch/x86/include/generated -I./include -I./arch/x86/include/uapi -I./arch/x86/include/generated/uapi -I./include/uapi -I./include/generated/uapi -include ./include/linux/compiler-version.h -include ./include/linux/kconfig.h -include ./include/linux/compiler_types.h -D__KERNEL__ -Wall -Wundef -Werror=strict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -fshort-wchar -fno-PIE -Werror=implicit-function-declaration -Werror=implicit-int -Werror=return-type -Wno-format-security -std=gnu11 -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx -m64 -falign-jumps=1 -falign-loops=1 -mno-80387 -mno-fp-ret-in-387 -mpreferred-stack-boundary=3 -mskip-rax-setup -mtune=generic -mno-red-zone -mcmodel=kernel -Wno-sign-compare -fno-asynchronous-unwind-tables -mindirect-branch=thunk-extern -mindirect-branch-register -fno-jump-tables -fno-delete-null-pointer-checks -Wno-frame-address -O2 --param=allow-store-data-races=0 -Wframe-larger-than=1024 -fstack-protector-strong -Wno-main -Wno-unused-but-set-variable -Wno-unused-const-variable -pg -mrecord-mcount -mfentry -DCC_USING_FENTRY -Wdeclaration-after-statement -Wvla -Wno-pointer-sign -Wno-maybe-uninitialized -fno-strict-overflow -fno-stack-check -fconserve-stack -Werror=date-time -Werror=incompatible-pointer-types -Werror=designated-init -g -gdwarf-4 -Wall -g -DMODULE -DKBUILD_BASENAME='"likely"' -DKBUILD_MODNAME='"likely"' -D__KBUILD_MODNAME=kmod_likely -c -o /github/linux-driver/2-likely/likely.o /github/linux-driver/2-likely/likely.c ... [Inferior 1 (process 26045 ) exited normally] >>正常退出未见触发
测试编译内核/modules 编译内核和动态模块未见触发断点