1 BPF ring buffer解决的问题及背后的设计-德赢Vwin官网 网
0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

BPF ring buffer解决的问题及背后的设计

Linux阅码场 来源:Linux阅码场 作者:赵亚楠 2022-05-17 09:37 次阅读

作者简介

赵亚楠,携程资深架构师,负责携程云平台网络虚拟化、云原生安全、内核等基础设施研发工作。

译者序本文翻译自 BPF 核心开发者 Andrii Nakryiko 2020 的一篇文章:BPF ring buffer。

文章介绍了 BPF ring buffer 解决的问题及背后的设计,并给出了一些代码示例和内核 patch 链接,深度和广度兼备,是学习 ring buffer 的极佳参考。

由于译者水平有限,本文不免存在遗漏或错误之处。如有疑问,请查阅原文。

目录

译者序1 ringbuf 相比 perfbuf 的改进 1.1 降低内存开销(memory overhead) 1.2 保证事件顺序(event ordering) 1.3 减少数据复制(wasted data copy)2 ringbuf 使用场景和性能 2.1 常规场景 2.2 高吞吐场景 2.3 不可掩码中断(non-maskable interrupt)场景 2.4 小结3 示例程序(show me the code) 3.1 perfbuf 示例 内核 BPF 程序 用户空间程序 3.2 ringbuf 示例 内核 BPF 程序 用户空间程序 3.3 ringbuf reserve/commit API 示例 原理 限制 内核 BPF 程序 用户空间程序4 ringbuf 事件通知控制 4.1 事件通知开销 4.2 perbuf 解决方式 4.3 ringbuf 解决方式5 总结其他相关资料(译注)

以下是译文。

很多场景下,BPF 程序都需要将数据发送到用户空间(userspace), BPF perf buffer(perfbuf)是目前这一过程的事实标准,但它存在一些问题,例如 浪费内存(因为其 per-CPU 设计)、事件顺序无法保证等。

作为改进,内核 5.8 引入另一个新的 BPF 数据结构:BPF ring buffer(环形缓冲区,ringbuf),

  • 相比 perf buffer,它内存效率更高、保证事件顺序,性能也不输前者;

  • 在使用上,既提供了与 perf buffer 类似的 API ,以方便用户迁移;又提供了一套新的reserve/commit API(先预留再提交),以实现更高性能

此外,实验与真实环境的压测结果都表明,从 BPF 程序发送数据给用户空间时, 应该首选 BPF ring buffer。

1.ringbuf 相比perfbuf的改进

perfbuf 是 per-CPU 环形缓冲区(circular buffers),能实现高效的 “内核-用户空间”数据交互,在实际中也非常有用,但 per-CPU 的设计 导致两个严重缺陷:

  • 内存使用效率低下(inefficient use of memory)

  • 事件顺序无法保证(event re-ordering)

因此内核 5.8 引入了 ringbuf 来解决这个问题。ringbuf 是一个“多生产者、单消费者”(multi-producer, single-consumer,MPSC) 队列,可安全地在多个 CPU 之间共享和操作。perfbuf 支持的一些功能它都支持,包括,

  1. 可变长数据(variable-length data records);

  2. 通过 memory-mapped region 来高效地从 userspace 读数据,避免内存复制或系统调用;

  3. 支持 epoll notifications 和 busy-loop 两种获取数据方式。

此外,它还解决了 perfbuf 的下列问题:

  1. 可变长数据(variable-length data records);

  2. 通过 memory-mapped region 来高效地从 userspace 读数据,避免内存复制或系统调用;

  3. 支持 epoll notifications 和 busy-loop 两种获取数据方式。

下面具体来看。

1.1 降低内存开销(memory overhead)

perfbuf 为每个 CPU 分配一个独立的缓冲区,这意味着开发者通常需要 在内存效率和数据丢失之间做出折中:

  1. 越大的 per-CPU buffer 越能避免丢数据,但也意味着大部分时间里,大部分内存都是浪费的;

  2. 尽量小的 per-CPU buffer 能提高内存使用效率,但在数据量陡增(毛刺)时将导致丢数据。

对于那些大部分时间都比较空闲、周期性来一大波数据的场景, 这个问题尤其突出,很难在两者之间取得一个很好的平衡。

ringbuf 的解决方式是分配一个所有 CPU 共享的大缓冲区,

  • “大缓冲区”意味着能更好地容忍数据量毛刺

  • “共享”则意味着内存使用效率更高

另外,ringbuf 内存效率的扩展性也更好,比如 CPU 数量从 16 增加到 32 时,

  • perfbuf 的总 buffer 会跟着翻倍,因为它是 per-CPU buffer;

  • ringbuf 的总 buffer 不一定需要翻倍,就足以处理扩容之后的数据量。

1.2 保证事件顺序(event ordering)

如果 BPF 应用要跟踪一系列关联事件(correlated events),例如进程的启动和终止、 网络连接的生命周期事件等,那保持事件的顺序就非常关键。perfbuf 在这种场景下有一些问题:如果这些事件发生的间隔非常短(几毫秒)并且分散 在不同 CPU 上,那事件的发送顺序可能就会乱掉 ——这同样是 perbuf 的 per-CPU 特性决定的。

举个真实例子,几年前我写的一个应用需要跟踪进程 fork/exec/exit 事件,收集进程级别(per-process)的资源使用量。BPF 程序将这些事件 写入 perfbuf,但它们到达的顺序经常乱掉。这是因为内核调度器在不同 CPU 上调度进程时, 对于那些存活时间很短的进程,fork(), exec(), and exit() 会在极短的时间内在不同 CPU 上执行。这里的问题很清楚,但要解决这个问题,就需要在应用逻辑中加入大量的判断和处理, 只有亲自做过才知道有多复杂。

但对于 ringbuf 来说,这根本不是问题,因为它是共享的同一个缓冲区。ringbuf 保证 如果事件 A 发生在事件 B 之前,那 A 一定会先于 B 被提交,也会在 B 之前被消费。这个特性显著简化了应用处理逻辑。

1.3 减少数据复制(wasted data copy)

BPF 程序使用 perfbuf 时,必须先初始化一份事件数据,然后将它复制到 perfbuf, 然后才能发送到用户空间。这意味着数据会被复制两次:

  • 第一次:复制到一个局部变量(a local variable)或 per-CPU array (BPF 的栈空间很小,因此较大的变量无法放到栈上,后面有例子)中;

  • 第二次:复制到perfbuf中。

更糟糕的是,如果 perfbuf 已经没有足够空间放数据了,那第一步的复制完全是浪费的。

BPF ringbuf 提供了一个可选的 reservation/submit API 来避免这种问题。

  • 首先申请为数据预留空间reserve the space),

  • 预留成功后,

    • 应用就可以直接将准备发送的数据放到 ringbuf 了,从而节省了 perfbuf 中的第一次复制

    • 将数据提交到用户空间将是一件极其高效、不会失败的操作,也不涉及任何额外的内存复制。

  • 如果因为 buffer 没有空间而预留失败了,那 BPF 程序马上就能知道,从而也不用再 执行 perfbuf 中的第一步复制。

后面会有具体例子。

2 ringbuf 使用场景和性能

2.1 常规场景

对于所有实际场景(尤其是那些基于bcc/libbpf 的默认配置在使用 perfbuf 的场景), ringbuf 的性能都优于 perfbuf 性能。各种不同场景的仿真压测(synthetic benchmarking) 结果见内核 patch。

2.2 高吞吐场景

Per-CPU buffer 特性的 perfbuf 在理论上能支持更高的数据吞吐, 但这只有在每秒百万级事件(millions of events per second)的场景下才会显现。

在编写了一个真实场景的高吞吐应用之后,我们证实了 ringbuf 在作为与 perfbuf 类似的 per-CPU buffer 使用时,仍然可以作为 perfbuf 的一个高性能替代品,尤其是用到手动管理事件通知(manual data availability notification)机制时。

  • BPF side

  • user-space side

2.3 不可掩码中断(non-maskable interrupt)场景

唯一需要注意、最好先试验一下的场景:BPF 程序必须在 NMI (non-maskable interrupt) context 中执行时,例如处理 cpu-cycles 等 perf events 时。

ringbuf 内部使用了一个非常轻量级的 spin-lock,这意味着如果 NMI context 中有竞争,data reservation 可能会失败。因此,在 NMI context 中,如果 CPU 竞争非常严重,可能会 导致丢数据,虽然此时 ringbuf 仍然有可用空间。

2.4 小结

除了 NMI context 之外,在其他所有场景中优先选择 ringbuf 而不是 perfbuf 都是非常明智的。

3 示例程序(show me the code)

完整代码见 bpf-ringbuf-examples project

BPF 程序的功能是 trace 所有进程的 exec() 操作,也就是创建新进程事件。

每次 exec() 事件:收集进程 ID (pid)、进程名字 (comm)、可执行文件路径 (filename),然后发送给用户空间程序;用户空间简单通过 printf() 打印输出。用三种不同方式实现,输出都类似:

$ sudo ./ringbuf-reserve-commit    # or ./ringbuf-output, or ./perfbuf-outputTIME     EVENT PID     COMM             FILENAME1939 EXEC  3232062 sh               /bin/sh1939 EXEC  3232062 timeout          /usr/bin/timeout1939 EXEC  3232063 ipmitool         /usr/bin/ipmitool1939 EXEC  3232065 env              /usr/bin/env1939 EXEC  3232066 env              /usr/bin/env1939 EXEC  3232065 timeout          /bin/timeout1939 EXEC  3232066 timeout          /bin/timeout1939 EXEC  3232067 sh               /bin/sh1939 EXEC  3232068 sh               /bin/sh^C

事件的结构体定义:

#define TASK_COMM_LEN 16#define MAX_FILENAME_LEN 512
// BPF 程序发送给 userspace 的事件struct event {    int pid;    char comm[TASK_COMM_LEN];    char filename[MAX_FILENAME_LEN];};

这里有意让这个结构体的大小超过 512 字节,这样 event 变量就无法 放到 BPF 栈空间(max 512Byte)上,后面会看到 perfbuf 和 ringbuf 程序分别怎么处理。

3.1 perfbuf 示例

内核 BPF 程序

// 声明一个 perfbuf map。几点注意:// 1. 不用特意设置 max_entries,libbpf 会自动将其设置为 CPU 数量;// 2. 这个 map 的 per-CPU buffer 大小是 userspace 设置的,后面会看到struct {  __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); // perf buffer (array)  __uint(key_size, sizeof(int));  __uint(value_size, sizeof(int));} pb SEC(".maps");
// 一个 struct event 变量的大小超过了 512 字节,无法放到 BPF 栈上,// 因此声明一个 size=1 的 per-CPU array 来存放 event 变量struct {  __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);    // per-cpu array  __uint(max_entries, 1);  __type(key, int);  __type(value, struct event);} heap SEC(".maps");
SEC("tp/sched/sched_process_exec")int handle_exec(struct trace_event_raw_sched_process_exec *ctx){  unsigned fname_off = ctx->__data_loc_filename & 0xFFFF;  struct event *e;  int zero = 0;
  e = bpf_map_lookup_elem(&heap, &zero);  if (!e) /* can't happen */    return 0;
  e->pid = bpf_get_current_pid_tgid() >> 32;  bpf_get_current_comm(&e->comm, sizeof(e->comm));  bpf_probe_read_str(&e->filename, sizeof(e->filename), (void *)ctx + fname_off);
  // 发送事件,参数列表   bpf_perf_event_output(ctx, &pb, BPF_F_CURRENT_CPU, e, sizeof(*e));  return 0;}

用户空间程序

完整代码 the user-space side, 基于 BPF skeleton(更多信息见 这里)。

看一个关键点:使用 libbpf user-space perfbuffer_new() API 来创建一个 perf buffer consumer:

  struct perf_buffer *pb = NULL;  struct perf_buffer_opts pb_opts = {};  struct perfbuf_output_bpf *skel;
  /* Set up ring buffer polling */  pb_opts.sample_cb = handle_event;  pb = perf_buffer__new(bpf_map__fd(skel->maps.pb), 8 /* 32KB per CPU */, &pb_opts);

这里设置 per-CPU buffer 为 32KB, 注意其中的 8 表示的是 number of memory pages,每个 page 是 4KB,因此总大小:8 pages x 4096 byte/page = 32KB。

3.2 ringbuf 示例

完整代码:

  • BPF-side code

  • user-space code

内核 BPF 程序

bpf_ringbuf_output()在设计上遵循了bpf_perf_event_output()的语义, 以使应用从 perfbuf 迁移到 ringbuf 时更容易。为了看出二者有多相似,这里展示下 两个示例代码的 diff。

--- src/perfbuf-output.bpf.c  2020-10-25 1822.247019800 -0700+++ src/ringbuf-output.bpf.c  2020-10-25 1814.510630322 -0700@@ -6,12 +6,11 @@
 char LICENSE[] SEC("license") = "Dual BSD/GPL";
-/* BPF perfbuf map */+/* BPF ringbuf map */ struct {-  __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);-  __uint(key_size, sizeof(int));-  __uint(value_size, sizeof(int));-} pb SEC(".maps");+  __uint(type, BPF_MAP_TYPE_RINGBUF);+  __uint(max_entries, 256 * 1024 /* 256 KB */);+} rb SEC(".maps");
 struct {   __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);@@ -35,7 +34,7 @@   bpf_get_current_comm(&e->comm, sizeof(e->comm));   bpf_probe_read_str(&e->filename, sizeof(e->filename), (void *)ctx + fname_off);
-  bpf_perf_event_output(ctx, &pb, BPF_F_CURRENT_CPU, e, sizeof(*e));+  bpf_ringbuf_output(&rb, e, sizeof(*e), 0);   return 0; }

只有两个小改动:

  1. ringbuf map 的大小(max_entries)可以在 BPF 侧指定了,注意这是所有 CPU 共享的大小。

  • 在 userspace 侧来设置(或 override) max_entries 也是可以的,API 是 bpf_map__set_max_entries();

  • max_entries的单位是字节,必须是内核页大小( 几乎永远是 4096)的倍数,也必须是 2 的幂次

  • bpf_perf_event_output()替换成了类似的bpf_ringbuf_output(),后者更简单,不需要 BPF context 参数。

用户空间程序

事件 handler 签名有点变化:

  1. 会返回错误信息(进而终止 consumer 循环)

  2. 参数里面去掉了产生这个事件的 CPU Index

-void handleevent(void *ctx, int cpu, void *data, unsigned int datasz)+int handleevent(void *ctx, void *data, sizet data_sz){const struct event *e = data;struct tm *tm;

如果 CPU index 对你很重要,那你需要自己在 BPF 代码中记录它。

另外,ringbuffer API 不提供丢失数据(lost samples)的回调函数,而 perfbuffer 是支持的。如果需要这个功能,必须自己在 BPF 代码中处理。这样的设计对于一个(所有 CPU)共享的 ring buffer 能最小化锁竞争, 同时也避免了为不需要的功能买单:在实际中,这功能除了能用户在 userspace 打印出有数据丢失之外,其他基本也做不了什么, 而类似的目的在 BPF 中可以更显式和高效地完成。

第二个不同是 ringbuffer_new() API 更加简洁:

  /* Set up ring buffer polling */-  pb_opts.sample_cb = handle_event;-  pb = perf_buffer__new(bpf_map__fd(skel->maps.pb), 8 /* 32KB per CPU */, &pb_opts);-  if (libbpf_get_error(pb)) {+  rb = ring_buffer__new(bpf_map__fd(skel->maps.rb), handle_event, NULL, NULL);+  if (!rb) {     err = -1;-    fprintf(stderr, "Failed to create perf buffer
");+    fprintf(stderr, "Failed to create ring buffer
");     goto cleanup;   }

接下来基本上就是文本替换一下的事情了:perf_buffer__poll()-ring_buffer__poll()

   printf("%-8s %-5s %-7s %-16s %s
",          "TIME", "EVENT", "PID", "COMM", "FILENAME");   while (!exiting) {-    err = perf_buffer__poll(pb, 100 /* timeout, ms */);+    err = ring_buffer__poll(rb, 100 /* timeout, ms */);     /* Ctrl-C will cause -EINTR */     if (err == -EINTR) {       err = 0;       break;     }     if (err < 0) {-      printf("Error polling perf buffer: %d
", err);+      printf("Error polling ring buffer: %d
", err);       break;     }   }

3.3 ringbuf reserve/commit API 示例

bpf_ringbuf_output()API 的目的是确保从 perfbuf 到 ringbuf 迁移时无需对 BPF 代 码做重大改动,但这也意味着它继承了 perfbuf API 的一些缺点:

  1. 额外的内存复制(extra memory copy)

    这意味着需要额外的空间来构建 event 变量,然后将其复制到 buffer。不仅低效, 而且经常需要引入只有一个元素的 per-CPU array,增加了不必要的处理复杂性。

  2. 非常晚的 buffer 空间申请(data reservation)

    如果这一步失败了(例如由于用户空间消费不及时导致 buffer 满了,或者有大量 突发事件导致 buffer 溢出了),那上一步的工作将变得完全无效,浪费内存空间和计算资源。

原理

如果能提前知道事件将在第二步被丢弃,就无需做第一步了, 节省一些内存和计算资源,消费端反而因此而消费地更快一些。但 xxx_output()风格的API 是无法实现这个目的的。这就是为什么引入了新的bpfringbufreserve()/bpfringbufcommit() API。

  • 提前预留空间,或者能立即发现没有可以空间了(返回NULL);

  • 预留成功后,一旦数据写好了,将它发送到 userspace 是一个不会失败的操作。

    也就是说只要bpf_ringbuf_reserve()返回非空,那随后的bpf_ringbuf_commit()就永远会成功,因此它没有返回值。

另外,ring buffer 中预留的空间在被提交之前,用户空间是看不到的, 因此 BPF 程序可以从容地组织自己的 event 数据,不管它有多复杂、需要多少步骤。这种方式也避免了额外的内存复制和临时存储空间(extra memory copying and temporary storage spaces)。

限制

唯一的限制是:BPF 校验器在校验时(at verification time), 必须知道预留数据的大小 (size of the reservation),因此不支持动态大小的事件数据。

  • 对于动态大小的数据,用户只能退回到用bpf_ringbuf_output()方式来提交,忍受额外的数据复制开销;

  • 其他所有情况下,reserve/commit API 都应该是首选。

内核 BPF 程序

  • BPF

  • user-space

--- src/ringbuf-output.bpf.c  2020-10-25 1814.510630322 -0700+++ src/ringbuf-reserve-submit.bpf.c  2020-10-25 1853.409470270 -0700@@ -12,29 +12,21 @@   __uint(max_entries, 256 * 1024 /* 256 KB */); } rb SEC(".maps");
-struct {-  __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);-  __uint(max_entries, 1);-  __type(key, int);-  __type(value, struct event);-} heap SEC(".maps");- SEC("tp/sched/sched_process_exec") int handle_exec(struct trace_event_raw_sched_process_exec *ctx) {   unsigned fname_off = ctx->__data_loc_filename & 0xFFFF;   struct event *e;-  int zero = 0;
-  e = bpf_map_lookup_elem(&heap, &zero);-  if (!e) /* can't happen */+  e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0);+  if (!e)     return 0;
   e->pid = bpf_get_current_pid_tgid() >> 32;   bpf_get_current_comm(&e->comm, sizeof(e->comm));   bpf_probe_read_str(&e->filename, sizeof(e->filename), (void *)ctx + fname_off);
-  bpf_ringbuf_output(&rb, e, sizeof(*e), 0);+  bpf_ringbuf_submit(e, 0);   return 0; }

用户空间程序

用户空间代码与之前的 ringbuf output API 完全一样,因为这个 API 涉及到的只是提交方(生产方), 消费方还是一样的方式来消费。

4 ringbuf 事件通知控制

4.1 事件通知开销

在高吞吐场景中,最大的性能损失经常来自提交数据时,内核的信号通知开销(in-kernel signalling of data availability) ,也就是内核的 poll/epoll 通知阻塞在读数据上的 userspace handler 接收数据。

这一点对 perfbuf 和 ringbuf 都是一样的。

4.2 perbuf 解决方式

perfbuf 处理这种场景的方式是提供了一个采样通知(sampled notification)机制:每 N 个事件才会发送一次通知。用户空间创建 perfbuf 时可以指定这个参数。

这种机制能否解决问题,因具体场景而异。

4.3 ringbuf 解决方式

ringbuf 选了一条不同的路:bpfringbufoutput() 和 bpfringbufcommit() 都支持一个额外的 flags 参数,

  • BPF_RB_NO_WAKEUP:不触发通知

  • BPF_RB_FORCE_WAKEUP:会触发通知

基于这个 flags,用户能实现更加精确的通知控制。例子见 BPF ringbuf benchmark

默认情况下,如果没指定任何 flag,ringbuf 会采用自适应通知 (adaptive notification)机制,根据 userspace 消费者是否有滞后(lagging)来动态 调整通知间隔,尽量确保 userspace 消费者既不用承担额外开销,又不丢失任何数据。这种默认配置在大部分场景下都是有效和安全的,但如果想获得极致性能,那 显式控制数据通知就是有必要的,需要结合具体应用场景和处理逻辑来设计。

5 总结

本文介绍了 BPF ring buffer 解决的问题及其背后的设计。

文中给出的示例代码和内核代码链接,展示了 ringbuf API 的基础和高级用法。希望阅读本文之后,读者能对 ringbuf 有一个很好的理解和把握,能根据自己的具体应用 选择合适的 API 来使用。

其他相关资料(译注)

内核文档,BPF ring buffer

有一些更细节的设计与实现,可作为本文补充。

原文标题:[译] BPF ring buffer:使用场景、核心设计及程序示例

文章出处:【微信公众号:Linux阅码场】欢迎添加关注!文章转载请注明出处。

审核编辑:汤梓红
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表德赢Vwin官网 网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 内存
    +关注

    关注

    8

    文章

    3019

    浏览量

    74000
  • 程序
    +关注

    关注

    117

    文章

    3785

    浏览量

    80999
  • BPF
    BPF
    +关注

    关注

    0

    文章

    25

    浏览量

    4002

原文标题:[译] BPF ring buffer:使用场景、核心设计及程序示例

文章出处:【微信号:LinuxDev,微信公众号:Linux阅码场】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    Ring Buffer 有什么特别?

    首先 - Ring Buffer。我对 Disruptor 的最初印象只有 Ring Buffer。后来我渐渐明白 Ring
    发表于 05-25 00:41

    BPF2怎么修订历史

    我刚从设计器V4.4切换到V5.3,我注意到BPF2过滤器现在是V6.0。我要去哪里修改历史? 以上来自于百度翻译 以下为原文I have just switched from Designer
    发表于 05-17 12:29

    BPF-A580+带通滤波器产品介绍

    `产品名称: 带通滤波器产品型号:BPF-A580+BPF-A580+ 产品特性线性相位,Fc±60 MHz时,典型值高达±6度高拒绝率屏蔽盒水性废水工作温度-40 o C至85 o C储存温度
    发表于 09-24 15:29

    什么是Resilient Packet Ring

    什么是Resilient Packet Ring    英文缩写: Resilient Packet Ring 中文译名: 弹性分组环
    发表于 02-23 09:31 623次阅读

    粉红圈(pink ring),粉红圈(pink ring)是

    粉红圈(pink ring)定义成因/影响/改善 粉红圈(pink ring)的定义 板面在氧化后,生成一绒毛层(氧化铜及氧化亚铜)。在本质
    发表于 03-27 16:27 2636次阅读

    Ring buffer介绍

    首先 - Ring Buffer。我对 Disruptor 的最初印象只有 Ring Buffer。后来我渐渐明白 Ring
    发表于 04-02 14:32 3218次阅读

    保证BPF程序安全的BPF验证器介绍

    1. 前言 我们可以使用BPF对Linux内核进行跟踪,收集我们想要的内核数据,从而对Linux中的程序进行分析和调试。与其它的跟踪技术相比,使用BPF的主要优点是几乎可以访问Linux内核
    的头像 发表于 05-03 11:27 1875次阅读
    保证<b class='flag-5'>BPF</b>程序安全的<b class='flag-5'>BPF</b>验证器介绍

    如何使用BPF对Linux内核进行实时跟踪

    我们可以使用BPF对Linux内核进行跟踪,收集我们想要的内核数据,从而对Linux中的程序进行分析和调试。与其它的跟踪技术相比,使用BPF的主要优点是几乎可以访问Linux内核和应用程序的任何信息,同时,BPF对系统性能影响很
    的头像 发表于 06-30 17:28 2292次阅读
    如何使用<b class='flag-5'>BPF</b>对Linux内核进行实时跟踪

    BPF系统调用与Tracing类型的BPF程序

    既然是提供向内核注入代码的技术,那么安全问题肯定是重中之重。平时防范他人通过漏洞向内核中注入代码,这下子专门开了一个口子不是大开方便之门。所以内核指定了很多的规则来限制BPF代码,确保它的错误不会影响到内核:
    的头像 发表于 03-14 16:42 3509次阅读

    BPF ring buffer解决的问题及其背后的设计

    因此内核 5.8 引入了 ringbuf 来解决这个问题。ringbuf 是一个“多生产者、单消费者”(multi-producer, single-consumer,MPSC) 队列,可安全地在多个 CPU 之间共享和操作。
    的头像 发表于 05-07 11:12 1266次阅读

    Ring Clojure的Web框架

    ./oschina_soft/ring.zip
    发表于 06-13 09:38 1次下载
    <b class='flag-5'>Ring</b> Clojure的Web框架

    BPF编程的环境搭建方法

    本来想写一篇“BPF 深度分析、环境搭建与案例分析”的文章,但是篇幅过长,于是先把BPF编程的环境搭建先放出来。接下来的文章将对BPF深度分析(包括BPF虚拟机、
    的头像 发表于 10-14 17:02 1999次阅读
    <b class='flag-5'>BPF</b>编程的环境搭建方法

    BPF为内核编程提供了一个新的参考模型

    这个新的编程环境混合使用了 C语言扩展以及运行时环境的组合实现的,这个运行时环境包含了 Clang、用户空间的 BPF 加载器库(libbpf)和内核中的 BPF 子系统。
    的头像 发表于 10-19 11:27 1132次阅读

    内核观测技术BPF详解

    BPF简介 BPF,全称是Berkeley Packet Filter(伯克利数据包过滤器)的缩写。其诞生于1992年,最初的目的是提升网络包过滤工具的性能。后面,随着这个工具重新实现BPF的内核
    的头像 发表于 11-10 10:34 1228次阅读

    MSPM0 UART通信中DMA和Ring Buffer环形缓冲的应用

    德赢Vwin官网 网站提供《MSPM0 UART通信中DMA和Ring Buffer环形缓冲的应用.pdf》资料免费下载
    发表于 09-05 11:01 0次下载
    MSPM0 UART通信中DMA和<b class='flag-5'>Ring</b> <b class='flag-5'>Buffer</b>环形缓冲的应用