驅動程式 - Linux Device Driver(LDD) - SystemTap - Oneshot、Begin差異



參考資訊:
https://segmentfault.com/a/1190000019602980

main.stp

probe oneshot
{
    printf("=== oneshot ===\n");
}

probe begin
{
    printf("=== begin ===\n");
}

probe end 
{
    printf("=== end ===\n");
}

執行

$ sudo stap main.stp
    === oneshot ===
    === end ===

為何begin沒有被執行到?

經由轉換成C語言,可以發現,oneshot和begin都是屬於同一個state和type,因此,誰先出現誰就先被執行

static struct stap_probe stap_probes[] = {
  STAP_PROBE_INIT(0, &probe_6362, "begin", "oneshot", "main.stp:1:7", " from: oneshot from: oneshot"),
  STAP_PROBE_INIT(1, &probe_6363, "begin", "begin", "main.stp:6:1", " from: begin"),
  STAP_PROBE_INIT(2, &probe_6364, "end", "end", "main.stp:11:1", " from: end"),
};

static struct stap_be_probe {
  const struct stap_probe * const probe;
  int state, type;
} stap_be_probes[] = {
  { .probe=(&stap_probes[0]), .state=STAP_SESSION_STARTING, .type=0 },
  { .probe=(&stap_probes[1]), .state=STAP_SESSION_STARTING, .type=0 },
  { .probe=(&stap_probes[2]), .state=STAP_SESSION_STOPPING, .type=1 },
};

oneshot

static void probe_6362 (struct context * __restrict__ c)
{
  __label__ deref_fault;
  __label__ out;
  struct probe_6362_locals * __restrict__ l = & c->probe_locals.probe_6362;
  (void) l;
  if (c->actionremaining < 2) { c->last_error = "MAXACTION exceeded"; goto out; }
  {
    (void)
    ({
      _stp_print ("=== oneshot ===\n");
    });

    (void)
    ({
      c->last_stmt = "identifier 'exit' at /usr/local/share/systemtap/tapset/oneshot.stp:4:3";
      function___global_exit__overload_0(c);
      if (unlikely(c->last_error || c->aborted)) goto out;
      (void) 0;
    });

  }
deref_fault: __attribute__((unused));
out:
  _stp_print_flush();
}

P.S. function___global_exit__overload_0()

begin

static void probe_6363 (struct context * __restrict__ c)
{
  __label__ deref_fault;
  __label__ out;
  struct probe_6363_locals * __restrict__ l = & c->probe_locals.probe_6363;
  (void) l;
  if (c->actionremaining < 1) { c->last_error = "MAXACTION exceeded"; goto out; }
  (void)
  ({
    _stp_print ("=== begin ===\n");
  });
deref_fault: __attribute__((unused));
out:
  _stp_print_flush();
}

oneshot和begin的差異就是,oneshot會呼叫function___global_exit__overload_0(),進而呼叫_stp_exit()結束執行,這也是為何oneshot執行後,程式直接結束的原因

static void function___global_exit__overload_0(struct context* __restrict__ c)
{
    ...
    atomic_set(session_state(), STAP_SESSION_STOPPING);
    _stp_exit();
    ...
}

重新改寫位置

probe begin
{
    printf("=== begin ===\n");
}

probe oneshot
{
    printf("=== oneshot ===\n");
}

probe end
{
    printf("=== end ===\n");
}

執行

$ sudo stap main.stp
    === begin ===
    === oneshot ===
    === end ===