systemtap-探秘五-编译和运行
经过前面几篇文章,我们已经走完了 systemtap 运行的前三个流程,只差最后的编译和运行了。 编译编译阶段没有什么要说的,唯一要说明的是 stap 生成的内核模块编译起来很耗时。一般来说,整个编译阶段会花上十几二十秒。所以在生成火焰图时,我通常会让 stap 空跑一遍,让它把内核模块编译出来,完成编译阶段后 Ctrl+C 中断掉它。等到正式压测时,再跑一遍。第二次跑的时候,由于可以用上第一次编译出来的内核,花在前四个阶段的时间会减少很多。 来说下最后的运行阶段。 加载stap 的最后一个阶段,其实是通过运行一个独立的 staprun 二进制文件实现的。这么设计的目的在于把对内核模块的准备和运行分离开来。我们之前执行的 stap 二进制文件可以只负责生成内核模块,然后在目标机器上通过 staprun 运行。这样做的一个好处在于目标机器上可以不用装许多依赖(比如 kernel debuginfo)。另外,在有些公司,服务器只能运行签过名的内核模块,这时候就能先通过 stap 生成内核模块,签了名之后再通过 staprun 运行。具体怎么操作,烦请参考 man staprun。 在 staprun/staprun_funcs.c 文件下,insert_module 函数调用了系统 API init_module,把生成的内核模块加载上去。感兴趣的可以 man init_module 了解下这个 API。 通讯加载的内核模块会创建 /sys/kernel/debug/systemtap/$module_name 这个目录, __stp_module_dir = debugfs_create_dir(module_name, root_dir);然后创建 /sys/kernel/debug/systemtap/$module_name/.cmd 这个文件。 /* create [debugfs]/systemtap/module_name/.cmd */ _stp_cmd_file = debugfs_create_file(".cmd", 0600, module_dir, NULL, &_stp_ctl_fops_cmd);debugfs_create_dir 和 debugfs_create_file 两者是内核模块提供的 API,用来创建一个 debugfs 下的“伪文件”。本着“一切皆文件”的传统,用户态程序可以通过读写这些“伪文件”来调用内核模块指定函数。 _stp_ctl_fops_cmd 这个结构体顾名思义,就是用在发送控制指令并接收响应的。我们可以看下它的定义: ...