进程名称(comm)作为 BPF 映射的键

Posted

技术标签:

【中文标题】进程名称(comm)作为 BPF 映射的键【英文标题】:process name (comm) as key for BPF map 【发布时间】:2020-08-08 11:13:27 【问题描述】:

我一直在尝试设计一个工具,我可以在其中进行每个进程的跟踪,但这意味着我需要为每个进程提供一个键,以便我可以为每个进程存储键值映射配对。我本能地不喜欢使用结构或字符串作为键,有一段时间我在考虑如何访问 inode 值以将它们用作键。然而,有许多 examples 使用结构或字符串作为 hashmap 键,Alexei 建议进程名称将是 commonly used as a key。也就是说,我无法让这种哈希图的基本实现工作。在 BPF 程序中,跟踪点无法找到与 process_name 键相关的值。也许我正在比较内存位置而不是预期的字符串文字? 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))

【问题讨论】:

你运行的是什么内核版本?这可能是您链接到的补丁修复的问题。 5.7.0-rc1 -- 发布补丁 经过进一步调查,这似乎是我如何实现 python 的 ctypes 的问题。我会尝试深入了解并发布解决方案 @pchaigno 感谢您在过去几周的帮助!我完成了我的第一次迭代,并组建了一个非常酷的 HIDS 项目。 【参考方案1】:

原始代码中的错误与 BCC 和 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

因此,包含基于 process_name 的键和实现从 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))

【讨论】:

以上是关于进程名称(comm)作为 BPF 映射的键的主要内容,如果未能解决你的问题,请参考以下文章

Linux / Bash,使用ps -o按特定名称获取进程?

MPI C 将矩阵逐行发送到所有进程子进程 (MPI_COMM_SPAWN)

vs2019运行mpi如何改变进程数, 运行结果总是一个进程,进程号为0; 如何改变VS2019进程数? return 0;

Linux 内核进程管理 task_struct 结构体 ④ ( comm 字段 | 进程优先级字段 | cpus_ptr 字段 | mmactive_mm 字段 | fs 字段 )

MPI_Type_commit 是不是隐式调用 MPI_COMM_WORLD 中所有进程的屏障?

查看进程运行时间