Изучение Dtrace лучше начать c простых вызовов, использующих пробу BEGIN, которая включается каждый раз, когда мы запускаем какую-либо трассировку.
Для включения пробы запустите dtrace с опцией -n, например:
После короткой паузы dtrace сообщит о включении пробы BEGIN. В выводе видно что dtrace ожидает включения других проб. Так как пока нам не нужны другие пробы, нажмем Control-C для возврата в shell:
# dtrace -n BEGIN
dtrace: description 'BEGIN' matched 1 probe
CPU ID FUNCTION:NAME
0 1 :BEGIN
^C
Вывод показывает что включена одна проба BEGIN и сообщает ее имя и ID - 1. По дефолту выводится номер CPU, на котором включена проба. В примере dtrace использует CPU 0. Можно конструировать Dtrace-вызовы используя различные номера проб и действия.
Создадим простой вызов двух проб, добавив пробу END в предыдущий вызов.
Проба END включается по завершении трассировки:
# dtrace -n BEGIN -n END
dtrace: description 'BEGIN' matched 1 probe
dtrace: description 'END' matched 1 probe
CPU ID FUNCTION:NAME
0 1 :BEGIN
^C
0 2 :END
Нажатие Control-C завершило вызов и включило пробу END. Dtrace перед выходом сообщает о включении пробы.
Откуда же берутся пробы? Пробы DTrace создаются модулями ядра - провайдерами,каждый из которых имеет специфический набор инструментов для создания проб. Например провайдер syscall обеспечивает пробы для каждого системного вызова, а провайдер fbt обеспечивает пробы для каждой функции в ядре.
Когда мы запускаем DTrace, каждый провайдер создает те пробы, которые необходимы DTrace. После этого можно задействовать трассировки для каждой из созданных проб.
Дадим следующую команду:
ID PROVIDER MODULE FUNCTION NAME
1 dtrace BEGIN
2 dtrace END
3 dtrace ERROR
4 nfsmapid260 nfsmapid check_domain daemon-domain
5 nfsmapid260 nfsmapid resolv_query_thread thread-domain
6 syscall nosys entry
7 syscall nosys return
...
Dtrace выводит все пробы, существующие в нашей системе, где:
- ID - внутренний ID пробы
- Provider - Имя провайдера.
- Module - Имя Unix-модуля или библиотеки приложения для пробы
- Function - Имя функции в которой существует проба
- Name - Имя пробы
Найдем общее число всех проб в нашей системе:
# dtrace -l | wc -l
44961
Это число всех проб в системе (зависит от типа системы).
Можно также отфильтровать вывод с помощью опций:
-P для провайдера
-m для модуля
-f для функции
-n для имени
Например:
# dtrace -l -P lockstat
ID PROVIDER MODULE FUNCTION NAME
1535 lockstat genunix mutex_enter adaptive-acquire
1536 lockstat genunix mutex_enter adaptive-block
1537 lockstat genunix mutex_enter adaptive-spin
1538 lockstat genunix mutex_exit adaptive-release
1539 lockstat genunix mutex_destroy adaptive-release
1540 lockstat genunix mutex_tryenter adaptive-acquire
1541 lockstat genunix lock_set spin-acquire
1542 lockstat genunix lock_set spin-spin
1543 lockstat genunix lock_set_spl spin-acquire
1544 lockstat genunix lock_set_spl spin-spin
1545 lockstat genunix lock_try spin-acquire
...
Выводятся только пробы провайдера lockstat.
# dtrace -l -m ufs|more
ID PROVIDER MODULE FUNCTION NAME
770 sysinfo ufs ufs_idle_free ufsinopage
771 sysinfo ufs ufs_idle_free ufsipage
772 sysinfo ufs ufs_iget_internal ufsiget
773 sysinfo ufs blkatoff ufsdirblk
17548 fbt ufs hashalloc entry
17549 fbt ufs hashalloc return
17550 fbt ufs alloccg entry
17551 fbt ufs alloccg return
17552 fbt ufs fragextend entry
17553 fbt ufs fragextend return
...
Здесь выводятся только пробы модуля UFS.
# dtrace -l -f open
ID PROVIDER MODULE FUNCTION NAME
16 syscall open entry
17 syscall open return
9455 fbt genunix open entry
9456 fbt genunix open return
Выводятся только пробы функции open.
# dtrace -l -n start
ID PROVIDER MODULE FUNCTION NAME
495 proc unix mutex_exit_critical_start start
524 io genunix default_physio start
525 io genunix bdev_strategy start
526 io genunix aphysio start
1495 io nfs nfs4_bio start
1496 io nfs nfs3_bio start
1497 io nfs nfs_bio start
Здесь выводятся все пробы c именем start.
Теперь попробуем написать простой D-скрипт. В текстовом редакторе создадим файл hello.d следующего содержания:
BEGIN
{
trace("hello, world");
exit(0);
}
Сохраним и запустим:
# dtrace -s hello.d
dtrace: script 'hello.d' matched 1 probe
CPU ID FUNCTION:NAME
0 1 :BEGIN hello,world!
#
Теперь нет необходимости завершать работу скрипта нажатием Control-C - это результат действий, которые мы прописали для пробы BEGIN. Каждый D-срипт состоит из пунктов, описывающих одну или несколько проб и действий, выполняющихся когда проба включается. Действия прописываются
в фигурных скобках вслед за именем пробы. Каждый пункт заканчивается точкой с запятой. Cначала мы вызываем функцию trace() чтобы Dtrace при включении пробы BEGIN записала и вывела в output специальный аргумент - строку "hello, world". Затем мы используем функцию exit() чтобы Dtrace закончила трассировку и завершила команду dtrace.
DTrace содержит целый ряд полезных функций для вызова в D-программах. Для вызова функции мы пишем ее название и следом список аргументов. Полный список функций представлен в Solaris Dynamic Tracing Guide. Если кто знаком с языком Cи, он может заметить, что D напоминает Cи и awk. Тем не менее, D произошел из сложной комбинации C и специального ряда функций и переменных, созданных для облегчения трассировок.
(По материалам Sun Microsystems)