linux内核学习的屠龙刀、倚天剑(需要搭配硬件调试环境)

    好久没来这里写博客了。看到浏览量有所增加,十分开心。希望自己的点滴付出对他人能有所帮助。要是有不对的地方,也希望博友能给予点出纠正。

要是能获得博友的转发,也希望能注明下原出处。打字不易,在此谢过啦!

    下面介绍下2个学习内核时很有用的工具(方法):

1.函数:dump_stack();    -------------------屠龙刀

    内核中,在调试过程中使用printk打印信息当然是最直接的办法。但当我们在刚开始学习内核时,要是一开始就定位到底层的某一个模块(函数),往往想知道它(模块、函数)到底是怎么被顶层一步一步调用下来,并最终调用到的。这时,我们可以利用dump_stack来最根溯源。

    以下用例子做使用说明:

static int m25p80_read(struct spi_nor *nor, loff_t from, size_t len,size_t *retlen, u_char *buf)
{
    ......
        printk(KERN_DEBUG "==============m25p80_read=======dump_stack s=====================\n");
	dump_stack();
	printk(KERN_DEBUG "==============m25p80_read=======dump_stack e=====================\n");
    ......
}
这是在内核代码 ./drivers/mtd/devices/m25p80.c 中的函数m25p80_read(...)内加入的。编译该内核,下载到你的板子上。上电。

看看dump_stack()能打印出什么信息:

==============m25p80_read=======dump_stack s=====================
CPU: 0 PID: 284 Comm: hexdump Not tainted 3.10.31-ltsi #269
Backtrace: 
[<c0012f24>] (dump_backtrace+0x0/0x110) from [<c001313c>] (show_stack+0x18/0x1c)
 r6:d6057810 r5:00000000 r4:d6057814 r3:00000000
[<c0013124>] (show_stack+0x0/0x1c) from [<c04968a4>] (dump_stack+0x24/0x28)
[<c0496880>] (dump_stack+0x0/0x28) from [<c02b87a8>] (m25p80_read+0x34/0x148)
[<c02b8774>] (m25p80_read+0x0/0x148) from [<c02b927c>] (spi_nor_read+0x60/0x7c)
 r9:00001000 r8:d6225ef0 r7:00000000 r6:d6057814 r5:00000000
r4:00700000
[<c02b921c>] (spi_nor_read+0x0/0x7c) from [<c02aa52c>] (part_read+0x70/0xa8)
 r7:d632b000 r6:d606c400 r5:00000000 r4:00000000
[<c02aa4bc>] (part_read+0x0/0xa8) from [<c02a7d9c>] (mtd_read+0xc0/0xec)
[<c02a7cdc>] (mtd_read+0x0/0xec) from [<c02abcf4>] (mtdchar_read+0xe0/0x20c)
[<c02abc14>] (mtdchar_read+0x0/0x20c) from [<c00c49e4>] (vfs_read+0xa0/0x14c)
[<c00c4944>] (vfs_read+0x0/0x14c) from [<c00c5070>] (SyS_read+0x44/0x80)
 r8:00000000 r7:b6f26000 r6:d6145cc0 r5:00000000 r4:00000000
[<c00c502c>] (SyS_read+0x0/0x80) from [<c000f100>] (ret_fast_syscall+0x0/0x30)
 r9:d6224000 r8:c000f2a8 r7:00000003 r6:b6effcb8 r5:0000000a
r4:00000000
==============m25p80_read=======dump_stack e=====================
以上可以看到调用dump_stack的函数是m25p80_read,并且也给出了函数m25p80_read的所在地址,

这样:m25p80_read<--spi_nor_read<--part_read<--mtd_read<--mtdchar_read<--vfs_read(文件系统相关的)

我们就可以看到相关各个层的大体关系了:flash具体《==  spi-nor  《==  mtd_part  《==  mtdcore  《==  mtdchar  《== vfs。

对你去理解内核的运作是不是很有帮助 ^_^


以上是自底而上的方法,下面介绍一种自顶而下的方法:



2.运用printk打印函数指针           ------------------倚天剑

当用函数指针调用一个函数时,我们在看代码时,往往不知道它调用的是哪里(哪个函数),举个例子,如下面的ret = master->transfer_one(master, msg->spi, xfer) :

static int spi_transfer_one_message(struct spi_master *master, struct spi_message *msg)
{
              .............
		printk(KERN_DEBUG "====master->transfer_one=%p=================\n",master->transfer_one);  //这里是额外加入的,查看master->transfer_one值
		ret = master->transfer_one(master, msg->spi, xfer);
              .............
}
这时,我们在它的上面加上printk,把master->transfer_one值打印出来:

编译该内核,下载到你的板子上。上电。log如下:

====master->transfer_one=c02be98c=================

拿着  c02be98c  ,进入编译好的内核源码根目录下,打开文件:System.map,查找c02be98c,可以看到:

c02be884 t rspi_common_transfer
c02be98c t qspi_transfer_one    (这里)
c02bec30 t rspi_rz_transfer_one


这个函数正是 master->transfer_one 指向的函数。

接下来,不用我说了,你也会拿着这个函数名去内核代码里面查找了吧^_^

要是查找出一堆函数,不知道用的是哪一个,那就接着用printk在各个函数里将该函数名的值(即它的地址)也打印出来,一对比不就清楚孰是孰非了吗。

祝你内核学习愉快^_^



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

寒江独钓2009

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值