имя процесса (comm) в качестве ключа для карты BPF - PullRequest
0 голосов
/ 24 апреля 2020

Я пытался разработать инструмент, в котором я мог бы выполнять трассировку для каждого процесса, но это подразумевает, что мне нужен ключ для каждого процесса, чтобы я мог хранить пары сопоставлений ключ-значение для каждого процесса. Я инстинктивно не люблю использовать структуры или строки в качестве ключей, и какое-то время я думал о том, как получить доступ к значениям inode для их использования в качестве ключей. Однако существует множество примеров , которые используют структуры или строки в качестве ключей hashmap, и Алексей предположил, что имена процессов будут , обычно используемыми в качестве ключа . Тем не менее, я не могу заставить базовую c реализацию такой хэш-карты работать. В программе BPF точка трассировки не может найти связанное значение с ключом имя_процесса. Возможно, я сравниваю области памяти, а не строковые литералы, как предполагалось? Что-то происходит под капотом с c_types, что создает несоответствие между клавишами?

from bcc import BPF
from bcc.utils import printb
from bcc.syscall import syscall_name, syscalls
from ctypes import *

b = BPF(text = """

struct procName {
    char name[16];
};

BPF_HASH(attempt, struct procName, u32);

TRACEPOINT_PROBE(raw_syscalls, sys_exit)
{
    u32 *val;
    struct procName hKey;
    bpf_get_current_comm(hKey.name,16);
    val = attempt.lookup(&hKey);

    if (val)
    {
        bpf_trace_printk("Hello world, I have value %d!\\n", *val);
    }

    return 0;
}
""")

class procName(Structure):
    _fields_ = [("name", (c_char_p*16))]

myFirst = procName(('p','y','t','h','o','n','\0'))
trialUpload[myFirst] = c_int(10)

while 1:
    try:
        (task, pid, cpu, flags, ts, msg) = b.trace_fields()
    except KeyboardInterrupt:
        print("Detaching")
        exit()
    print("%-18.9f %-16s %-6d %s" % (ts, task, pid, msg))

1 Ответ

0 голосов
/ 25 апреля 2020

Ошибка в исходном коде не имеет ничего общего с B CC & BPF и лежит в моей реализации ctypes. Для начала -

class procName(Structure):
    _fields_ = [("name", (c_char_p*16))]

создает структуру с полем «имя». В приведенном выше определении name будет иметь тип * char [16], когда я хочу char [16]. Во-вторых, хотя это

myFirst = procName(('p','y','t','h','o','n','\0'))

может сработать, это не лучший способ инициализации. Это правильный подход -

class procName(Structure):
    _fields_ = [("name", (c_char*16))]

s = "python"

mySecond = procName()
mySecond.name = s

Таким образом, полная программа, включающая ключ на основе имя_процесса и его реализация для передачи данных из python, будет ..

from bcc import BPF
from bcc.utils import printb
from bcc.syscall import syscall_name, syscalls
import ctypes
from ctypes import *

b = BPF(text = """

#include <linux/string.h>

struct procName {
    char name[16];
};

BPF_HASH(attempt, struct procName, u32);

TRACEPOINT_PROBE(raw_syscalls, sys_exit)
{
    u32 *myVal;
    struct procName key;
    bpf_get_current_comm(&(key.name),16);

    myVal = attempt.lookup(&key);

    if (myVal)
    {
        bpf_trace_printk("values: %d\\n", *myVal);
    }

    return 0;

}
""")

class procName(Structure):
    _fields_ = [("name", (c_char*16))]

trialUpload = b["attempt"]

s = "python"

mySecond = procName()
mySecond.name = s
trialUpload[mySecond] = c_int(5)

while 1:
    try:
        (task, pid, cpu, flags, ts, msg) = b.trace_fields()
    except KeyboardInterrupt:
        print("Detaching")
        exit()
    print("%-18.9f %-16s %-6d %s" % (ts, task, pid, msg))
...