hello_perf_output_using_ns.php 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. <?php
  2. $prog = <<<EOT
  3. #include <linux/sched.h>
  4. // define output data structure in C
  5. struct data_t {
  6. u32 pid;
  7. u64 ts;
  8. char comm[TASK_COMM_LEN];
  9. };
  10. BPF_PERF_OUTPUT(events);
  11. int hello(struct pt_regs *ctx) {
  12. struct data_t data = {};
  13. struct bpf_pidns_info ns = {};
  14. if(bpf_get_ns_current_pid_tgid(DEV, INO, &ns, sizeof(struct bpf_pidns_info)))
  15. return 0;
  16. data.pid = ns.pid;
  17. data.ts = bpf_ktime_get_ns();
  18. bpf_get_current_comm(&data.comm, sizeof(data.comm));
  19. events.perf_submit(ctx, &data, sizeof(data));
  20. return 0;
  21. }
  22. EOT;
  23. $stat = stat("/proc/self/ns/pid");
  24. $dev = $stat["dev"];
  25. $ino = $stat["ino"];
  26. $prog = str_replace("DEV", strval($dev), $prog);
  27. $prog = str_replace("INO", strval($ino), $prog);
  28. # load BPF program
  29. $b = new Bpf(["text" => $prog]);
  30. $b->attach_kprobe($b->get_syscall_fnname("clone"), "hello");
  31. # header
  32. printf("%-18s %-16s %-6s %s\n", "TIME(s)", "COMM", "PID", "MESSAGE");
  33. # process event
  34. $start = 0;
  35. function print_event($cpu, $data, $size) {
  36. global $start;
  37. $event = unpack("Qpid/Qts/A16comm", $data);
  38. if ($start == 0) {
  39. $start = $event['ts'];
  40. }
  41. $time_s = ($event['ts'] - $start) / 1000000000.0;
  42. printf("%-18.9f %-16s %-6d %s\n", $time_s, $event['comm'], $event['pid'], "Hello, perf_output!");
  43. }
  44. # loop with callback to print_event
  45. $b->events->open_perf_buffer("print_event");
  46. while (true) {
  47. try {
  48. $b->perf_buffer_poll();
  49. } catch (Exception $e) {
  50. exit();
  51. }
  52. }