C编写DTrace使用者 [英] Writing a DTrace consumer in C

查看:133
本文介绍了C编写DTrace使用者的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想写在FreeBSD 10.1 C程序实现一个的 DTrace使用者的使用 libdtrace

我知道,我要开始一起 dtrace_open()通话 - 例如我发现的老presentation,但我不能得到甚至开始,因​​为没有 dtrace.h 安装(仅在系统源代码树)。

共享库的安装,例如在 / usr / sbin目录/使用DTrace 工具包含在FreeBSD可以作为一个DTrace使用者与该工具的链接 /lib/libdtrace.so.2 <行动/ code>(这也是通过符号链接指向从 /usr/lib/libdtrace.so )。

任何基本的例子,包括建立指令(FreeBSD的10.1 /铛)将帮助我很多东西。


编写定制的消费者的实际目标是创建一个 CFFI 基于可用的Python包装和 PyPy 方式:。上面的C程序刚刚上手,学习,然后进行

CFFI是推荐的,现代的,高性能的共享库接口PyPy方式。

CFFI可以在 ABI 使用和API级别。后者需要一个头文件,包括,前者需要申报从一个lib使用的东西。


从亚当的回答改编,这里要说的是在FreeBSD 10.1使用一个完整的例子。

的Makefile

 所有:
        CC \\
         -I / usr / src目录/ CDDL / COMPAT / OpenSolaris的/包括\\
         -I / usr / src目录/ CDDL /的contrib / OpenSolaris的/ lib目录/ libdtrace /普通/ \\
         -I / usr / src目录/ SYS / CDDL / COMPAT / OpenSolaris的\\
         -I / usr / src目录/ SYS / CDDL /的contrib / OpenSolaris的/ UTS /普通/ \\
         hello_dtrace.c \\
         -l -l的DTrace -l PROC周大福-l精灵-lž-l rtld_db -l的pthread -l UTIL \\
         -o hello_dtrace

hello_dtrace.c

 的#include&LT; dtrace.h&GT;
#包括LT&;&signal.h中GT;
#包括LT&;&stdio.h中GT;静态dtrace_hdl_t * g_dtp;静态INT chewrec(常量dtrace_probedata_t *数据常量dtrace_recdesc_t * REC,无效* ARG){
   的printf(嚼DTrace的记录.. \\ n);
   //一个NULL REC表示,我们已处理的最后记录。
   如果(REC == NULL){
      返回(DTRACE_CONSUME_NEXT);
   }
   返回(DTRACE_CONSUME_THIS);
}静态为const char * g_prog ={(你好从DTrace的\\\\ñ\\BEGIN \\)printf的;};
//静态为const char * g_prog =系统调用::开*:进入{printf的(\\%s%S \\\\ñ\\,execname,copyinstr(为arg0));};静态INT g_intr;
静态INT g_exited;静态无效INTR(INT预兆报){
   g_intr = 1;
}
INT主(INT ARGC,字符** argv的){
   INT犯错;   如果((g_dtp = dtrace_open(DTRACE_VERSION,0,&安培;犯错))== NULL){
      fprintf中(标准错误,初始化失败的DTrace:%S \\ n,dtrace_errmsg(NULL,ERR));
      返回-1;
   }
   的printf(初始化的Dtrace \\ n);   (无效)dtrace_setopt(g_dtp,BUFSIZE,4M);
   (无效)dtrace_setopt(g_dtp,aggsize,4M);
   的printf(DTrace的选项设置\\ n);   dtrace_prog_t * PROG;
   如果((PROG = dtrace_program_strcompile(g_dtp,g_prog,DTRACE_PROBESPEC_NAME,0,0,NULL))== NULL){
      fprintf中(标准错误,无法编译DTrace的程序\\ n);
      返回-1;
   }其他{
      的printf(DTrace的程序编译\\ n);
   }   dtrace_proginfo_t信息;
   如果(dtrace_program_exec(g_dtp,PROG,&安培;信息)== -1){
      fprintf中(标准错误,未能使DTrace探测器的\\ n);
      返回-1;
   }其他{
      的printf(DTrace探测器启用\\ n);
   }   结构sigaction的行为;
   (无效)sigemptyset(安培; act.sa_mask);
   act.sa_flags = 0;
   act.sa_handler = INTR;
   (无效)的sigaction(SIGINT,和放大器;行为,NULL);
   (无效)的sigaction(SIGTERM,&安培;行为,NULL);   如果(dtrace_go(g_dtp)!= 0){
      fprintf中(标准错误,无法启动仪器\\ n);
      返回-1;
   }其他{
      的printf(仪器开始.. \\ n);
   }   做了诠释= 0;
   做{
      如果(g_intr&安培;!&安培;!完成){
         dtrace_sleep(g_dtp);
      }      如果(做|| g_intr || g_exited){
         做= 1;
         如果(dtrace_stop(g_dtp)== -1){
            fprintf中(标准错误,无法停止跟踪\\ n);
            返回-1;
         }
      }      开关(dtrace_work(g_dtp,标准输出,NULL,chewrec,NULL)){
         案例DTRACE_WORKSTATUS_DONE:
            做= 1;
            打破;
         案例DTRACE_WORKSTATUS_OKAY:
            打破;
         默认:
            fprintf中(标准错误,处理中止);
            返回-1;
      }
   }而(!做);   输出(关DTrace的\\ n);
   dtrace_close(g_dtp);   返回0;
}

要运行:

  [oberstet @ brummer2〜/ hello_dtrace] $作;须藤./hello_dtrace
CC -I / usr / src目录/ CDDL /的contrib / OpenSolaris的/ lib目录/ libdtrace /普通/ -I / usr / src目录/ SYS / CDDL / COMPAT / OpenSolaris的-I / usr / src目录/ SYS / CDDL /的contrib / OpenSolaris的/ UTS /普通/ hello_dtrace.c -l的DTrace -l PROC -l周大福-l精灵-l rtld_db -lz -l的pthread -l UTIL -o hello_dtrace
DTrace的初始化
DTrace的选项设置
DTrace的程序编译
启用DTrace探测器
仪表开始..
咀嚼的DTrace记录..
从打招呼的DTrace
咀嚼的DTrace记录..
^ Cclosing的DTrace


解决方案

libdtrace API不一定适用于稳定的消费者,但它是pretty容易从一些现有消费者学会上手。最简单和最现代的是<一个href=\"https://github.com/illumos/illumos-gate/blob/31c6d826a7f7a4ee7d83c8e99f25d82a4a248076/usr/src/cmd/plockstat/plockstat.c\"><$c$c>plockstat,在Illumos的实用程序用户锁定土地统计。

下面是一个简单的DTrace使用者程序的基本流程:

dtrace_open()来得到一个dtrace_hdl_t,对于其他 libdtrace 交互的手柄

dtrace_setopt()配置选项( -x 标志的DTrace(1M)

dtrace_strcompile()编译D程序
的字符串
dtrace_program_exec()到该程序传送到内核

dtrace_go()来检测系统,并开始记录数据

dtrace_close()
清理

有关主数据收集循环(与 dtrace_go() dtrace_close())执行以下操作:

dtrace_sleep()来根据的DTrace选项暂停(switchrate和aggrate)

dtrace_work()来处理跟踪数据

dtrace_stop()中止

请参阅<一个主循环href=\"https://github.com/illumos/illumos-gate/blob/31c6d826a7f7a4ee7d83c8e99f25d82a4a248076/usr/src/cmd/plockstat/plockstat.c#L971\"><$c$c>plockstat.c更多。

有关其他简单的DTrace使用者,检查<一href=\"https://github.com/illumos/illumos-gate/blob/31c6d826a7f7a4ee7d83c8e99f25d82a4a248076/usr/src/cmd/intrstat/intrstat.c\"><$c$c>intrstat和<一个href=\"https://github.com/illumos/illumos-gate/blob/31c6d826a7f7a4ee7d83c8e99f25d82a4a248076/usr/src/cmd/lockstat/lockstat.c\"><$c$c>lockstat.对于厨房水槽,检查出code中的使用DTrace(1M)命令行实用工具。

I'd like to write a C program on FreeBSD 10.1 that implements a DTrace consumer using libdtrace.

I know that I need to start with a call to dtrace_open() - e.g. I have found this old presentation, but I can't get even started, since there is no dtrace.h installed (only in the system source tree).

The shared library is installed, e.g. the /usr/sbin/dtrace tool included with FreeBSD can act as a DTrace consumer and this tool links to /lib/libdtrace.so.2 (which is also pointed to via a symbolic link from /usr/lib/libdtrace.so).

Any basic example, including build instructions (FreeBSD 10.1 / clang) will help me a lot.


The actual goal of writing a custom consumer is creating a CFFI based wrapper usable in Python and PyPy. Means: above C program is just to get started, learn and then proceed.

CFFI is the recommended, modern, high-performance way of interfacing PyPy with shared libraries.

CFFI can be used at the ABI and API level. The latter requires a header file to include, the former requires to declare the stuff used from a lib.


Adapted from Adam's answer, here is a complete example that works on FreeBSD 10.1.

Makefile:

all:
        cc \
         -I /usr/src/cddl/compat/opensolaris/include \
         -I /usr/src/cddl/contrib/opensolaris/lib/libdtrace/common/ \
         -I /usr/src/sys/cddl/compat/opensolaris \
         -I /usr/src/sys/cddl/contrib/opensolaris/uts/common/ \
         hello_dtrace.c \
         -l dtrace -l proc -l ctf -l elf -l z -l rtld_db -l pthread -l util \
         -o hello_dtrace

hello_dtrace.c:

#include <dtrace.h>
#include <signal.h>
#include <stdio.h>

static dtrace_hdl_t* g_dtp;

static int chewrec (const dtrace_probedata_t *data, const dtrace_recdesc_t *rec, void *arg) {
   printf("chewing dtrace record ..\n");
   // A NULL rec indicates that we've processed the last record.
   if (rec == NULL) {
      return (DTRACE_CONSUME_NEXT);
   }
   return (DTRACE_CONSUME_THIS);
}

static const char* g_prog = "BEGIN { printf(\"hello from dtrace\\n\"); }";
//static const char* g_prog = "syscall::open*:entry { printf(\"%s %s\\n\", execname, copyinstr(arg0)); }";

static int g_intr;
static int g_exited;

static void intr (int signo) {
   g_intr = 1;
}


int main (int argc, char** argv) {
   int err;

   if ((g_dtp = dtrace_open(DTRACE_VERSION, 0, &err)) == NULL) {
      fprintf(stderr, "failed to initialize dtrace: %s\n", dtrace_errmsg(NULL, err));
      return -1;
   }
   printf("Dtrace initialized\n");

   (void) dtrace_setopt(g_dtp, "bufsize", "4m");
   (void) dtrace_setopt(g_dtp, "aggsize", "4m");
   printf("dtrace options set\n");

   dtrace_prog_t* prog;
   if ((prog = dtrace_program_strcompile(g_dtp, g_prog, DTRACE_PROBESPEC_NAME, 0, 0, NULL)) == NULL) {
      fprintf(stderr, "failed to compile dtrace program\n");
      return -1;
   } else {
      printf("dtrace program compiled\n");
   }

   dtrace_proginfo_t info;
   if (dtrace_program_exec(g_dtp, prog, &info) == -1) {
      fprintf(stderr, "failed to enable dtrace probes\n");
      return -1;
   } else {
      printf("dtrace probes enabled\n");
   }

   struct sigaction act;
   (void) sigemptyset(&act.sa_mask);
   act.sa_flags = 0;
   act.sa_handler = intr;
   (void) sigaction(SIGINT, &act, NULL);
   (void) sigaction(SIGTERM, &act, NULL);

   if (dtrace_go(g_dtp) != 0) {
      fprintf(stderr, "could not start instrumentation\n");
      return -1;
   } else {
      printf("instrumentation started ..\n");
   }

   int done = 0;
   do {
      if (!g_intr && !done) {
         dtrace_sleep(g_dtp);
      }

      if (done || g_intr || g_exited) {
         done = 1;
         if (dtrace_stop(g_dtp) == -1) {
            fprintf(stderr, "could not stop tracing\n");
            return -1;
         }
      }

      switch (dtrace_work(g_dtp, stdout, NULL, chewrec, NULL)) {
         case DTRACE_WORKSTATUS_DONE:
            done = 1;
            break;
         case DTRACE_WORKSTATUS_OKAY:
            break;
         default:
            fprintf(stderr, "processing aborted");
            return -1;
      }
   } while (!done);

   printf("closing dtrace\n");
   dtrace_close(g_dtp);

   return 0;
}

To run:

[oberstet@brummer2 ~/hello_dtrace]$ make; sudo ./hello_dtrace
cc  -I /usr/src/cddl/contrib/opensolaris/lib/libdtrace/common/  -I /usr/src/sys/cddl/compat/opensolaris  -I /usr/src/sys/cddl/contrib/opensolaris/uts/common/  hello_dtrace.c  -l dtrace  -l proc  -l ctf  -l elf  -l rtld_db  -l z  -l pthread  -l util  -o hello_dtrace
Dtrace initialized
dtrace options set
dtrace program compiled
dtrace probes enabled
instrumentation started ..
chewing dtrace record ..
hello from dtrace
chewing dtrace record ..
^Cclosing dtrace

解决方案

The libdtrace API isn't necessarily intended for stable consumers, but it's pretty easy to learn from some existing consumers to get started. The simplest and most modern is plockstat, the illumos utility for user-land locking statistics.

Here's the basic flow of a simple DTrace consumer program:

dtrace_open() to get a dtrace_hdl_t, a handle for other libdtrace interactions
dtrace_setopt() to configure options (-x flag to dtrace(1M))
dtrace_strcompile() to compile a string of your D program
dtrace_program_exec() to send that program to the kernel
dtrace_go() to instrument the system and start recording data
dtrace_close() to clean up at the end

For the main data collection loop (between dtrace_go() and dtrace_close()) do the following:

dtrace_sleep() to pause according to the DTrace options (switchrate and aggrate)
dtrace_work() to process traced data
dtrace_stop() to abort

See the main loop in plockstat.c for more.

For other simple DTrace consumers, check out intrstat and lockstat. For the kitchen sink, check out the code the the dtrace(1M) command-line utility.

这篇关于C编写DTrace使用者的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆