背景信息
我刚刚开始学习有关驱动程序和linux内核的知识.我想了解用户write()和read()的工作方式.因此,我开始使用ftrace来查看函数的运行路径.
但是像下面这样的单个程序的跟踪结果是“巨大的”.
int main() {
int w;
char buffer[] = "test string mit 512 byte";
int fd = open("/dev/sdd",O_DIRECT | O_RDWR | O_SYNC);
w = write(fd,buffer,sizeof(buffer));
}
我也不知道可以过滤哪些功能,因为我不了解Linux内核,也不想丢掉一些重要的东西.
因此,我开始研究function_graph跟踪.这是一个片段.
[...]
12) 0.468 us | .down_write();
12) 0.548 us | .do_brk();
12) 0.472 us | .up_write();
12) 0.762 us | .kfree();
12) 0.472 us | .fput();
[...]
我看到了这些.down_write()和.up_write(),我认为,这正是我要搜索的内容.所以我查了一下. down_write() sourcecode:
/*
* lock for writing
*/
void __sched down_write(struct rw_semaphore *sem)
{
might_sleep();
rwsem_acquire(&sem->dep_map, 0, 0, _RET_IP_);
LOCK_CONTENDED(sem, __down_write_trylock, __down_write);
}
但是事实证明,这只是为了锁定和释放锁.
然后,我开始为我写一个小参考,所以我不必总是去查找这些东西,因为它的数量可能超过9000.然后我有了一个主意,为什么不解析这些函数及其注释呢?并将它们写在跟踪文件中的函数后面?像这样:
[...]
12) 0.468 us | .down_write(); lock for writing
12) 0.548 us | .do_brk();
12) 0.472 us | .up_write(); release a write lock
12) 0.762 us | .kfree();
12) 0.472 us | .fput();
[...]
主要问题
因此,我开始考虑如何实现这一目标.我想用python来做,因为我觉得最舒服.
1.问题
为了匹配C函数和注释,我必须定义和实现一个递归匹配语法:(
2.问题
有些功能只是包装器,没有注释.例如do_brk()包装__do_brk(),并且注释仅在__do_brk()上
所以我认为,也许还有其他评论来源.也许是文档?还有可能,这种使用python的“文档生成”已经实现了.
还是我理解系统read()write()的方式非常不智能?你能给我小费我应该如何更深入地挖掘吗?
非常感谢您的阅读,
法比安
解决方法:
在实践中解析注释非常困难.解析内核代码并不是特别容易.
首先,您应该准确了解linux kernel中的system call,以及应用程序如何使用它们. Linux Assembly HowTo有很好的解释.
然后,您应该了解Linux内核的组织.我强烈建议您阅读一些不错的书.
使用自动工具探索内核源代码需要大量的工作(几个月而不是几天).您可能考虑使用coccinelle工具(用于所谓的“语义补丁”).您也可以考虑使用插件或更好的自定义GCC编译器(扩展为MELT)
(MELT是扩展GCC的高级领域特定语言;我是它的主要设计者和实现者).
如果使用GCC,您将在中端获得GCC内部表示和处理的所有功能(但在此阶段,注释会丢失).
您尝试做的可能比您最初想的要雄心勃勃.另请参见Alexandre Lissy的作品,例如model-checking the linux kernel和他将在Linux Symposium 2012(2012年7月)上发表的论文