当前位置: 首页 > news >正文

网站公司建站温州谷歌优化排名公司

网站公司建站,温州谷歌优化排名公司,网站建设与管理是学什么,中国做投资的网站gdb 和 addr2line 调试内核模块内核模块插入内核链表的时候#xff0c;会调用 init 里面的程序#xff0c;我们上面给的那个例程的程序因为是经过多年风吹雨打的#xff0c;但是如果你是一个萌新的码农#xff0c;你能保证自己写的内核模块没有问题吗#xff1f;所以就需要… gdb 和 addr2line 调试内核模块内核模块插入内核链表的时候会调用 init 里面的程序我们上面给的那个例程的程序因为是经过多年风吹雨打的但是如果你是一个萌新的码农你能保证自己写的内核模块没有问题吗所以就需要调试方法如果你写了一个内核模块加载不成功这时候就会产生 oops 内核不会有影响就好像你拿了一个伪造的车票想上高铁结果被列车员发现了把你踢下车了列车不受影响继续运行。我们用个示例来说明下调试 oops 的问题调试的最终目的就是要找到出现问题的地方。oops.c 源代码相比HelloWorld的代码这个代码增加了一些东西一个是增加了模块描述 MODULE_DESCRIPTION 和模块作者 MODULE_AUTHOR 这些都不是必须的但是作为一个标准的内核开发者把自己的模块写得越规范是越好的不仅代码看起来比较美观而且别人也可以从这些代码里面看到一些有用的信息。#include linux/init.h#include linux/module.hMODULE_LICENSE(Dual BSD/GPL);MODULE_DESCRIPTION (Oops);MODULE_AUTHOR(weiqifa);static int my_oops_init(void){ int *a; a (int *)0x00003333; *a 3;    printk(KERN_ALERT oops %d\n,a);    return 0;}static void my_oops_exit(void){    printk(KERN_ALERT Goodbye, oops\n);}module_init(my_oops_init);module_exit(my_oops_exit)Makefile 文件这个文件跟上面的文件有些不同加入了一个 FLAG 这个FLAG 为了方便我们调试内核。ifneq ($(KERNELRELEASE),)EXTRA_CFLAGS -Wall -gobj-m : oops.oelsePWD  : $(shell pwd)KVER : $(shell uname -r)KDIR : /lib/modules/$(KVER)/buildall: $(MAKE) -C $(KDIR) M$(PWD) modulesclean: rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versionsendif我们执行 insmod oops.ko 的时候会出现 kernel panic再通过 dmesg 来查看 panic 内容其中看到的 kernel 日志如下rootubuntu:~/linuxBook/oopsmodules# dmesg |tail -20[  815.844634] RSP: 0018:ffff88003b933de8  EFLAGS: 00010246[  815.844635] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000001[  815.844637] RDX: 0000000000040770 RSI: 0000000000003333 RDI: ffffffffa0359024[  815.844638] RBP: ffff88003b933e68 R08: 00000000000030d4 R09: 0000000000000100[  815.844639] R10: 8000000000000000 R11: 0000000000000000 R12: ffffffffa0358000[  815.844640] R13: 0000000000000000 R14: 0000000001005010 R15: 0000000000000000[  815.844641] FS:  00007fb80a1f6700(0000) GS:ffff88003d600000(0000) knlGS:0000000000000000[  815.844643] CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b[  815.844643] CR2: 0000000000003333 CR3: 0000000036198000 CR4: 00000000000407f0[  815.844687] Stack:[  815.844689]  ffff88003b933e68 ffffffff8100215a 0000000001005010 0000000000000000[  815.844691]  ffff88003b933e38 ffffffff8105ec93 0000000000000000 0000000000000000[  815.844693]  0000000001005010 ffffffffa0020000 ffff88003b933e68 00000000181edb8b[  815.844695] Call Trace:[  815.844734]  [ffffffff8100215a] ? do_one_initcall0xfa/0x1b0[  815.844740]  [ffffffff8105ec93] ? set_memory_nx0x43/0x50[  815.844752]  [ffffffff8175a462] do_init_module0x80/0x1d1[  815.844759]  [ffffffff810ec66d] load_module0x4ed/0x620[  815.844761]  [ffffffff810e9f10] ? show_initstate0x50/0x50[  815.844763]  [ffffffff810ec854] SyS_init_module0xb4/0x100[  815.844798]  [ffffffff8177b55d] system_call_fastpath0x1a/0x1f[  815.844800] Code: c7 04 25 33 33 00 00 03 00 00 00 48 89 e5 e8 3c 16 40 e1 31 c0 5d[  815.844809] RIP  [ffffffffa0358014] my_oops_init0x14/0x30 [oops][  815.844812]  RSP ffff88003b933de8[  815.844813] CR2: 0000000000003333[  815.844818] ---[ end trace f8f9b64af5078acc ]---看日志也是一个比较考验程序员的事情从上面的日志看我们可以看到 oops 发生的关键日志如下其中还有一些函数的堆栈调用但是这个不是重点。[  815.844809] RIP  [ffffffffa0358014] my_oops_init0x14/0x30 [oops][  815.844812]  RSP ffff88003b933de8查看模块的加载地址上面出现 oops 的是从模块的基地址偏移出来的地址我们要找到基地址然后再用基地址和偏移地址运算就可以知道出现问题的偏移量了。rootubuntu:~/linuxBook/oopsmodules# cat /proc/modules |grep oopsoops 13418 1 - Loading 0xffffffffa0358000 (OX)rootubuntu:~/linuxBook/oopsmodules#使用 addr2line 找到 oops 位置知道了基地址和偏移地址我们就可以知道偏移量了 offset 0xffffffffa0358014 - 0xffffffffa0358000 0x14rootubuntu:~/linuxBook/oopsmodules# addr2line -e oops.o 0x14/home/linux/linuxBook/oopsmodules/oops.c:12rootubuntu:~/linuxBook/oopsmodules#这样知道代码导致 oops 的位置是第12 行。通过objdump 来查找oops 位置rootubuntu:~/linuxBook/oopsmodules# objdump -dS --adjust-vma0xffffffffa0358000 oops.kooops.ko:     file format elf64-x86-64Disassembly of section .text:ffffffffa0358000 init_module:MODULE_LICENSE(Dual BSD/GPL);MODULE_DESCRIPTION (Oops);MODULE_AUTHOR(weiqifa);static int my_oops_init(void){ffffffffa0358000: e8 00 00 00 00       callq  ffffffffa0358005 init_module0x5ffffffffa0358005: 55                   push   %rbp int *a; a (int *)0x00003333; *a 3;    printk(KERN_ALERT oops %d\n,a);ffffffffa0358006: be 33 33 00 00       mov    $0x3333,%esiffffffffa035800b: 48 c7 c7 00 00 00 00 mov    $0x0,%rdiffffffffa0358012: 31 c0                 xor    %eax,%eaxstatic int my_oops_init(void){ int *a; a (int *)0x00003333; *a 3;ffffffffa0358014: c7 04 25 33 33 00 00 movl   $0x3,0x3333ffffffffa035801b: 03 00 00 00MODULE_LICENSE(Dual BSD/GPL);MODULE_DESCRIPTION (Oops);MODULE_AUTHOR(weiqifa);static int my_oops_init(void){ffffffffa035801f: 48 89 e5             mov    %rsp,%rbp int *a; a (int *)0x00003333; *a 3;    printk(KERN_ALERT oops %d\n,a);ffffffffa0358022: e8 00 00 00 00       callq  ffffffffa0358027 init_module0x27    return 0;}ffffffffa0358027: 31 c0                 xor    %eax,%eaxffffffffa0358029: 5d                   pop    %rbpffffffffa035802a: c3                   retq  ffffffffa035802b: 0f 1f 44 00 00       nopl   0x0(%rax,%rax,1)ffffffffa0358030 cleanup_module:static void my_oops_exit(void){ffffffffa0358030: e8 00 00 00 00       callq  ffffffffa0358035 cleanup_module0x5ffffffffa0358035: 55                   push   %rbp    printk(KERN_ALERT Goodbye, oops\n);ffffffffa0358036: 48 c7 c7 00 00 00 00 mov    $0x0,%rdiffffffffa035803d: 31 c0                 xor    %eax,%eax *a 3;    printk(KERN_ALERT oops %d\n,a);    return 0;}static void my_oops_exit(void){ffffffffa035803f: 48 89 e5             mov    %rsp,%rbp    printk(KERN_ALERT Goodbye, oops\n);ffffffffa0358042: e8 00 00 00 00       callq  ffffffffa0358047 cleanup_module0x17}ffffffffa0358047: 5d                   pop    %rbpffffffffa0358048: c3                   retq  ffffffffa0358049: 00 00                 add    %al,(%rax) ...rootubuntu:~/linuxBook/oopsmodules#这样看就更加清晰了我们知道出现 oops 的位置是 ffffffffa0358014 直接在上面找就可以看到了。 *a 3;ffffffffa0358014: c7 04 25 33 33 00 00 movl   $0x3,0x3333使用函数dump_stack()调试内核不知道大家有没有跟我一样的困惑Linux 代码非常多也非常大有时候为了找到这个函数是从哪里调用的需要花费非常多的时间去查找代码而且很多宏函数还会蒙蔽你的双眼让你沦陷在Linux 内核里面这时候就需要这么一个函数让你拨开层层乌云看清它的真面目这时候你就会有一个感觉我从哪里来我要到哪里去都是一清二楚了。废话不多说dump_stack()这个函数可以打印当前函数的上下文调用让你更加直观的知道你的函数调用关系这样你就更清楚的知道你的爸爸的妈妈的妹妹的姑姑的姐姐的儿子的弟弟是你的什么关系了。代码#include linux/init.h#include linux/module.hMODULE_LICENSE(Dual BSD/GPL);static int hello_init(void){    dump_stack();    printk(KERN_ALERT Hello, world\n);    return 0;}static void hello_exit(void){    printk(KERN_ALERT Goodbye, cruel world\n);}module_init(hello_init);module_exit(hello_exit);执行sudo insmod hello.ko后的kernel日志如下[176360.807755]  [ffffffff81765bf5] dump_stack0x64/0x82[176360.807776]  [ffffffffa0275000] ? 0xffffffffa0274fff[176360.807779]  [ffffffffa027500e] hello_init0xe/0x20 [hello][176360.807931]  [ffffffff8100215a] do_one_initcall0xfa/0x1b0[176360.808709]  [ffffffff8105ec93] ? set_memory_nx0x43/0x50[176360.808717]  [ffffffff8175a462] do_init_module0x80/0x1d1[176360.809093]  [ffffffff810ec66d] load_module0x4ed/0x620[176360.809097]  [ffffffff810e9f10] ? show_initstate0x50/0x50[176360.809100]  [ffffffff810ec854] SyS_init_module0xb4/0x100[176360.809187]  [ffffffff8177b55d] system_call_fastpath0x1a/0x1f[176360.809308] Hello, world可以看到里面的地址还有堆栈的调用使用dump_stack函数不用外加什么头文件使用起来非常方便也不用指定说只有在oops的时候才调用正常的时候我们想看函数调用关系的时候也可以调用就像我上面那样。实现源码位置/lib/dump_stack.c几个比较关键的函数调用关系主要想研究的同学可以去看看dump_stack_print_info 和show_stack里面的实现。dump_stack总结我们知道CPU工作的时候有不同的工作模式不同的工作模式代表有不同的权限就比如我是老板我才可能有保险柜的钥匙。这里有一个用户模式超级用户模式和中断模式我们知道每个进程分配的内存空间是不一样的他们的堆栈有一个task_struct来维护每个进程不能互相访问相互的内存进程切换的时候SP指针去执行要执行进程的堆栈地址所以我们可以知道一个事情SP这个东东啊是可以知道所有进程的东西的。但是呢操作系统在运行的时候CPU肯定有需要从用户模式跳转到中断模式运行进入中断的时候SP指针这个东东就体现出当前的堆栈了所以dump_stack就是从这些不断的切换中把堆栈地址给保存打印出来得到一个上下文的调用关系。使用vmlinux调试内核我们知道使用objdump反编译调试的是动态加载的内核模块但是我们需要调试那些静态编译进入内核的那些代码不能使用这个方法这时候就需要使用vmlinuxvmlinux是每次编译内核的时候生成的内核符号表里面包含了所有编译到内核的函数名还有偏移地址。使用方法高通平台arm-eabi-gdb out/target/product/msm8625/obj/KERNEL_OBJ/vmlinux在内核的.config里面要打开 DEBUG_INFO和DEBUG_VM定位故障方法(gdb) l * qrd7627a_add_io_devices0x1000xc07cd05c is in qrd7627a_add_io_devices (/home/yejialong/GH700C/kernel/arch/arm/mach-msm/msm8x25/goso-msm7627a-io.c:1851).1846            } else if (machine_is_msm8625q_skud() || machine_is_msm8625q_evbd()) {1847        #ifndef CONFIG_CALA021848                    platform_device_register(pmic_mpp_leds_pdev_skud);1849        #endif1850                    /* enable the skud flash and torch by gpio leds driver */1851                    platform_device_register(gpio_flash_skud);1852            } else if (machine_is_msm8625q_skue()) {1853                     /* enable the skue flashlight by gpio leds driver */1854                    platform_device_register(gpio_flash_skue);1855            }使用方法MTK平台weiqifaweiqifa-Inspiron-3847:~/weiqifa/tm100$ ./prebuilts/gcc/linux-x86/arm/arm-eabi-4.7/bin/arm-eabi-gdb ./out/target/product/tm100/obj/KERNEL_OBJ/vmlinuxGNU gdb (GDB) 7.3.1-gg2Copyright (C) 2011 Free Software Foundation, Inc.License GPLv3: GNU GPL version 3 or later http://gnu.org/licenses/gpl.htmlThis is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law.  Type show copyingand show warranty for details.This GDB was configured as --hostx86_64-linux-gnu --targetarm-linux-android.For bug reporting instructions, please see:http://source.android.com/source/report-bugs.html...Reading symbols from /home/weiqifa/weiqifa/tm100/out/target/product/tm100/obj/KERNEL_OBJ/vmlinux...done.(gdb)使用方法rockchip平台./prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android-addr2line -f -e kernel/vmlinuxweiqifadev:~/rk3399_7in1$ ./prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android-addr2line -f -e kernel/vmlinux ffffff8008459f3crk_iommu_domain_free/data/weiqifa/rk3399_7in1/kernel/drivers/iommu/rockchip-iommu.c:1005 (discriminator 2)weiqifadev:~/rk3399_7in1$一些调试相关的命令查看中断linuxubuntu:/usr/src/linux-headers-3.13.0-117/kernel$ cat /proc/interrupts            CPU0         0:         26   IO-APIC-edge      timer   1:      12200   IO-APIC-edge      i8042   8:          1   IO-APIC-edge      rtc0   9:          0   IO-APIC-fasteoi   acpi  12:     110704   IO-APIC-edge      i8042  14:          0   IO-APIC-edge      ata_piix  15:          0   IO-APIC-edge      ata_piix  16:      21165   IO-APIC-fasteoi   vmwgfx, snd_ens1371  17:      76243   IO-APIC-fasteoi   ehci_hcd:usb1, ioc0  18:        657   IO-APIC-fasteoi   uhci_hcd:usb2  19:     197583   IO-APIC-fasteoi   eth0  40:          0   PCI-MSI-edge      PCIe PME, pciehp这个可以在嵌入式调试的时候查看中断是否被触发非常有作用。查看工作队列cat /proc/sched_debug查看内核定时器cat /proc/timer_listproc应该重点关注proc下面的文件系统应该重点关注内核的调试信息很多都在这里面特别是初学者把下面的每个文件夹都看看作用还是非常明显的。下周开始我们可能进去封闭开发了时间会更加紧张可能会分享一些心得连载的话我还是会写只会迟到不会缺席这样也是对自己的一种鞭策。共勉加油~
http://www.pierceye.com/news/323118/

相关文章:

  • 找工作哪个网站好2022查询网站备案显示划横线
  • 06627网页制作和网站建设如何制作自己的公司内部网站
  • 网站营销与推广方案百度大数据分析
  • 手机怎么做自己的网站做网站的公司广州
  • asp.net网站开发案例教程南京seo排名
  • 购物网站开发技术分销
  • 企业网站建设专家工业产品设计包括哪些
  • 潍坊网站开发高手重庆市设计院
  • 微信公众号平台网站开发WordPress破解分享
  • 东营网站建设服务商低价备案域名购买
  • 高校网站建设自查报告哪个外贸网站开发客户比较好用
  • 网站做付费推广都需要问什么wordpress小工具插件
  • 网站的建设技术有哪些北京一环都是住什么人
  • 做外贸soho网站的公司吗已有备案号新增网站备案要关闭原先的站点吗
  • 网站域名注册免费wordpress 让导航悬浮
  • 全景旅游网站项目建设湖南建筑公司网站
  • 做网批那个网站好免费视频素材库app
  • cms建站模板appseo网络优化是什么工作
  • 云落wordpress优化大师在哪里
  • 威海网站建设公司手机网站做落地页
  • 海宁建设局网站三网合一 网站建设
  • 1688货源网官方网站网站怎么做背景
  • 做阿里还是网站中小企业为什么要建设网站
  • 天津的网站建设做网站费用怎么入账
  • 网站原型是产品经理做wordpress手机上用的
  • 专业网站排名优化重庆广告公司电话
  • 在线免费看影视网站正规企业展厅设计公司
  • 励志网站织梦源码做电子杂志用什么网站
  • 电子设计网站wordpress数据清除
  • 义乌网站推广中国住房和城乡建设厅网站