用python从C代码中提取函数名及其注释(了解Linux内核)

Backrground信息

我刚开始学习有关驱动程序和Linux内核的东西。 我想了解用户如何write()read()作品。 所以我开始使用ftrace来希望看到函数的path。 但是像下面这样的单一程序的痕迹是“巨大的”。

 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() ,我想,这正是我所search的。 所以我查了一下。 down_write()源代码 :

  /* * 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); } 

但事实certificate,这只是locking和释放锁。 然后我开始为我写一个小的参考资料,所以我不必总是查阅这个东西,因为它有9000多个。然后我有这个想法,为什么不呢,parsing这些函数和他们的意见并把它们写在跟踪文件中的函数之后? 喜欢这个:

  [...] 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函数和注释,我必须定义和实现一个recursion匹配语法:(

2.问题
有些函数只是包装,没有评论。 例如, do_brk()包装__do_brk() ,注释仅在__do_brk()

所以我想,也许还有其他来源的意见。 也许文档? 也有可能,这个与Python的“文档一代”有人已经实施。

或者是我的方式来理解一个系统read() write()非常不智能? 你可以给我一些我应该更深入的了解吗?

非常感谢您的阅读,
法比安

解析评论在实践中相当困难。 解析内核代码并不容易。

首先,您应该明确了解Linux内核中的系统调用 ,以及应用程序如何使用它们。 Linux Assembly HowTo有很好的解释。

那么,你应该了解Linux内核的组织。 我强烈建议阅读一些关于此的好书。

使用自动工具来探索内核源代码是一个很大的工作量(几个月,而不是几天)。 你可能会考虑使用coccinelle工具(所谓的“语义补丁”)。 你也可以考虑使用插件定制GCC编译器,或者更好的是使用MELT扩展

(MELT是扩展GCC的高级领域特定语言;我是它的主要设计者和实现者)。

如果与GCC合作,您将获得GCC内部表示和中间处理的所有权力(但在此阶段,评论将丢失)。

你想要做的事情可能是你最初的想法更加雄心勃勃。 另请参阅Alexandre Lissy的工作,例如模型检查Linux内核和他将在Linux Symposium 2012 (2012 年 7月)

是的,你的方法是正确的:学习内核,总是从系统调用开始。 内核代码=以比普通代码更高的特权执行的代码。 英特尔有大约18(不确定)特权指令集。

http://duartes.org/gustavo/blog/post/cpu-rings-privilege-and-protection/

http://en.wikipedia.org/wiki/Privilege_level

当用户代码从低权限级别转换到高权限级别执行这些特殊指令时,它通过一个标准的系统调用机制。

做一个简单的“strace ls”,你可以看到许多正在执行的系统调用:每一个都必须转换到内核来执行一些任务。

编写一个简单的脚本(如内核版本依赖,针对您的特定内核,请参阅/ sys / kernel / debug / tracing / README):

 echo function > /sys/kernel/debug/tracing/current_tracer cat /sys/kernel/debug/tracing/current_tracer echo 1 > /sys/kernel/debug/tracing/tracing_on ls /tmp cat /sys/kernel/debug/tracing/trace echo 0 > /sys/kernel/debug/tracing/tracing_on 

我们将得到以下输出(在删除所有非ls ftrace输出后):

http://pastebin.com/vEk2NrDQ

上面的ftrace输出显示了从用户空间执行“ls”时执行的实际内核函数。 并不是每个功能都需要被理解或者是重要的。 学习内核API本身也不是。 但更重要的是有很多概念:如何在不同CPU,不同进程,不同类型的同步原语之间共享资源等。

享受每一个小小的步骤…..一次一个。