Почему аргумент чтения системного вызова равен нулю?

dtrace

dtrace -n 'syscall::read:entry { @[fds[arg0].fi_fs] = count(); }'

Я хочу найти аргумент read fds

trace -lvn 'syscall::*read*:entry'


 933    syscall                                       read_nocancel entry

    Probe Description Attributes
        Identifier Names: Private
        Data Semantics:   Private
        Dependency Class: ISA

    Argument Attributes
        Identifier Names: Private
        Data Semantics:   Private
        Dependency Class: ISA

    Argument Types
        None

  963    syscall                                      readv_nocancel entry

    Probe Description Attributes
        Identifier Names: Private
        Data Semantics:   Private
        Dependency Class: ISA

    Argument Attributes
        Identifier Names: Private
        Data Semantics:   Private
        Dependency Class: ISA

    Argument Types
        None

  969    syscall                                      pread_nocancel entry

    Probe Description Attributes
        Identifier Names: Private
        Data Semantics:   Private
        Dependency Class: ISA

    Argument Attributes
        Identifier Names: Private
        Data Semantics:   Private
        Dependency Class: ISA

    Argument Types
         None

Но аргумент отсутствует. Как найти аргументы?


person fuyou001    schedule 01.01.2014    source источник


Ответы (2)


Вы путаете значение аргумента с типом аргумента.

Значение аргумента зависит от поставщика. Если вы хотите узнать о syscall::: зондах, вам необходимо обратиться к документации по поставщик системных вызовов, в котором говорится

Аргументы

Для зондов входа аргументы (arg0 .. argn) являются аргументами системного вызова. Для обратных зондов как arg0, так и arg1 содержат возвращаемое значение. Ненулевое значение в переменной D errno указывает на сбой системного вызова.

Поэтому в пункте

syscall::read:entry
{
    ...
}

, что соответствует

ssize_t read(int fildes, void *buf, size_t nbyte);

, arg0 будет значением fildes, arg1 будет значением buf, а arg2 будет значением nbyte.

Тип arg0, arg1, arg2 и т. д. всегда является int64_t независимо от типов аргументов, которые они представляют. Этого достаточно для скалярных величин, но для структуры dtrace(1) должен понимать типы. Можно использовать аргументы, например.

((struct mystruct *)(arg0))->my_member

но это раздражает. Иногда, но не всегда, DTrace знает типы самих аргументов и позволяет описывать их с помощью нотации args[0], args[1] и т. д.; таким образом, при определенных обстоятельствах я мог бы вместо этого написать гораздо более удобный

args[0]->my_member

Для поставщика системных вызовов DTrace не знает типы аргументов, поэтому вы видите

# dtrace -lv -n syscall::read:entry
    ...
    Argument Types
        None

#

и почему

dtrace -n 'syscall::read:entry {trace(args[0])}'

не действует.

Однако для поставщика ввода-вывода DTrace действительно знает типы аргументов, например.

# dtrace -lv -n io:::start
    ... 
    Argument Types
        args[0]: bufinfo_t *
        args[1]: devinfo_t *
        args[2]: fileinfo_t *

#

Прочитав документацию по провайдеру ввода-вывода, можно см., что определение bufinfo_t включает

typedef struct bufinfo {
    ...
    size_t b_bcount;                /* number of bytes */
    ...
} bufinfo_t;

и это позволяет писать, например.

dtrace -n 'io:::start {trace(args[0]->b_bcount)}'.

Наконец, вы упоминаете fds[]. Как я объяснял ранее, тип fds[n] равен fileinfo_t *.

Я рекомендую вам следовать этому введению.

person Robert Harris    schedule 02.01.2014

Как насчет man 2 read? В Mac OS я получаю это:

READ(2)                     BSD System Calls Manual                    READ(2)

NAME
     pread, read, readv -- read input

LIBRARY
     Standard C Library (libc, -lc)

SYNOPSIS
     #include <sys/types.h>
     #include <sys/uio.h>
     #include <unistd.h>

     ssize_t
     pread(int d, void *buf, size_t nbyte, off_t offset);

     ssize_t
     read(int fildes, void *buf, size_t nbyte);

     ssize_t
     readv(int d, const struct iovec *iov, int iovcnt);
...

Однако это, очевидно, будет работать только для поставщика syscall.

person Dan    schedule 02.01.2014
comment
Я не вижу. Не могли бы вы рассказать подробнее? - person fuyou001; 02.01.2014
comment
Зонды, соответствующие syscall:::entry (в вашем случае syscall::read:entry), отмечают точки входа в системные вызовы. Страницы man предоставляют список аргументов, которые предоставляются каждому системному вызову. Как вы можете видеть выше, аргументами для read() являются int (дескриптор файла для чтения), void * (буфер для чтения данных) и size_t (целое число байтов без знака, которое мы хотим прочитать). Однако это будет работать только для системных вызовов, а не для произвольных тестов DTrace, поскольку man обычно не предоставляет документацию для внутренних компонентов ядра и т. д. - person Dan; 03.01.2014