सी

2015-01-18 8 views
8

में एक डीटीआर उपभोक्ता लिखना मैं फ्रीबीएसडी 10.1 पर एक सी प्रोग्राम लिखना चाहता हूं जो डीटी्रेस उपभोक्ताlibdtrace का उपयोग कर लागू करता है।सी

मुझे पता है कि मुझे dtrace_open() पर कॉल के साथ शुरू करने की आवश्यकता है - उदा। मुझे this पुरानी प्रस्तुति मिली है, लेकिन मैं भी शुरू नहीं कर सकता, क्योंकि dtrace.h स्थापित नहीं है (केवल सिस्टम स्रोत पेड़ में)।

साझा लाइब्रेरी स्थापित है, उदा। /usr/sbin/dtrace फ्रीबीएसडी के साथ शामिल टूल एक डीटीआरएस उपभोक्ता के रूप में कार्य कर सकता है और यह टूल /lib/libdtrace.so.2 से लिंक करता है (जिसे /usr/lib/libdtrace.so से प्रतीकात्मक लिंक के माध्यम से भी इंगित किया जाता है)।

बिल्ड निर्देशों (फ्रीबीएसडी 10.1/क्लैंग) सहित कोई भी मूल उदाहरण मुझे बहुत मदद करेगा।


एक कस्टम उपभोक्ता एक CFFI आधारित आवरण अजगर और PyPy में प्रयोग करने योग्य पैदा कर रही है लेखन के वास्तविक लक्ष्य। मतलब: उपरोक्त सी प्रोग्राम शुरू करने के लिए है, सीखें और फिर आगे बढ़ें।

CFFI साझा पुस्तकालयों के साथ पीईपीई इंटरफेस करने की अनुशंसित, आधुनिक, उच्च-प्रदर्शन तरीका है।

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 
+0

सुनिश्चित नहीं हैं कि इस मदद करता है, लेकिन आप https://wiki.freebsd.org/DTrace की कोशिश कर सकते हैं। वहां कोड के उदाहरण हैं। – user590028

+1

धन्यवाद, मैं इन पढ़ा है, लेकिन यह खुलासा नहीं करता है कैसे सी में एक कस्टम उपभोक्ता लिखने के लिए – oberstet

+0

इतना पैडेंटिक होने के लिए खेद है, लेकिन क्या आपने उस साइट से https://wiki.freebsd.org/DTrace/KernelSupport पर लिंक भी पढ़ा था। अतिरिक्त 'मेक बिल्डवर्ल्ड' के लिए निर्देश हैं जो मुझे लगता है कि आप जिस समर्थन फ़ाइलों को ढूंढ रहे हैं उन्हें खींचेंगे। – user590028

उत्तर

7

libdtrace एपीआई जरूरी स्थिर उपभोक्ताओं के लिए इरादा नहीं है, लेकिन यह कुछ मौजूदा उपभोक्ताओं से जानने के लिए शुरू करने के लिए बहुत आसान है। सबसे सरल और सबसे आधुनिक plockstat है, उपयोगकर्ता-भूमि लॉकिंग आंकड़ों के लिए illumos उपयोगिता।

dtrace_open() एक dtrace_hdl_t प्राप्त करने के लिए, अन्य libdtrace बातचीत के लिए एक संभाल
dtrace_setopt() विकल्पों को कॉन्फ़िगर करने (-x झंडा dtrace(1M) करने के लिए)
dtrace_strcompile() एक स्ट्रिंग संकलित करने के लिए:

यहाँ एक सरल DTrace उपभोक्ता कार्यक्रम के बुनियादी प्रवाह है आपके डी प्रोग्राम
dtrace_program_exec() उस प्रोग्राम को कर्नेल
dtrace_go() सिस्टम को उपकरण के लिए भेजने और डेटा रिकॉर्डिंग शुरू करने के लिए,210 dtrace_close() अंत

मुख्य डेटा संग्रह लूप (dtrace_go() और dtrace_close() के बीच) के लिए कम से साफ करने के लिए निम्न करें:

dtrace_sleep() DTrace विकल्प (switchrate और aggrate)
dtrace_work() के अनुसार रोकने के लिए पता लगाया डेटा
dtrace_stop() कार्रवाई करने के लिए निरस्त करने के लिए

अधिक के लिए plockstat.c में मुख्य लूप देखें।

अन्य साधारण DTrace उपभोक्ताओं के लिए, बाहर intrstat और lockstat की जाँच करें। रसोई सिंक के लिए, कोड को dtrace (1M) कमांड लाइन उपयोगिता देखें।

+0

बहुत बढ़िया! मुझे फ्रीबीएसडी पर काम करने वाला कुछ मिला (प्रश्न शरीर में जोड़ा गया)। ऐसा लगता है, 'plockstat' में मुख्य लूप' dtrace_sleep' में अवरुद्ध है, जबकि 'intrstat'' sigsuspend' में उच्च आवृत्ति टाइमर और ब्लॉक सेट करता है। दोनों कॉलिंग थ्रेड ब्लॉक। किसी भी संकेत पर मुझे किस दृष्टिकोण पर पालन करना चाहिए? – oberstet

+0

आह, और एक और बात: आखिरकार, यह एक ऐसे प्रोग्राम में चल रहा है जिसमें एसिंक्रोनस रिएक्टर/इवेंट लूप (पायथन ट्विस्ट/एसिन्सीओ) है। इस संदर्भ में, किसी को कभी भी (मुख्य) थ्रेड को अवरुद्ध नहीं करना चाहिए (क्योंकि रिएक्टर लूप कॉल (')', 'मतदान()' या 'एफडी के लिए तैयार होने के लिए इंतजार कर रहा है' के लिए कॉल के अंदर खुद को अवरुद्ध करना चाहता है। इसलिए मुझे बैकग्राउंड थ्रेड (कौन सा ब्लॉक) पृष्ठभूमि थ्रेड पर चलने की आवश्यकता है। उसके साथ कोई समस्या है? – oberstet

3

dtrace एक प्रणाली आंतरिक इंटरफ़ेस माना जाता है, और एक कस्टम उपभोक्ता लेखन कुछ नहीं है कि समर्थित है।

सबसे अच्छा आप फ्रीबीएसडी स्रोत पेड़ की प्रतिलिपि देख सकते हैं और वहां से अपना कोड बना सकते हैं। यह वास्तव में बहुत मुश्किल नहीं है। जाहिर है, dtrace(1) कैनोनिकल ड्रेसेज उपभोक्ता है, इसलिए आप libdtrace का उपयोग करने के उदाहरणों के उदाहरणों के कार्यान्वयन को देख सकते हैं। इसके अतिरिक्त dtrace.h में डेटा संरचनाओं और आंतरिकों को समझाते हुए बड़ी संख्या में टिप्पणियां हैं।

स्रोत पेड़ के संदर्भ में फ़ाइलों का निर्माण करना बहुत आसान है; फ्रीबीएसडी स्रोत पेड़ लेआउट सरल है और स्वयं को निहित तरीके से बाइनरी बनाने के लिए मेकफ़ाइल लिखना मूल रूप से आपको "मुफ्त में" दिया जाता है।

प्रासंगिक अंक:

  • अपने स्रोत पेड़ चेकआउट में एक नया निर्देशिका में क्लोन the dtrace(1) Makefile।मेकफ़ाइल को संशोधित करें कि .PATH सही है, और अपने कस्टम उपभोक्ता समेत स्रोतों के सेट को शामिल करने के लिए PROG और SRCS सेट करें।

  • क्लोन dtrace.c अपने स्रोत निर्देशिका के लिए और आवश्यकतानुसार परिवर्तन कर (जहाँ आप .PATH की ओर इशारा)। हालांकि स्रोत लगभग 2,000 लाइनें है, इसमें से अधिकांश समर्थन कोड है। यदि आप केवल कार्यक्षमता के उप-समूह को क्लोन करना चाहते हैं, तो आप पाएंगे कि बाइनरी के अधिकांश विकल्प स्व-निहित कार्यों में लागू किए गए हैं, और इसलिए dtrace.c को कम-से-कम तक ट्रिम करना काफी आसान होना चाहिए प्रपत्र।

जानते हुए भी आप अपने कस्टम उपभोक्ता के साथ क्या करने की जरूरत के लिए विशेष रूप से कर रहे हैं क्या बिना, यह बताने के लिए और क्या आप में कॉल करने के लिए की आवश्यकता होगी मुश्किल है। मुझे लगता है कि आप शायद compile_file और साथ ही साथ exec_prog चाहते हैं। बेशक, आपकी जरूरतें अलग-अलग हो सकती हैं।

dtrace.h you will be using में प्रदान किए गए विभिन्न इंटरफेस के बारे में कई टिप्पणियां हैं।

उम्मीद है कि यह आपको शुरू करने के लिए पर्याप्त है; दुर्भाग्य से, वेनिला इंस्टॉल से आप जो चाहते हैं उसे करने का कोई तरीका नहीं है। आप निश्चित हेडर फाइलों को स्थापित करने और अपना आंतरिक वितरण बनाने के लिए प्रासंगिक मेकफ़ाइल को हॅक कर सकते हैं। लेकिन यह इसके लायक से ज्यादा दर्द की तरह लगता है।

+0

आपके विस्तृत उत्तर के लिए धन्यवाद। कृपया मुझे कोशिश करने के लिए कुछ समय दें, और https://twitter.com/ahl/status/557981334615126016 की वजह से - मैंने कस्टम उपभोक्ता – oberstet

+1

के साथ मेरे वास्तविक लक्ष्यों के लिए प्रश्न अपडेट किया है आपका स्वागत है! मुझे उत्तर पर विस्तार करने के लिए खुशी है/स्वीकार्य उत्तर प्रदान करने के लिए क्या करने की आवश्यकता है, इस बारे में अधिक अंतर्दृष्टि प्रदान करने में मुझे खुशी है। (हाय, एडम!) – dho