• LINUX 内核调试基础+编程基础


     http://blog.chinaunix.net/uid-20564848-id-73208.html

    内核文档:
    [root@localhost Documentation]# pwd
    /usr/src/kernels/linux-2.6.32/Documentation [root@localhost Documentation]# ls 00-INDEX i2o parport.txt ABI ia64 PCI accounting ics932s401 pcmcia acpi ide pi-futex.txt aoe infiniband pnp.txt applying-patches.txt initrd.txt power arm input powerpc atomic_ops.txt Intel-IOMMU.txt pps auxdisplay intel_txt.txt prctl bad_memory.txt ioctl preempt-locking.txt basic_profiling.txt io-mapping.txt printk-formats.txt binfmt_misc.txt IO-mapping.txt prio_tree.txt blackfin io_ordering.txt rbtree.txt block iostats.txt RCU blockdev IPMI.txt rfkill.txt braille-console.txt IRQ-affinity.txt robust-futex-ABI.txt bt8xxgpio.txt irqflags-tracing.txt robust-futexes.txt btmrvl.txt IRQ.txt rtc.txt BUG-HUNTING isapnp.txt rt-mutex-design.txt c2port.txt isdn rt-mutex.txt cachetlb.txt ja_JP s390 cdrom java.txt SAK.txt cgroups kbuild scheduler Changes kdump scsi CodingStyle kernel-doc-nano-HOWTO.txt SecurityBugs connector kernel-docs.txt SELinux.txt console kernel-parameters.txt serial cpu-freq keys-request-key.txt serial-console.txt cpu-hotplug.txt keys.txt sgi-ioc4.txt cpuidle kmemcheck.txt sgi-visws.txt cpu-load.txt kmemleak.txt sh cputopology.txt kobject.txt slow-work.txt credentials.txt ko_KR SM501.txt cris kprobes.txt Smack.txt crypto kref.txt sound dcdbas.txt kvm sparc debugging-modules.txt laptops sparse.txt debugging-via-ohci1394.txt ldm.txt spi dell_rbu.txt leds-class.txt spinlocks.txt development-process leds-lp3944.txt stable_api_nonsense.txt device-mapper lguest stable_kernel_rules.txt devices.txt local_ops.txt SubmitChecklist DMA-API.txt lockdep-design.txt SubmittingDrivers DMA-attributes.txt lockstat.txt SubmittingPatches dmaengine.txt logo.gif svga.txt DMA-ISA-LPC.txt logo.txt sysctl DMA-mapping.txt m68k sysfs-rules.txt DocBook magic-number.txt sysrq.txt dontdiff make telephony driver-model Makefile thermal dvb ManagementStyle timers dynamic-debug-howto.txt mca.txt tomoyo.txt early-userspace md.txt trace edac.txt memory-barriers.txt uml eisa.txt memory-hotplug.txt unaligned-memory-access.txt email-clients.txt memory.txt unicode.txt fault-injection mips unshare.txt fb misc-devices usb feature-removal-schedule.txt mn10300 vgaarbiter.txt filesystems mono.txt VGA-softcursor.txt firmware_class mtd video4linux flexible-arrays.txt mutex-design.txt video-output.txt frv namespaces vm futex-requeue-pi.txt netlabel volatile-considered-harmful.txt gcov.txt networking voyager.txt gpio.txt nmi_watchdog.txt w1 highuid.txt nommu-mmap.txt watchdog HOWTO numastat.txt wimax hwmon oops-tracing.txt x86 hw_random.txt parisc zh_CN i2c parport-lowlevel.txt zorro.txt
    内核书籍:
    
    LDK:LINUX内核设计与实现
    
    ULK:深入理解LINUX内核
    
    LDD:LINUX 设备驱动程序
    
    LVMM:深入理解LINUX 虚拟内存管理
    
    深入理解LINUX网络内幕
    内核社区:
    
    http://vger.kernel.org/vger-lists.html#linux-kernel
    
    http://dir.gmane.org/gmane.linux.usb.general
    
    https://www.kernel.org/

    http://linux.chinaunix.net/
    printk小结
    
    1 printk 消息级别定义
        
        #define KERN_EMERG   "<0>"   /*紧急事件,一般是系统崩溃之前的提示消息*/
        #define KERN_ALERT   "<1>"   /*必须立即采取行动*/
        #define KERN_CRIT    "<2>"   /*临界状态,通常涉及严重的硬件或者软件操作失败*/
        #define KERN_ERR     "<3>"   /*用于报告错误状态,设备驱动会经常使用KERN_ERR来报告硬件错误*/
        #define KERN_WARNING "<4>"   /*对可能出现问题的情况进行警告,这类情况通常不会对系统造成严重问题 */
        #define KERN_NOTICE  "<5>"   /*有必要进行提示的正常情形,许多与安全相关的状况用这个级别进行汇报*/
        #define KERN_INFO    "<6>"   /*内核提示性信息,很多驱动程序在启动的时候以这个级别打印找到的硬件信息*/
        #define KERN_DEBUG   "<7>"   /*用于调试信息*/
    
    2  使用方法
        printk(KERN_ALERT "XXXXXX",XXXX);
    3 /proc/sys/kernel/printk
         该文件可以调节printk的输出等级,文件中有四个数字值。
        (1)  控制台日志级别:优先级高于该值的消息将被打印至控制台。
        (2)  默认的消息日志级别:用该优先级来打印未定义优先级的消息。
        (3) 最低的控制台日志级别:控制台日志界别可被设置的最小值。
        (4) 默认的控制台日志级别:控制台日志级别的默认值。
    4 通过如下命令可以使得Linux内核的任何printk都被输出到控制台 #echo 8 > /proc/sys/kernel/printk

    5. cat /proc/kmsg
      这个文件用于检索用printk生成的内核消息。任何时刻只能有一个具有超级用户权限的进程可以读取这个文件。也可以用系统调用syslog检索这些消息。
    通常使用工具dmesg或守护进程klogd检索这些消息。



    printk---------------->log buffer --------------->klogd---------------->syslogd------->文件
    printk---------------->log buffer  --------------->klogd---------------->文件
    printk---------------->log buffer------------------>dmesg



    内核模块:
    OOPS:LINUX 系统崩溃,LINUX 不能使用

    1.EIP
    2.CALL TRACE
    3.OBJDUMP 反汇编 EIP

    GDB调试内核:

     [root@localhost linux-2.6.32]# pwd
      /usr/src/kernels/linux-2.6.32
     [root@localhost linux-2.6.32]# gdb vmlinux /proc/kcore

    刷新GDB缓存:

    (gdb) core-file /proc/kcore
     [New process 1]
     Core was generated by `ro root=LABEL=/ rhgb quiet'.
     #0 0x0000000000000000 in per_cpu.irq_stack_union ()

    (gdb) print jiffies
    $11 = -109 '223'


    (gdb) core-file /proc/kcore
    [New process 1]
    Core was generated by `ro root=LABEL=/ rhgb quiet'.
    #0 0x0000000000000000 in per_cpu.irq_stack_union ()
    (gdb) print jiffies
    $12 = 42 '*'

    其他内核调试器:

    KGDB

    http://blog.csdn.net/hejinjing_tom_com/article/details/9932451

    KDB

    KPROBES

    KDUMP

    硬件调试器

    BDM/JTAG

    SysRq:
     
    0-9 设定终端输出的内核 log 优先级

    b 立即重启系统
    c 内核live reboot,并输出错误信息
    d 显示所有排它锁
    e 向除 init 外进程发送 SIGTERM 信号,让其自行结束
    f 人为触发 OOM Killer (out of memory)
    g 当进入内核模式时,以 framebuttter 代替输出
    h 输出帮助
    i 向除 init 以外所有进程发送 SIGKILL 信号,强制结束进程
    k 结束与当前控制台相关的全部进程
    m 内存使用信息
    n 重置所有进程的 nice(优先级)
    o 关机
    p 输出cpu 寄存器信息
    q Display all active high-resolution timers and clock sources.
    r 把键盘设置为 ASCII 模式,使按键可以穿透 x server 捕捉传递给内核
    s 同步缓冲区数据到硬盘
    t 输出进程列表
    u 重新挂载所有文件系统为只读模式
    v 输出 Voyager SMP 处理信息
    w 输出 block(d状态)进程列表
     
     





    hello.c 内核模块编绎
    
    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/init.h>
    
    static int init_hello_4(void)
    {
       printk(KERN_ALERT "Hello, world 4 ");
       return 0;
    }
    
    static void cleanup_hello_4(void)
    {
       printk(KERN_ALERT "Goodbye, world 4 ");
    }
    
    module_init(init_hello_4);
    module_exit(cleanup_hello_4);
    MODULE_LICENSE("GPL");
    MODULE_AUTHOR("Playmud");
    MODULE_DESCRIPTION("Test only!");

    配置Makefile和执行ko编译

    [root@server1 ~]# 
    echo "obj-m:=hello.o" > Makefile

      [root@server1 ~]# make -C /lib/modules/`uname -r`/build M=`pwd` modules
      make: Entering directory `/usr/src/kernels/2.6.32-431.23.3.el6.x86_64'
      Building modules, stage 2.
      MODPOST 1 modules
      make: Leaving directory `/usr/src/kernels/2.6.32-431.23.3.el6.x86_64'

    /lib/modules/`uname -r`/build
    就是本地机子的module编译配置目录 不是为正在运行的内核编译模块: make
    -C M=`pwd`
    为正在运行的内核编译模块: make -C /lib/modules/`uname -r`/build M=`pwd` modules
    printk没有在console上打印出提示,通过

      [root@server1 ~]# dmesg |tail -1
      Hello, world 


    可以查到,具体配置可以查看
    vim /etc/syslog.conf
    sysrq
         常使用的魔术键:
         echo  1>/proc/sys/kernel/sysrq 打开sysrq功能
     
         echo 't' >/proc/sysrq-trigger   打印进程栈,调试时很有用
     
         echo 'c' >/proc/sysrq-trigger  常常用来测试dump模式
    printk打印不能显示到终端的问题
      【原型】
      int printk(const char * fmt,…);
      【示例】
      与大多数展示printf的功能一样,我们也用一个helloworld的程序来演示printk的输出:
      编写一个内核模块:
      #include
      #include
      #if CONFIG_MODVERSIONS==1
      #define MODVERSIONS
      #include
      #endif
      MODULE_LICENSE("GPL");
      int init_module()
      {
      printk("hello.word-this is the kernel speaking
    ");
      return 0;
      }
      void cleanup_module()
      {
      printk("Short is the life of a kernel module
    ");
      }
      保存为文件hello.c
      编写一个Makefile:
      CC=gcc
      MODCFLAGS:=-O6 -Wall -DMODULE -D__KERNEL__ -DLINUX
      hello.o:hello.c /usr/include/linux/version.h
      $(CC) $(MODCFLAGS) -c hello.c
      echo insmod hello.o to turn it on
      保存为文件Makefile
      执行make
      我们可以看到生成了一个hello.o的内核模块,我们想通过这个模块在插入内核的时候输出
      "hello.word-this is the kernel speaking"
      这样一条信息。
      然后我们开始:
      [root@localhost root]# insmod hello.o
      [root@localhost root]#
      并没有输出任何消息。why?
      这也是printf和printk的一个不同的地方
      用printk,内核会根据日志级别,可能把消息打印到当前控制台上,这个控制台通常是一个字符模式的终端、一个串口打印机或是一个并口打印机。这些消息正常输出的前提是──日志输出级别小于console_loglevel(在内核中数字越小优先级越高)。
      没有指定日志级别的printk语句默认采用的级别是 DEFAULT_ MESSAGE_LOGLEVEL(这个默认级别一般为<4>,即与KERN_WARNING在一个级别上),其定义在linux26/kernel/printk.c中可以找到
      日志级别一共有8个级别,printk的日志级别定义如下(在include/linux/kernel.h中):
      #define KERN_EMERG    0
      #define KERN_ALERT    1
      #define KERN_CRIT     2
      #define KERN_ERR      3
      #define KERN_WARNING  4
      #define KERN_NOTICE   5
      #define KERN_INFO     6
      #define KERN_DEBUG    7
      现在我们来修改hello.c程序,使printk的输出级别为最高:
      printk("<0>""hello.word-this is the kernel speaking
    ");
      然后重新编译hello.o,并插入内核:
      [root@localhost root]# insmod hello.o
      [root@localhost root]#
      Message from syslogd@localhost at Sat Aug 15 05:32:22 2009 ...
      localhost kernel: hello.word-this is the kernel speaking
      hello,world信息出现了。
      其实printk始终是能输出信息的,只不过不一定是到了终端上。我们可以去
      /var/log/messages这个文件里面去查看。
      如果klogd没有运行,消息不会传递到用户空间,只能查看/proc/kmsg
      通过读写/proc/sys/kernel/printk文件可读取和修改控制台的日志级别。查看这个文件的方法如下:
      #cat /proc/sys/kernel/printk 6 4 1 7
      上面显示的4个数据分别对应控制台日志级别、默认的消息日志级别、最低的控制台日志级别和默认的控制台日志级别。
      可用下面的命令设置当前日志级别:
      # echo 8 > /proc/sys/kernel/printk
      这样所有级别<8,(0-7)的消息都可以显示在控制台上. 


  • 相关阅读:
    网页打开本地exe程序
    【JS】最简单的域名防红方法,QQ/微信打开网站提示浏览器打开
    【HTML】建站成功默认页面
    python中日志器的使用
    python中连接mysql
    python中处理配置文件
    接口实战项目总结上
    布隆过滤器和LRU Cache
    Python版常见的排序算法
    LeetCode 27. 移除元素
  • 原文地址:https://www.cnblogs.com/zengkefu/p/5566721.html
Copyright © 2020-2023  润新知