Категории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 Архивы |
Tuesday, 14 December. 2004
Опции DTrace: flowindent Добавил Gleb Reys
в категории DTrace в
19:26
Комментарии (0) Обратные ссылки (0) Select language: English Defined tags for this entry: dtrace
Опции DTrace: flowindent
Одна из самых полезных для меня возможностей в DTrace - это опция flowindent. Всё, что она делает - это отмечает вход в какую-нибудь функцию с помощью знаков "->", и выход из этой же функции знаками "<-". Казалось бы, что может быть проще - а вы только посмотрите, насколько приятнее выглядит результат!
Данный пример ловит все пробы провайдера fbt. В режиме по умолчанию (а мы будем находиться именно в нём, раз никакими опциями ничего не меняем кроме flowindent) DTrace регистрирует указанные пробы и выводит информацию, когда регистрация этих проб произошла. Код скрипта: CODE: #!/usr/sbin/dtrace -s fbt::: /execname == "dtrace"/ { } И вот какой мы получаем результат: CODE: dtrace: script './try5.d' matched 32659 probes CPU ID FUNCTION:NAME 1 2027 xc_sync:entry 1 819 xc_do_call:entry 1 1210 mutex_vector_enter:entry 1 1238 lock_set_spl:entry 1 2353 splx:entry 1 15484 apic_setspl:entry 1 15485 apic_setspl:return 1 2354 splx:return 1 1239 lock_set_spl:return 1 1211 mutex_vector_enter:return 1 821 xc_common:entry 1 15510 apic_send_ipi:entry 1 15511 apic_send_ipi:return ... Стоит лишь добавить к этому скрипту опцию flowindent (это, кстати, можно также сделать просто добавив -F как параметр командной строки), как ход исполнения кода становится гораздо понятнее: Новый скрипт: CODE: #!/usr/sbin/dtrace -s #pragma D option flowindent fbt::: /execname == "dtrace"/ { } И результат: CODE: dtrace: script './try5.d' matched 32659 probes
CPU FUNCTION 1 -> xc_sync 1 -> xc_do_call 1 -> mutex_vector_enter 1 -> lock_set_spl 1 -> splx 1 -> apic_setspl 1 <- apic_setspl 1 <- splx 1 <- lock_set_spl 1 <- mutex_vector_enter 1 -> xc_common 1 -> apic_send_ipi 1 <- apic_send_ipi ... Friday, 10 December. 2004
Предикаты в DTrace Добавил Gleb Reys
в категории DTrace в
19:52
Комментарии (0) Обратные ссылки (0) Select language: English Defined tags for this entry: dtrace
Предикаты в DTrace
В DTrace нет условных операторных скобок типа if..then..else, вместо них используются предикаты.
Предикат - это заключённые в слэши (/) условия, приводимые сразу после строки объявления той или иной пробы, и предназначенные для контроля за необходимостью выполнения кода, относящегося к этой пробе. Скажем, следующий скрипт выведет список всех системных вызовов, кроме write, для всех процессов, запущенных на системе. Так как DTrace отслеживает события на уровне thread'ов, в примере запуска этого скрипта видно, что некоторые иднентификаторы процессов повторяются. Это потому что пробы сработали для различных thread'ов одного и того же процесса: CODE: #!/usr/sbin/dtrace -s #pragma D option quiet syscall::: /probefunc != "write"/ { printf("probefunc: %s, pid: %d, execname: %s\n", probefunc, pid, execname); } После запуска скрипта вы увидите примерно следующее: CODE: probefunc: ioctl, pid: 28603, execname: dtrace probefunc: ioctl, pid: 28603, execname: dtrace probefunc: ioctl, pid: 28603, execname: dtrace probefunc: ioctl, pid: 28603, execname: dtrace probefunc: ioctl, pid: 28603, execname: dtrace probefunc: sysconfig, pid: 28603, execname: dtrace probefunc: sysconfig, pid: 28603, execname: dtrace probefunc: sysconfig, pid: 28603, execname: dtrace probefunc: sysconfig, pid: 28603, execname: dtrace probefunc: sigaction, pid: 28603, execname: dtrace probefunc: sigaction, pid: 28603, execname: dtrace probefunc: sigaction, pid: 28603, execname: dtrace probefunc: sigaction, pid: 28603, execname: dtrace ... Т.е. скрипт учёл и системные вызовы, выполненные командой dtrace, которая выполняла скрипт. Для того, чтобы исключить эту команду из нашей статистики, следует изменить предикат: CODE: /probefunc != "write" && execname != "dtrace"/ и тогда вывод команды будет включать уже все другие процессы, кроме dtrace, в моём примере это парочка моих терминалов rxvt и java: CODE: probefunc: pollsys, pid: 28411, execname: rxvt probefunc: ioctl, pid: 28411, execname: rxvt probefunc: ioctl, pid: 28411, execname: rxvt probefunc: pollsys, pid: 28411, execname: rxvt probefunc: pollsys, pid: 28406, execname: rxvt probefunc: ioctl, pid: 28406, execname: rxvt probefunc: ioctl, pid: 28406, execname: rxvt probefunc: pollsys, pid: 28406, execname: rxvt probefunc: lwp_cond_wait, pid: 27870, execname: java_vm probefunc: lwp_cond_signal, pid: 27870, execname: java_vm probefunc: lwp_cond_signal, pid: 27870, execname: java_vm probefunc: lwp_cond_wait, pid: 27870, execname: java_vm ... В выражениях предикатов могут использоваться любые константы и переменные, ранее использовавшиеся в коде, или стандартные переменные, как в приведённых примерах. А если учесть, что локальные переменные уникальны для каждого thread'а процесса, то можно строить и конструкции посложнее... Локальные для каждого thread'а переменные объявляются с помощью оператора -> специального идентификатора self, например: self->flag = 1;. Приведённые ниже пример выведет лишь по одному сообщению про системный вызов write каждого из thread'ов всех процессов, выполняющих этот вызов. Как видно из кода, едва мы сообщаем об очередном thread'е, который мы уличили в завершении системного вызова write, мы тут же отмечаем в локальной для этого thread'а переменной, что он уже был обработан: self->processed = 1;. А предикат уже позаботится о том, чтобы в следующий раз для уже отмеченного thread'а мы не выполняли код нашей пробы: CODE: #!/usr/sbin/dtrace -s #pragma D option quiet syscall::write:return / self->processed == 0/ { printf("tid: %d, pid: %d, execname: %s\n", tid, pid, execname); self->processed = 1; } Как видно, каждый thread был зарегистрирован только один раз: CODE: tid: 1, pid: 21583, execname: soffice.bin tid: 4, pid: 21750, execname: thunderbird-bin tid: 4, pid: 27406, execname: mozilla-bin tid: 1, pid: 27406, execname: mozilla-bin tid: 1, pid: 21450, execname: icewm tid: 4, pid: 21583, execname: soffice.bin tid: 1, pid: 21750, execname: thunderbird-bin tid: 1, pid: 28636, execname: dtrace Всех способов использования предикатов не расскажешь в одной записи, так что в следующий раз я постараюсь показать ещё несколько вариантов использования этой замечательной возможности DTrace. Tuesday, 7 December. 2004
Встроенные ... Добавил Gleb Reys
в категории DTrace в
17:51
Комментарии (0) Обратные ссылки (0) Defined tags for this entry: dtrace
Встроенные переменные DTrace
В DTrace есть довольно много очень полезных встроенных переменных.
Полный их список приведён здесь, а пока я расскажу лишь про несколько из них. В этой заметке мы рассмотрим простейшие переменные, а в последующих записях постепенно научимся использовать и более сложные. Позволю себе разбить переменные на несколько групп. Помимо имени переменной, я также приведу её тип. Итак: 1) Имена файлов и каталогов string cwd - имя текущего каталога того процесса, которому принадлежит текущий thread string execname - символьное имя, которое было передано функции exec(2) для исполнения текущего процесса. 2) Процессы id_t tid - номер текущего thread'а. Для thread'ов пользовательских процессов, это значение будет равно результату вызова pthread_self(3C). pid_t pid - идентификатор процесса (PID) текущего процесса pid_t ppid - parent PID текущего процесса uid_t uid - пользовательский ID текущего процесса gid_t gid - идентификатор группы (group ID) текущего процесса 3) Пробы uint_t id - ID номер текущей пробы. Это тот самый номерок, что видно в таблице доступны проб при вызове команды dtrace -l string probefunc - имя функции согласно описанию текущей пробы string probemod - имя модуля согласно описанию текущей пробы string probename - имя пробы согласно описанию текущей пробы string probeprov - имя провайдера согласно описанию текущей пробы 4) Прочее int errno - код ошибки, возвращённый последним системным вызовом, выполненным текущим thread'ом uint64_t timestamp - текущее время счётчика наносекунд. Данный счётчик не привязан к текущему времени в системе, и потому должен использоваться только для относительных вычислений. Использовать эти переменные можно как угодно - один из простейших вариантов применения приведён ниже. Я привожу полный текст скрипта, поэтому если вы его сохраните под именем script.d и сделаете этому файлу chmod u+x ./script.d, то его можно будет запускать прямо из командной строки. Пока не обращайте внимания на строку с pragma D option, про несколько полезных опций DTrace я расскажу через несколько дней. ВНИМАНИЕ: в целях компактного размещения кода, я разбил длинные строки с printf на несколько строк. Если вы хотите запустить данный скрипт, вам следует склеить такие строки. CODE: #!/usr/sbin/dtrace -s #pragma D option quiet :::write:entry { printf("\nProcess info:\ntid=%d, pid=%d, ppid=%d, uid=%d, gid=%d\n", tid, pid, ppid, uid, gid); printf("CWD=%s, execname=%s\n", cwd, execname); printf("Probe info:\nid=%d, probeprov=%s, probemod=%s, probefunc=%s, probename=%s\n", id, probeprov, probemod, probefunc, probename); } Запущенный на вашей машине, данный скрипт выдаст вам примерно следующее (будет ОЧЕНЬ много строк, так как мы ловим, согласно шаблону, все обращения к вызову write): CODE: Process info:
tid=1, pid=22157, ppid=21995, uid=123, gid=10 CWD=/export/greys/./dtrace, execname=dtrace Probe info: id=6295, probeprov=fbt, probemod=genunix, probefunc=write, probename=entry Process info: tid=1, pid=21993, ppid=21450, uid=123, gid=10 CWD=/home/gr128638, execname=rxvt Probe info: id=12, probeprov=syscall, probemod=, probefunc=write, probename=entry Monday, 6 December. 2004
Официальное ... Добавил Gleb Reys
в категории DTrace в
20:06
Комментарии (2) Обратные ссылки (0) Select language: English Defined tags for this entry: dtrace
Официальное руководство по DTrace
Это уже далеко не новость, так как вы все, скорее всего, уже знаете эту ссылку, но тем не менее:
Solaris Dynamic Tracing Guide А вспомнил про эту ссылку я потому, что хотел рассказать о примерах, которые приведены в этом руководстве. Их довольно много, они простые и в то же время очень полезные. Так что на практике могут запросто пригодиться. Все эти примеры находятся в каталоге /usr/demo/dtrace, и открыв в вашем браузере файл /usr/demo/dtrace/index.html, вы сможете увидеть все примеры в таблице, разбирающей их по главам руководства по DTrace. Wednesday, 1 December. 2004
DTrace и настройка ... Добавил Gleb Reys
в категории DTrace в
16:48
Комментарии (3) Обратная ссылка (1) Defined tags for this entry: dtrace
DTrace и настройка привилегий
Одним из нововведений Solaris 10 являются привилегии - механизм, позволяющий легко ограничивать возможности пользователей или процессов в системе.
man privileges содержит список всех доступных привилегий, я же здесь пока затрону лишь те, которые относятся к DTrace. Смысл всего этого вот в чём - DTrace это довольно опасное оружие в умелых руках, и потому простые пользователи Solaris не должны иметь к нему доступ так же, как и они не должны иметь доступа к файлам других пользователей. Поэтому, попытка выполнить команду типа dtrace -l из-под обычного пользователя приведёт к такой вот ошибке: dtrace: failed to initialize dtrace: DTrace requires additional privileges По умолчанию, только root может пользоваться DTrace. Чтобы позволить другим пользователям тоже как-то использовать DTrace, существуют три привилегии, которые им может выдавать администратор: dtrace_proc - даёт пользователю лишь доступ к провайдеру pid. Естественно, доступна будет лишь информация о процессах, принадлежащих этому пользователю. dtrace_user - даёт пользователю доступ к провайдерам profile и syscall, опять же в рамках процессов, принадлежащих этому пользователю. dtrace_kernel - даёт доступ ко всем провайдерам, кроме pid, если он не позволен привилегией dtrace_proc. Губительные для ядра (kernel-destructive) функции недоступны. Вот эти три функции считаются kernel-destructive: breakpoint() - выбросит систему в отладчик ядра. На Sparc-системах вы окажетесь в ok приглашении OBP, а на x86 системах можете оказаться в kadb panic() - вызовет панику ядра (смешно переводить слова, которые никогда по-русски не говорятся) в целях получения крэш-дампа chill() - глобальный sleep, если хотите. Заставляет DTrace ждать указанное количество наносекунд. Естественно, это отразится на всей системе. Так вот, обычному пользователю, какие бы вы ему привилегии не давали, доступа к этим трём функциям нет. Вкратце, привилегии выдаются так: Нужно добавить в файлик /etc/user_attr строку с указанием привилегий для конкретного пользователя. Скажем, если имя пользователя - greys, то вот эта строчка даст ему возможность творить с помощью DTrace всё, что только можно позволить с помощью привилегий простому пользователю: greys::::defaultpriv=basic,dtrace_proc,dtrace_user,dtrace_kernel ну, или если не хочется пользователю надолго давать такие привилегии, можно осчастливить лишь процесс его командной оболочки командой: ppriv -s A+dtrace_user PID В этом случае пользователь сможет провести необходимые ему эксперименты, но по выходу из оболочки он эти волшебные свойства утратит до следующего вашего приступа душевной доброты. |




