Я хотел бы написать программу C на FreeBSD 10.1, которая реализует DTrace-потребитель с использованием libdtrace
.Написание потребителя DTrace в C
Я знаю, что мне нужно начать с звонка dtrace_open()
- например. Я нашел this старую презентацию, но я не могу даже начать, так как нет dtrace.h
(только в исходном дереве системы).
Общая библиотека установлена, например. инструмент /usr/sbin/dtrace
, входящий в состав FreeBSD, может выступать в качестве потребителя DTrace, и этот инструмент ссылается на /lib/libdtrace.so.2
(на который также указывается символьная ссылка от /usr/lib/libdtrace.so
).
Любой базовый пример, включая инструкции по сборке (FreeBSD 10.1/clang), очень поможет мне.
Фактическая цель написания пользовательского потребителя является создание на основе обертку CFFI годный к употреблению в Python и PyPy. Средство: выше программы C только для начала, изучения, а затем продолжить.
CFFI - рекомендуемый, современный высокопроизводительный способ взаимодействия PyPy с общими библиотеками.
CFFI может использоваться на уровне ABI и API. Последнее требует, чтобы заголовочный файл включался, первый должен объявить материал, используемый в lib.
Адаптированный ответ Адама, вот полный пример, который работает на 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;
}
Для запуска:
[[email protected] ~/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
Не уверен, что это помогает, но вы можете попробовать https://wiki.freebsd.org/DTrace. Там есть примеры кода. – user590028
Спасибо, я прочитал их, но он не раскрывает, как писать пользовательского потребителя в C. – oberstet
Извините, что так педантичен, но вы также прочитали ссылку с этого сайта на https://wiki.freebsd.org/DTrace/KernelSupport. Есть инструкции для дополнительных 'make buildworld', которые, я думаю, будут тянуть файлы поддержки, которые вы ищете. – user590028