КатегорииLinksUnix Tutorial
Personal Development Ruslan Valiev Solaris Performance Team Damien Farnham Fintan Ryan Nicky Veitch Niall Mullen Sean McGrath DTrace Bryan Cantrill Brendan Gregg ZFS Tim Foster General Ben Rockwood Learning Solaris 10 Privacy policy Архивы |
Saturday, 26 February. 2005
DTrace: провайдер pid Добавил Gleb Reys
в категории DTrace в
23:52
Комментарии (0) Обратные ссылки (0) Select language: English Defined tags for this entry: dtrace
DTrace: провайдер pid
При исследовании пользовательских процессов, часто нас интересует какой-то конкретный процесс. Поэтому мы используем переменную $target (я о ней уже рассказывал немного) или же просто номер процесса (pid) в предикатах наших проб, указывая таким образом DTrace наш особый интерес к тому или иному процессу.
Для начинающих работу с DTrace - это вполне приемлемая тактика. Но есть и более правильный способ: использование провайдера pid. Как говорится в официальном руководстве, провайдер pid - это на самом деле не просто провайдер DTrace, а целый класс провайдеров. Как видно из названия, он предлагает нам пробы, относящиеся к конкретному процессу. Скажем, провайдер pid737 предоставляет возможность следить за процессом с pid=737, и т.д. Более того - становится гораздо удобнее не только выделять интересующие нас пробы, но и понимать, на основе каких функций они создаются для каждого процесса. Такой способ отладки конкретного процесса, в отличие от пробы с использованием предиката типа /pid == $target/, является более правильным. Вместо того, чтобы указанные пробы активизировались и предикат проверялся для каждого процесса, теперь DTrace и смотреть не станет на другие процессы - и лишь только для одного, нужного нам, и будут активированы указанные пробы. Переменную $target по-прежнему можно и даже нужно использовать при создании наших проб с использованием провайдера pid. Мы уже знаем, как получить список проб, доступных DTrace. Я об этом уже рассказывал здесь. Так вот, стоит нам лишь один раз использовать провайдер pid для какого-то процесса, как dtrace -l начнёт нам показывать пробы, динамически созданные для него. Если процесс завершит работу, соответствующий провайдер исчезнет из списка доступных проб. Ещё одно удобство провайдера pid - это то, что в качестве модулей провайдера выступают библиотеки, подключаемые при выполнении исследуемого процесса. Соответственно, можно создавать пробы для отслеживания только лишь функций, выполняемых какой-то конкретной библиотекой. Очень удобно. Вот маленький примерчик. Берём самую обычную Hello, world! программку на C: CODE: void main() { printf("Hello, world!\n"); } После того, как мы получили исполняемый файл, принимаемся за наш очередной DTrace-скрипт: CODE: #!/usr/sbin/dtrace -s #pragma D option quiet BEGIN { printf("Target pid: %d\n", $target); } pid$target:::entry { printf("%s:%s:%s:%s\n", probeprov, probemod, probefunc, probename); } Сохраняем скрипт, делаем этот файл исполняемым, и запускаем его, указывая в параметре нашу hello: CODE: $ ./pid-global.d -c ./hello | more Target pid: 1059 Hello, world! pid1059:LM1`ld.so.1:call_array:entry pid1059:LM1`ld.so.1:call_init:entry pid1059:LM1`ld.so.1:leave:entry pid1059:LM1`ld.so.1:fmap_setup:entry pid1059:LM1`ld.so.1:munmap:entry pid1059:LM1`ld.so.1:rt_bind_clear:entry pid1059:LM1`ld.so.1:_rt_bind_clear:entry pid1059:LM1`ld.so.1:rt_mutex_unlock:entry pid1059:LM1`ld.so.1:_rt_null:entry pid1059:LM1`ld.so.1:rt_bind_clear:entry pid1059:LM1`ld.so.1:_rt_bind_clear:entry pid1059:libc.so.1:libc_init:entry pid1059:libc.so.1:__amd64id:entry pid1059:libc.so.1:atexit:entry pid1059:libc.so.1:lmalloc:entry pid1059:libc.so.1:getbucketnum:entry ... Длинный список получится, почти 1000 строк - так что все показывать не буду, но идея, надеюсь, понятна. Видно, какие функции каждой библиотеки можно отследить средствами DTrace. Очевидным будем из всего этого списка воспользоваться пробой, которая поймает наш printf: CODE: #!/usr/sbin/dtrace -s #pragma D option quiet BEGIN { printf("Target pid: %d\n", $target); } pid$target::printf:entry { printf("%s:%s:%s:%s\n", probeprov, probemod, probefunc, probename); printf("Argument: %s\n", copyinstr(arg0)); } Если запустить этот скрипт и передать ему нашу hello, как и в первом примере, то получится вот что: CODE: $ ./pid-printf.d -c ./hello
Target pid: 1201 Hello, world! pid1201:libc.so.1:printf:entry Argument: Hello, world! |




