首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用C编写DTrace使用者

用C编写DTrace使用者
EN

Stack Overflow用户
提问于 2015-01-18 15:38:40
回答 1查看 1.4K关注 0票数 10

我想在FreeBSD 10.1上编写一个C程序,它使用libdtrace实现DTrace使用者。

我知道我需要从调用dtrace_open()开始--例如,我已经找到了旧的演示文稿,但我甚至无法开始,因为没有安装dtrace.h (仅在系统源树中)。

已经安装了共享库,例如,与FreeBSD一起包含的FreeBSD工具可以充当DTrace使用者,并且这个工具链接到/lib/libdtrace.so.2 (这也是通过来自/usr/lib/libdtrace.so的符号链接)。

任何基本的示例,包括构建说明(FreeBSD 10.1 / clang)都将对我有很大帮助。

编写自定义用户的实际目标是创建一个可在PyPy.中使用的基于 CFFI 的包装器,这意味着:上面的C程序只是入门、学习和继续。

CFFI是一种推荐的、现代的、高性能的将PyPy与共享库连接起来的方法.

CFFI可以在ABI和API级别使用。后者需要包含一个头文件,前者需要声明库中使用的内容。

改编自亚当的答案,下面是一个适用于FreeBSD 10.1.的完整示例。

Makefile

代码语言:javascript
复制
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

代码语言:javascript
复制
#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;
}

跑:

代码语言:javascript
复制
[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
EN

回答 1

Stack Overflow用户

发布于 2015-01-21 19:15:08

dtrace被认为是一个系统内部接口,并且编写自定义使用者并不受支持。

您能做的最好的就是查看FreeBSD源代码树的副本,然后从那里构建代码。这其实并不难。显然,dtrace(1)是规范的dtrace使用者,因此您可以查看它的实现,以获得如何使用libdtrace的示例。此外,dtrace.h有大量的注释来解释数据结构和内部结构。

在源代码树的上下文中构建文件非常容易;FreeBSD源代码树布局很简单,编写Makefile来以一种独立的方式构建二进制文件基本上是“免费”的。

相关要点:

  • dtrace(1) Makefile克隆到源树签出中的新目录中。修改Makefile,使.PATH是正确的,并设置PROGSRCS,以包括包含自定义使用者的源集。
  • dtrace.c克隆到源目录(指向.PATH的任何位置),并根据需要进行更改。虽然源代码是近2,000行,但其中大部分是支持代码。如果您只是想克隆功能的一个子集,您会发现二进制的大多数选项都是在自带函数中实现的,因此,将dtrace.c缩减到一个最小的形式应该是相当容易的。

如果不知道您需要对自定义用户具体做什么,就很难告诉您还需要调用什么。我假设您可能希望文件编程都在里面。当然,你的需求可能会有所不同。

你会用提供了许多关于各种接口的注释。

希望这足以让您开始工作;不幸的是,没有一种方法可以通过普通安装来完成您想要的工作。当然,您可以利用相关的Makefile安装必要的头文件并创建您自己的内部发行版。但这似乎比它的价值更痛苦。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28011495

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档