簡體   English   中英

為什么 sys_futex 上的 kretprobe 調用頻率低於相應的 kprobe?

[英]Why is a kretprobe on sys_futex called less often than a corresponding kprobe?

我正在跟蹤各種內核函數和系統調用,並在它們之間建立可用於某些性能分析的模式。

我注意到的一件事是,有時,即使在我的簡單測試應用程序中,它會啟動一些與一些互斥體一起玩的線程,我也不會收到任何對kretprobe__sys_futex調用,但我會得到很多kprobe__sys_futex

我認為這是因為例如一個線程正在調用sys_futex ,然后進入睡眠狀態或可能終止,但我實際上看到相同的進程連續多次調用sys_futex而返回探測器從未注意到任何事情。

然后我假設問題在於我如何過濾對kprobe__sys_futex調用,所以我使用 BCC/eBPF 做了一個最小的例子來測試這個:

#! /usr/bin/env python

from bcc import BPF

b = BPF(text="""
BPF_HASH(call_count, int, int);

int kprobe__sys_futex() {
  int zero = 0;
  call_count.lookup_or_init(&zero, &zero);
  bpf_trace_printk("futex start\\n");
  call_count.increment(zero);
  return 0;
}

int kretprobe__sys_futex() {
  int zero = 0;
  int *val_p = call_count.lookup(&zero);
  if (val_p != NULL) {
      int val = *val_p;
      val--;
      call_count.update(&zero, &val);
      bpf_trace_printk("futex calls with no return: %d\\n", val);
  } else { bpf_trace_printk("unexpected futex return\\n"); }
  return 0;
}
""")

b.trace_print()

我注意到在各種應用程序中(一個很好的例子是 mysql-server,它即使在空閑時也會執行常規的 futex 操作 - 至少在我的機器上),許多(通常是 10+)個futex start在返回消息之前打印探測。

這是我在寫這篇文章時運行了幾分鍾的上述程序的示例跟蹤:

... hundreds of lines of much the same as below
           gdbus-612   [001] .... 211229.997665: 0x00000001: futex start
  NetworkManager-541   [001] .... 211229.997667: 0x00000001: futex start
           gdbus-612   [001] .... 211229.997670: 0x00000001: futex start
          mysqld-697   [001] .... 211230.789205: 0x00000001: futex start
          mysqld-697   [001] .... 211230.789227: 0x00000001: futex start
          mysqld-703   [001] .... 211230.789251: 0x00000001: futex start
          mysqld-703   [001] .... 211230.789253: 0x00000001: futex start
          mysqld-704   [001] d... 211230.789258: 0x00000001: futex calls with no return: 3994
          mysqld-704   [001] .... 211230.789259: 0x00000001: futex start
          mysqld-704   [001] d... 211230.789260: 0x00000001: futex calls with no return: 3994
          mysqld-704   [001] .... 211230.789272: 0x00000001: futex start
          mysqld-713   [000] .... 211231.037016: 0x00000001: futex start
          mysqld-713   [000] .... 211231.037036: 0x00000001: futex start
         vmstats-895   [000] .... 211231.464867: 0x00000001: futex start
          mysqld-697   [001] .... 211231.790738: 0x00000001: futex start
          mysqld-697   [001] .... 211231.790784: 0x00000001: futex start
          mysqld-703   [001] .... 211231.790796: 0x00000001: futex start
          mysqld-703   [001] .... 211231.790799: 0x00000001: futex start
          mysqld-704   [001] d... 211231.790809: 0x00000001: futex calls with no return: 4001
          mysqld-704   [001] .... 211231.790812: 0x00000001: futex start
          mysqld-704   [001] d... 211231.790814: 0x00000001: futex calls with no return: 4001

如您所見,例如 pid 697 似乎已經四次調用sys_futex ,而只是在這個小跟蹤中沒有返回。

我不認為這是 eBPF 代碼中的競爭條件,因為如果您將打印語句靜音並僅定期打印,則sys_write的計數通常在零sys_write ,這比sys_futex發生的頻率sys_futex (至少在我的系統的工作負載),所以我希望任何競爭條件都會加劇而不是解決。

我在位於 VirtualBox 的 Ubuntu 18.04 LTS 上運行內核 4.15.0-43-generic。

很高興提供更多可能有用的上下文!

IOVisor 郵件列表中有一個相關主題: https ://lists.iovisor.org/g/iovisor-dev/topic/29702757

這是 bcc 的已知限制(參見iovisor/bcc#1072 )。 基本上,對於您的跟蹤上下文,最大活動探測器數設置得太低,因此您會丟失一些返回探測器。

在 bcc 中, maxactive值(最大活動探測器數,請參閱下面的文檔摘錄)保留為其默認值。 由於 Alban Crequy的 Linux 內核補丁(參見iovisor/bcc#1072 ),通過 debugfs 附加探測器時可以更改maxactive值。 不過,這個新 API 還沒有通過 bcc 公開。 本周我將嘗試發送一個補丁來達到這個效果。

當被探測的函數正在執行時,它的返回地址存儲在 kretprobe_instance 類型的對象中。 在調用 register_kretprobe() 之前,用戶設置 kretprobe 結構體的 maxactive 字段以指定可以同時探測指定函數的多少個實例 register_kretprobe() 預先分配指定數量的 kretprobe_instance 對象。

例如,如果函數是非遞歸的並且在調用時持有自旋鎖,則 maxactive = 1 就足夠了。 如果函數是非遞歸的並且永遠不能放棄 CPU(例如,通過信號量或搶占),NR_CPUS 應該就足夠了。 如果 maxactive <= 0,則將其設置為默認值。 如果啟用了 CONFIG_PREEMPT,則默認值為 max(10, 2*NR_CPUS)。 否則,默認值為 NR_CPUS。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM