Категории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, December 14. 2004
DTrace options: flowindent Posted by Gleb Reys
in DTrace at
19:26
Comments (0) Trackbacks (0) Defined tags for this entry: dtrace
DTrace options: flowindent
One of the most useful (for me) options in DTrace is flowindent. All it does is indent the entry to each function with "->", and mark the return from this function with "<-". Doesn't seem like much, does it? But just look at the results!
The following example catches all the probes of the fbt provided. By default (that's our case since we're not changing any other options but flowindent), DTrace registers and prints to the standard output all the probes matched in the tracing process. Here is our script: CODE: #!/usr/sbin/dtrace -s fbt::: /execname == "dtrace"/ { } And this is the output we'll get by running this script: 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 ... But if we only add the flowindent option to our script (you can also achieve the same result by using -F dtrace command line option), the output is going to appear much more readable and easy to follow: Our new script: CODE: #!/usr/sbin/dtrace -s #pragma D option flowindent fbt::: /execname == "dtrace"/ { } And this is the output we'll get: 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, December 10. 2004
DTrace: predicates Posted by Gleb Reys
in DTrace at
19:52
Comments (0) Trackbacks (0) Defined tags for this entry: dtrace
DTrace: predicates
You don't have conditional statements like if..then..else in DTrace, instead of them predicates are used.
Predicates are slash (/) wrapped conditions which are put right after the lines of probe definitions, defining whether DTrace should or should not executre the code of such probes. Here's an example. The following script will print the list of all system calls, excluding write, for all the processes currently running on our system. Since DTrace tracks events on a thread-level, you can see in this example that some PIDs are the same. This is because these lines were printed by probes fired for different threads of the same process: CODE: #!/usr/sbin/dtrace -s #pragma D option quiet syscall::: /probefunc != "write"/ { printf("probefunc: %s, pid: %d, execname: %s\n", probefunc, pid, execname); } When you execute this script, you'll get something similar to this: 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 ... As you can see, our script even took a note of all the dtrace syscalls which was used to run the script. To exclude dtrace from our data, we should alter the predicate to include one more condition: CODE: /probefunc != "write" && execname != "dtrace"/ this will result in our output including all the processes but dtrace. In this example, we can see a couple of my rxvt terminals and 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 ... Predicates allow you to use any constants and variables defined earlier in the code, or standard ones, just like the ones shows in my examples. And if you keep in mind, that local variables are unique on thread-level, you can build up pretty complex constructions. Thread-specific local variables are defined with the help of self indicator and a special -> operator, for instance: self->flag = 1;. My next example will print only one message for each write syscall of every thread. As you can see in the code, every time we note a thread returning from write syscall, we mark this thread with a local variable, so that we know the thread has been processedt: self->processed = 1;. Next time a write probe fires for this thread, the predicate will take care of it and skip the probe code execution if needed: 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; } As it's clearly seen, every thread has been registered only once: 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 It's impossibly to even try to cover all different ways of using DTrace predicates in only one entry, so I think I'll call it a day. Next time I'll show a few more ways of making your life easier. Tuesday, December 7. 2004
Встроенные ... Posted by Gleb Reys
in DTrace at
17:51
Comments (0) Trackbacks (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, December 6. 2004
The official DTrace guide Posted by Gleb Reys
in DTrace at
20:06
Comments (2) Trackbacks (0) Defined tags for this entry: dtrace
The official DTrace guide
This guide has been around for quite some time, but I still wanted to write about it here.
Here is the link: Solaris Dynamic Tracing Guide This guide has lots of very simple and useful examples, so it's a good starting point. All these examples can be found in /usr/demo/dtrace, and if you open /usr/demo/dtrace/index.html in your browser, you'll see all the examples in a table, split by the guide chapters. Wednesday, December 1. 2004
DTrace и настройка ... Posted by Gleb Reys
in DTrace at
16:48
Comments (3) Trackback (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 В этом случае пользователь сможет провести необходимые ему эксперименты, но по выходу из оболочки он эти волшебные свойства утратит до следующего вашего приступа душевной доброты. |





