SystemTap脚本奇怪的行为

时间:2015-01-03 14:37:39

标签: linux system-calls systemtap

我有一个简单的ST脚本,可以计算每个文件的进程大小:

global fds, counts

probe syscall.open.return {
        if ( ( pid() == target() ) & ( $return != -1 ) ) {
                printf("%s opened as %d\n", user_string($filename), $return)
                fds[$return] = user_string($filename)
        }
}

probe syscall.read.return, syscall.write.return {
        if ( (pid() == target()) & ($return > 0) ) {
                counts[fds[$fd]] += $return
        }
}

probe end {
        foreach (fname in counts+) {
                count = counts[fname]
                if ( count > 1024) {
                        count = count / 1024
                        bs = "Kb"
                } else {
                        bs = "B"
                }
                printf("%s: %d %s\n", fname, count, bs)
        }
}

当我运行stap test.stp -c 'cat test.stp'时,我得到:

global fds, counts

probe syscall.open.return {
    if ( ( pid() == target() ) & ( $return != -1 ) ) {
        printf("%s opened as %d\n", user_string($filename), $return)
        fds[$return] = user_string($filename)
    }
}

probe syscall.read.return, syscall.write.return {
    if ( (pid() == target()) & ($return > 0) ) {
        counts[fds[$fd]] += $return
    }
}

probe end {
    foreach (fname in counts+) {
        count = counts[fname]
        if ( count > 1024) {
            count = count / 1024
            bs = "Kb"
        } else {
            bs = "B"
        }
        printf("%s: %d %s\n", fname, count, bs)
    }
}
/etc/ld.so.cache opened as 3
/lib64/libc.so.6 opened as 3
/usr/lib/locale/locale-archive opened as 3
test.stp opened as 3
test.stp: 541 B
: 541 B
/lib64/libc.so.6: 832 B

这几乎是正确的。但是当我执行stap test.stp -c 'cat test.stp > /dev/null'时,我得到了一些奇怪的东西:

/etc/ld.so.cache opened as 3
/lib64/libtinfo.so.5 opened as 3
/lib64/libdl.so.2 opened as 3
/lib64/libc.so.6 opened as 3
/dev/tty opened as 3
/usr/lib/locale/locale-archive opened as 3
/proc/meminfo opened as 3
/usr/lib64/gconv/gconv-modules.cache opened as 3
/lib64/libtinfo.so.5: 832 B
/lib64/libdl.so.2: 832 B
/lib64/libc.so.6: 832 B
/proc/meminfo: 1024 B

为什么我在第二种情况下看不到test.stp opened as 3

我用strace做了一些测试:

1)strace -e open -o trace cat test.stp

open("/home/al/lib/tls/x86_64/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/home/al/lib/tls/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/home/al/lib/x86_64/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/home/al/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
open("test.stp", O_RDONLY)              = 3
+++ exited with 0 +++

2)strace -e open -o trace cat test.stp > /dev/null

open("/home/al/lib/tls/x86_64/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/home/al/lib/tls/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/home/al/lib/x86_64/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/home/al/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
open("test.stp", O_RDONLY)              = 3
+++ exited with 0 +++

没有区别。

1 个答案:

答案 0 :(得分:1)

这是因为cat test.stp > /dev/null需要运行shell(bash)(注意带有>的输出重定向),因此bash进程的PID(而不是cat)将被识别为target()

您可以检查pid()是否为target()的孩子。 DTrace中有一个名为progenyof()的操作,用于确定当前任务是否为具有预定义pid()的任务的子项。 SystemTap中没有类似物,但您可以轻松地重现它:

function progenyof(pid:long) {
    parent = task_parent(task_current());
    task = pid2task(pid);

    while(parent && task_pid(parent) > 0) {
        if(task == parent)
            return 1;

        parent = task_parent(parent);
    }
}