一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

BPF ring buffer解決的問題及背后的設(shè)計

Linux閱碼場 ? 來源:Linux閱碼場 ? 作者:趙亞楠 ? 2022-05-17 09:37 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

作者簡介

趙亞楠,攜程資深架構(gòu)師,負責(zé)攜程云平臺網(wǎng)絡(luò)虛擬化、云原生安全、內(nèi)核等基礎(chǔ)設(shè)施研發(fā)工作。

譯者序本文翻譯自 BPF 核心開發(fā)者 Andrii Nakryiko 2020 的一篇文章:BPF ring buffer。

文章介紹了 BPF ring buffer 解決的問題及背后的設(shè)計,并給出了一些代碼示例和內(nèi)核 patch 鏈接,深度和廣度兼?zhèn)?,是學(xué)習(xí) ring buffer 的極佳參考。

由于譯者水平有限,本文不免存在遺漏或錯誤之處。如有疑問,請查閱原文。

目錄

譯者序1 ringbuf 相比 perfbuf 的改進 1.1 降低內(nèi)存開銷(memory overhead) 1.2 保證事件順序(event ordering) 1.3 減少數(shù)據(jù)復(fù)制(wasted data copy)2 ringbuf 使用場景和性能 2.1 常規(guī)場景 2.2 高吞吐場景 2.3 不可掩碼中斷(non-maskable interrupt)場景 2.4 小結(jié)3 示例程序(show me the code) 3.1 perfbuf 示例 內(nèi)核 BPF 程序 用戶空間程序 3.2 ringbuf 示例 內(nèi)核 BPF 程序 用戶空間程序 3.3 ringbuf reserve/commit API 示例 原理 限制 內(nèi)核 BPF 程序 用戶空間程序4 ringbuf 事件通知控制 4.1 事件通知開銷 4.2 perbuf 解決方式 4.3 ringbuf 解決方式5 總結(jié)其他相關(guān)資料(譯注)

以下是譯文。

很多場景下,BPF 程序都需要將數(shù)據(jù)發(fā)送到用戶空間(userspace), BPF perf buffer(perfbuf)是目前這一過程的事實標準,但它存在一些問題,例如 浪費內(nèi)存(因為其 per-CPU 設(shè)計)、事件順序無法保證等。

作為改進,內(nèi)核 5.8 引入另一個新的 BPF 數(shù)據(jù)結(jié)構(gòu):BPF ring buffer(環(huán)形緩沖區(qū),ringbuf),

  • 相比 perf buffer,它內(nèi)存效率更高、保證事件順序,性能也不輸前者;

  • 在使用上,既提供了與 perf buffer 類似的 API ,以方便用戶遷移;又提供了一套新的reserve/commit API(先預(yù)留再提交),以實現(xiàn)更高性能。

此外,實驗與真實環(huán)境的壓測結(jié)果都表明,從 BPF 程序發(fā)送數(shù)據(jù)給用戶空間時, 應(yīng)該首選 BPF ring buffer。

1.ringbuf 相比perfbuf的改進

perfbuf 是 per-CPU 環(huán)形緩沖區(qū)(circular buffers),能實現(xiàn)高效的 “內(nèi)核-用戶空間”數(shù)據(jù)交互,在實際中也非常有用,但 per-CPU 的設(shè)計 導(dǎo)致兩個嚴重缺陷:

  • 內(nèi)存使用效率低下(inefficient use of memory)

  • 事件順序無法保證(event re-ordering)

因此內(nèi)核 5.8 引入了 ringbuf 來解決這個問題。ringbuf 是一個“多生產(chǎn)者、單消費者”(multi-producer, single-consumer,MPSC) 隊列,可安全地在多個 CPU 之間共享和操作。perfbuf 支持的一些功能它都支持,包括,

  1. 可變長數(shù)據(jù)(variable-length data records);

  2. 通過 memory-mapped region 來高效地從 userspace 讀數(shù)據(jù),避免內(nèi)存復(fù)制或系統(tǒng)調(diào)用;

  3. 支持 epoll notifications 和 busy-loop 兩種獲取數(shù)據(jù)方式。

此外,它還解決了 perfbuf 的下列問題:

  1. 可變長數(shù)據(jù)(variable-length data records);

  2. 通過 memory-mapped region 來高效地從 userspace 讀數(shù)據(jù),避免內(nèi)存復(fù)制或系統(tǒng)調(diào)用;

  3. 支持 epoll notifications 和 busy-loop 兩種獲取數(shù)據(jù)方式。

下面具體來看。

1.1 降低內(nèi)存開銷(memory overhead)

perfbuf 為每個 CPU 分配一個獨立的緩沖區(qū),這意味著開發(fā)者通常需要 在內(nèi)存效率和數(shù)據(jù)丟失之間做出折中:

  1. 越大的 per-CPU buffer 越能避免丟數(shù)據(jù),但也意味著大部分時間里,大部分內(nèi)存都是浪費的;

  2. 盡量小的 per-CPU buffer 能提高內(nèi)存使用效率,但在數(shù)據(jù)量陡增(毛刺)時將導(dǎo)致丟數(shù)據(jù)。

對于那些大部分時間都比較空閑、周期性來一大波數(shù)據(jù)的場景, 這個問題尤其突出,很難在兩者之間取得一個很好的平衡。

ringbuf 的解決方式是分配一個所有 CPU 共享的大緩沖區(qū),

  • “大緩沖區(qū)”意味著能更好地容忍數(shù)據(jù)量毛刺

  • “共享”則意味著內(nèi)存使用效率更高

另外,ringbuf 內(nèi)存效率的擴展性也更好,比如 CPU 數(shù)量從 16 增加到 32 時,

  • perfbuf 的總 buffer 會跟著翻倍,因為它是 per-CPU buffer;

  • ringbuf 的總 buffer 不一定需要翻倍,就足以處理擴容之后的數(shù)據(jù)量。

1.2 保證事件順序(event ordering)

如果 BPF 應(yīng)用要跟蹤一系列關(guān)聯(lián)事件(correlated events),例如進程的啟動和終止、 網(wǎng)絡(luò)連接的生命周期事件等,那保持事件的順序就非常關(guān)鍵。perfbuf 在這種場景下有一些問題:如果這些事件發(fā)生的間隔非常短(幾毫秒)并且分散 在不同 CPU 上,那事件的發(fā)送順序可能就會亂掉 ——這同樣是 perbuf 的 per-CPU 特性決定的。

舉個真實例子,幾年前我寫的一個應(yīng)用需要跟蹤進程 fork/exec/exit 事件,收集進程級別(per-process)的資源使用量。BPF 程序?qū)⑦@些事件 寫入 perfbuf,但它們到達的順序經(jīng)常亂掉。這是因為內(nèi)核調(diào)度器在不同 CPU 上調(diào)度進程時, 對于那些存活時間很短的進程,fork(), exec(), and exit() 會在極短的時間內(nèi)在不同 CPU 上執(zhí)行。這里的問題很清楚,但要解決這個問題,就需要在應(yīng)用邏輯中加入大量的判斷和處理, 只有親自做過才知道有多復(fù)雜。

但對于 ringbuf 來說,這根本不是問題,因為它是共享的同一個緩沖區(qū)。ringbuf 保證 如果事件 A 發(fā)生在事件 B 之前,那 A 一定會先于 B 被提交,也會在 B 之前被消費。這個特性顯著簡化了應(yīng)用處理邏輯。

1.3 減少數(shù)據(jù)復(fù)制(wasted data copy)

BPF 程序使用 perfbuf 時,必須先初始化一份事件數(shù)據(jù),然后將它復(fù)制到 perfbuf, 然后才能發(fā)送到用戶空間。這意味著數(shù)據(jù)會被復(fù)制兩次:

  • 第一次:復(fù)制到一個局部變量(a local variable)或 per-CPU array (BPF 的棧空間很小,因此較大的變量無法放到棧上,后面有例子)中;

  • 第二次:復(fù)制到perfbuf中。

更糟糕的是,如果 perfbuf 已經(jīng)沒有足夠空間放數(shù)據(jù)了,那第一步的復(fù)制完全是浪費的。

BPF ringbuf 提供了一個可選的 reservation/submit API 來避免這種問題。

  • 首先申請為數(shù)據(jù)預(yù)留空間reserve the space),

  • 預(yù)留成功后,

    • 應(yīng)用就可以直接將準備發(fā)送的數(shù)據(jù)放到 ringbuf 了,從而節(jié)省了 perfbuf 中的第一次復(fù)制,

    • 將數(shù)據(jù)提交到用戶空間將是一件極其高效、不會失敗的操作,也不涉及任何額外的內(nèi)存復(fù)制。

  • 如果因為 buffer 沒有空間而預(yù)留失敗了,那 BPF 程序馬上就能知道,從而也不用再 執(zhí)行 perfbuf 中的第一步復(fù)制。

后面會有具體例子。

2 ringbuf 使用場景和性能

2.1 常規(guī)場景

對于所有實際場景(尤其是那些基于bcc/libbpf 的默認配置在使用 perfbuf 的場景), ringbuf 的性能都優(yōu)于 perfbuf 性能。各種不同場景的仿真壓測(synthetic benchmarking) 結(jié)果見內(nèi)核 patch。

2.2 高吞吐場景

Per-CPU buffer 特性的 perfbuf 在理論上能支持更高的數(shù)據(jù)吞吐, 但這只有在每秒百萬級事件(millions of events per second)的場景下才會顯現(xiàn)。

在編寫了一個真實場景的高吞吐應(yīng)用之后,我們證實了 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 中執(zhí)行時,例如處理 cpu-cycles 等 perf events 時。

ringbuf 內(nèi)部使用了一個非常輕量級的 spin-lock,這意味著如果 NMI context 中有競爭,data reservation 可能會失敗。因此,在 NMI context 中,如果 CPU 競爭非常嚴重,可能會 導(dǎo)致丟數(shù)據(jù),雖然此時 ringbuf 仍然有可用空間。

2.4 小結(jié)

除了 NMI context 之外,在其他所有場景中優(yōu)先選擇 ringbuf 而不是 perfbuf 都是非常明智的。

3 示例程序(show me the code)

完整代碼見 bpf-ringbuf-examples project。

BPF 程序的功能是 trace 所有進程的 exec() 操作,也就是創(chuàng)建新進程事件。

每次 exec() 事件:收集進程 ID (pid)、進程名字 (comm)、可執(zhí)行文件路徑 (filename),然后發(fā)送給用戶空間程序;用戶空間簡單通過 printf() 打印輸出。用三種不同方式實現(xiàn),輸出都類似:

$ 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

事件的結(jié)構(gòu)體定義:

#define TASK_COMM_LEN 16#define MAX_FILENAME_LEN 512
// BPF 程序發(fā)送給 userspace 的事件struct event {    int pid;    char comm[TASK_COMM_LEN];    char filename[MAX_FILENAME_LEN];};

這里有意讓這個結(jié)構(gòu)體的大小超過 512 字節(jié),這樣 event 變量就無法 放到 BPF 棧空間(max 512Byte)上,后面會看到 perfbuf 和 ringbuf 程序分別怎么處理。

3.1 perfbuf 示例

內(nèi)核 BPF 程序

// 聲明一個 perfbuf map。幾點注意:// 1. 不用特意設(shè)置 max_entries,libbpf 會自動將其設(shè)置為 CPU 數(shù)量;// 2. 這個 map 的 per-CPU buffer 大小是 userspace 設(shè)置的,后面會看到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 字節(jié),無法放到 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);
  // 發(fā)送事件,參數(shù)列表   bpf_perf_event_output(ctx, &pb, BPF_F_CURRENT_CPU, e, sizeof(*e));  return 0;}

用戶空間程序

完整代碼 the user-space side, 基于 BPF skeleton(更多信息見 這里)。

看一個關(guān)鍵點:使用 libbpf user-space perfbuffer_new() API 來創(chuàng)建一個 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);

這里設(shè)置 per-CPU buffer 為 32KB, 注意其中的 8 表示的是 number of memory pages,每個 page 是 4KB,因此總大?。? pages x 4096 byte/page = 32KB。

3.2 ringbuf 示例

完整代碼:

  • BPF-side code

  • user-space code

內(nèi)核 BPF 程序

bpf_ringbuf_output()在設(shè)計上遵循了bpf_perf_event_output()的語義, 以使應(yīng)用從 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 的大?。╩ax_entries)可以在 BPF 側(cè)指定了,注意這是所有 CPU 共享的大小。

  • 在 userspace 側(cè)來設(shè)置(或 override) max_entries 也是可以的,API 是 bpf_map__set_max_entries();

  • max_entries的單位是字節(jié),必須是內(nèi)核頁大小( 幾乎永遠是 4096)的倍數(shù),也必須是 2 的冪次。

  • bpf_perf_event_output()替換成了類似的bpf_ringbuf_output(),后者更簡單,不需要 BPF context 參數(shù)。

用戶空間程序

事件 handler 簽名有點變化:

  1. 會返回錯誤信息(進而終止 consumer 循環(huán))

  2. 參數(shù)里面去掉了產(chǎn)生這個事件的 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 不提供丟失數(shù)據(jù)(lost samples)的回調(diào)函數(shù),而 perfbuffer 是支持的。如果需要這個功能,必須自己在 BPF 代碼中處理。這樣的設(shè)計對于一個(所有 CPU)共享的 ring buffer 能最小化鎖競爭, 同時也避免了為不需要的功能買單:在實際中,這功能除了能用戶在 userspace 打印出有數(shù)據(jù)丟失之外,其他基本也做不了什么, 而類似的目的在 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. 額外的內(nèi)存復(fù)制(extra memory copy)

    這意味著需要額外的空間來構(gòu)建 event 變量,然后將其復(fù)制到 buffer。不僅低效, 而且經(jīng)常需要引入只有一個元素的 per-CPU array,增加了不必要的處理復(fù)雜性。

  2. 非常晚的 buffer 空間申請(data reservation)

    如果這一步失敗了(例如由于用戶空間消費不及時導(dǎo)致 buffer 滿了,或者有大量 突發(fā)事件導(dǎo)致 buffer 溢出了),那上一步的工作將變得完全無效,浪費內(nèi)存空間和計算資源。

原理

如果能提前知道事件將在第二步被丟棄,就無需做第一步了, 節(jié)省一些內(nèi)存和計算資源,消費端反而因此而消費地更快一些。但 xxx_output()風(fēng)格的API 是無法實現(xiàn)這個目的的。這就是為什么引入了新的bpfringbufreserve()/bpfringbufcommit() API。

  • 提前預(yù)留空間,或者能立即發(fā)現(xiàn)沒有可以空間了(返回NULL);

  • 預(yù)留成功后,一旦數(shù)據(jù)寫好了,將它發(fā)送到 userspace 是一個不會失敗的操作。

    也就是說只要bpf_ringbuf_reserve()返回非空,那隨后的bpf_ringbuf_commit()就永遠會成功,因此它沒有返回值。

另外,ring buffer 中預(yù)留的空間在被提交之前,用戶空間是看不到的, 因此 BPF 程序可以從容地組織自己的 event 數(shù)據(jù),不管它有多復(fù)雜、需要多少步驟。這種方式也避免了額外的內(nèi)存復(fù)制和臨時存儲空間(extra memory copying and temporary storage spaces)。

限制

唯一的限制是:BPF 校驗器在校驗時(at verification time), 必須知道預(yù)留數(shù)據(jù)的大小 (size of the reservation),因此不支持動態(tài)大小的事件數(shù)據(jù)。

  • 對于動態(tài)大小的數(shù)據(jù),用戶只能退回到用bpf_ringbuf_output()方式來提交,忍受額外的數(shù)據(jù)復(fù)制開銷;

  • 其他所有情況下,reserve/commit API 都應(yīng)該是首選。

內(nèi)核 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 涉及到的只是提交方(生產(chǎn)方), 消費方還是一樣的方式來消費。

4 ringbuf 事件通知控制

4.1 事件通知開銷

在高吞吐場景中,最大的性能損失經(jīng)常來自提交數(shù)據(jù)時,內(nèi)核的信號通知開銷(in-kernel signalling of data availability) ,也就是內(nèi)核的 poll/epoll 通知阻塞在讀數(shù)據(jù)上的 userspace handler 接收數(shù)據(jù)。

這一點對 perfbuf 和 ringbuf 都是一樣的。

4.2 perbuf 解決方式

perfbuf 處理這種場景的方式是提供了一個采樣通知(sampled notification)機制:每 N 個事件才會發(fā)送一次通知。用戶空間創(chuàng)建 perfbuf 時可以指定這個參數(shù)。

這種機制能否解決問題,因具體場景而異。

4.3 ringbuf 解決方式

ringbuf 選了一條不同的路:bpfringbufoutput() 和 bpfringbufcommit() 都支持一個額外的 flags 參數(shù),

  • BPF_RB_NO_WAKEUP:不觸發(fā)通知

  • BPF_RB_FORCE_WAKEUP:會觸發(fā)通知

基于這個 flags,用戶能實現(xiàn)更加精確的通知控制。例子見 BPF ringbuf benchmark。

默認情況下,如果沒指定任何 flag,ringbuf 會采用自適應(yīng)通知 (adaptive notification)機制,根據(jù) userspace 消費者是否有滯后(lagging)來動態(tài) 調(diào)整通知間隔,盡量確保 userspace 消費者既不用承擔(dān)額外開銷,又不丟失任何數(shù)據(jù)。這種默認配置在大部分場景下都是有效和安全的,但如果想獲得極致性能,那 顯式控制數(shù)據(jù)通知就是有必要的,需要結(jié)合具體應(yīng)用場景和處理邏輯來設(shè)計。

5 總結(jié)

本文介紹了 BPF ring buffer 解決的問題及其背后的設(shè)計。

文中給出的示例代碼和內(nèi)核代碼鏈接,展示了 ringbuf API 的基礎(chǔ)和高級用法。希望閱讀本文之后,讀者能對 ringbuf 有一個很好的理解和把握,能根據(jù)自己的具體應(yīng)用 選擇合適的 API 來使用。

其他相關(guān)資料(譯注)

內(nèi)核文檔,BPF ring buffer

有一些更細節(jié)的設(shè)計與實現(xiàn),可作為本文補充。

原文標題:[譯] BPF ring buffer:使用場景、核心設(shè)計及程序示例

文章出處:【微信公眾號:Linux閱碼場】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

審核編輯:湯梓紅
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 內(nèi)存
    +關(guān)注

    關(guān)注

    8

    文章

    3125

    瀏覽量

    75274
  • 程序
    +關(guān)注

    關(guān)注

    117

    文章

    3826

    瀏覽量

    83000
  • BPF
    BPF
    +關(guān)注

    關(guān)注

    0

    文章

    26

    瀏覽量

    4347

原文標題:[譯] BPF ring buffer:使用場景、核心設(shè)計及程序示例

文章出處:【微信號:LinuxDev,微信公眾號:Linux閱碼場】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點推薦

    Ring Buffer 有什么特別?

    首先 - Ring Buffer。我對 Disruptor 的最初印象只有 Ring Buffer。后來我漸漸明白 Ring
    發(fā)表于 05-25 00:41

    BPF2怎么修訂歷史

    我剛從設(shè)計器V4.4切換到V5.3,我注意到BPF2過濾器現(xiàn)在是V6.0。我要去哪里修改歷史? 以上來自于百度翻譯 以下為原文I have just switched from Designer
    發(fā)表于 05-17 12:29

    BPF-A580+帶通濾波器產(chǎn)品介紹

    `產(chǎn)品名稱: 帶通濾波器產(chǎn)品型號:BPF-A580+BPF-A580+ 產(chǎn)品特性線性相位,F(xiàn)c±60 MHz時,典型值高達±6度高拒絕率屏蔽盒水性廢水工作溫度-40 o C至85 o C儲存溫度
    發(fā)表于 09-24 15:29

    什么是Resilient Packet Ring

    什么是Resilient Packet Ring    英文縮寫: Resilient Packet Ring 中文譯名: 彈性分組環(huán)
    發(fā)表于 02-23 09:31 ?679次閱讀

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

    粉紅圈(pink ring)定義成因/影響/改善 粉紅圈(pink ring)的定義 板面在氧化后,生成一絨毛層(氧化銅及氧化亞銅)。在本質(zhì)
    發(fā)表于 03-27 16:27 ?2803次閱讀

    Ring buffer介紹

    首先 - Ring Buffer。我對 Disruptor 的最初印象只有 Ring Buffer。后來我漸漸明白 Ring
    發(fā)表于 04-02 14:32 ?3426次閱讀

    保證BPF程序安全的BPF驗證器介紹

    1. 前言 我們可以使用BPF對Linux內(nèi)核進行跟蹤,收集我們想要的內(nèi)核數(shù)據(jù),從而對Linux中的程序進行分析和調(diào)試。與其它的跟蹤技術(shù)相比,使用BPF的主要優(yōu)點是幾乎可以訪問Linux內(nèi)核
    的頭像 發(fā)表于 05-03 11:27 ?2171次閱讀
    保證<b class='flag-5'>BPF</b>程序安全的<b class='flag-5'>BPF</b>驗證器介紹

    如何使用BPF對Linux內(nèi)核進行實時跟蹤

    我們可以使用BPF對Linux內(nèi)核進行跟蹤,收集我們想要的內(nèi)核數(shù)據(jù),從而對Linux中的程序進行分析和調(diào)試。與其它的跟蹤技術(shù)相比,使用BPF的主要優(yōu)點是幾乎可以訪問Linux內(nèi)核和應(yīng)用程序的任何信息,同時,BPF對系統(tǒng)性能影響很
    的頭像 發(fā)表于 06-30 17:28 ?2642次閱讀
    如何使用<b class='flag-5'>BPF</b>對Linux內(nèi)核進行實時跟蹤

    BPF系統(tǒng)調(diào)用與Tracing類型的BPF程序

    既然是提供向內(nèi)核注入代碼的技術(shù),那么安全問題肯定是重中之重。平時防范他人通過漏洞向內(nèi)核中注入代碼,這下子專門開了一個口子不是大開方便之門。所以內(nèi)核指定了很多的規(guī)則來限制BPF代碼,確保它的錯誤不會影響到內(nèi)核:
    的頭像 發(fā)表于 03-14 16:42 ?4118次閱讀

    BPF ring buffer解決的問題及其背后的設(shè)計

    因此內(nèi)核 5.8 引入了 ringbuf 來解決這個問題。ringbuf 是一個“多生產(chǎn)者、單消費者”(multi-producer, single-consumer,MPSC) 隊列,可安全地在多個 CPU 之間共享和操作。
    的頭像 發(fā)表于 05-07 11:12 ?1654次閱讀

    Ring Clojure的Web框架

    ./oschina_soft/ring.zip
    發(fā)表于 06-13 09:38 ?1次下載
    <b class='flag-5'>Ring</b> Clojure的Web框架

    BPF編程的環(huán)境搭建方法

    本來想寫一篇“BPF 深度分析、環(huán)境搭建與案例分析”的文章,但是篇幅過長,于是先把BPF編程的環(huán)境搭建先放出來。接下來的文章將對BPF深度分析(包括BPF虛擬機、
    的頭像 發(fā)表于 10-14 17:02 ?2324次閱讀
    <b class='flag-5'>BPF</b>編程的環(huán)境搭建方法

    BPF為內(nèi)核編程提供了一個新的參考模型

    這個新的編程環(huán)境混合使用了 C語言擴展以及運行時環(huán)境的組合實現(xiàn)的,這個運行時環(huán)境包含了 Clang、用戶空間的 BPF 加載器庫(libbpf)和內(nèi)核中的 BPF 子系統(tǒng)。
    的頭像 發(fā)表于 10-19 11:27 ?1439次閱讀

    內(nèi)核觀測技術(shù)BPF詳解

    BPF簡介 BPF,全稱是Berkeley Packet Filter(伯克利數(shù)據(jù)包過濾器)的縮寫。其誕生于1992年,最初的目的是提升網(wǎng)絡(luò)包過濾工具的性能。后面,隨著這個工具重新實現(xiàn)BPF的內(nèi)核
    的頭像 發(fā)表于 11-10 10:34 ?2118次閱讀

    MSPM0 UART通信中DMA和Ring Buffer環(huán)形緩沖的應(yīng)用

    電子發(fā)燒友網(wǎng)站提供《MSPM0 UART通信中DMA和Ring Buffer環(huán)形緩沖的應(yīng)用.pdf》資料免費下載
    發(fā)表于 09-05 11:01 ?0次下載
    MSPM0 UART通信中DMA和<b class='flag-5'>Ring</b> <b class='flag-5'>Buffer</b>環(huán)形緩沖的應(yīng)用