rbbcc 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 162758633aea60cbe4979dd77f61603a7f2032d624594b523f990d703d9fc0e6
4
- data.tar.gz: 39b9b0b9fd390f45a5a242d6182197d9e39de0fb0444f06c94872a42b5dd4d5a
3
+ metadata.gz: 35d11d74dd0d8eacf88978ec066ede1d64aef374027d819f5891a124822db4e9
4
+ data.tar.gz: 22125362cf25181c33b253d7c6ece7d2e9b9fa2d8933d8c7f120c453384df5d8
5
5
  SHA512:
6
- metadata.gz: e807d4903cbd8683eb58b073700a24993824e23027de3445d2729728e9cbe7d556a7948a15efaf5c5e7462521675854ec40e32e9776d64c637778fcbad4ad79c
7
- data.tar.gz: fcecb00f5eb34f247987b445c59daa221b99ed477ffcd5355e965ac20c97cbe748b3650f2066de1b6575e4ffaf97c7cf21bf9751a7e55ec02cfb0a1837f3e7be
6
+ metadata.gz: d145f5307df79f42679892b26b4f3f320dbdfb7d931f65f9f2b84ba4032d780991c2f2d0fb36a06b030bc59e45d16b4cca201d42e0368eb5ed4d4853958d44f3
7
+ data.tar.gz: 86c50507da5cc6ba947def8ce7c169937a432579ce92e0b70c0d24d4316fbba7c45a2de22d602b0c166f473db8e8fddeab1d961b07b97dd719b0a30f15fd9234
data/Gemfile.lock CHANGED
@@ -12,7 +12,7 @@ GEM
12
12
  pry (0.12.2)
13
13
  coderay (~> 1.1.0)
14
14
  method_source (~> 0.9.0)
15
- rake (10.5.0)
15
+ rake (13.0.1)
16
16
 
17
17
  PLATFORMS
18
18
  ruby
@@ -21,7 +21,7 @@ DEPENDENCIES
21
21
  bundler (~> 2.0)
22
22
  minitest
23
23
  pry
24
- rake (~> 10.0)
24
+ rake (~> 13.0)
25
25
  rbbcc!
26
26
 
27
27
  BUNDLED WITH
data/README.md CHANGED
@@ -94,6 +94,10 @@ $ docker run --privileged \
94
94
  runc-5025 [003] d... 1237.797464: : Hello, World!
95
95
  ```
96
96
 
97
+ ## Documents
98
+
99
+ See [docs/](docs/) for getting started and tutorial.
100
+
97
101
  ## Development
98
102
 
99
103
  After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
data/docs/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # RbBCC Docs
2
2
 
3
3
  * [Getting Started](getting_started.md)
4
+ * [Ruby Tutorial](tutorial_bcc_ruby_developer.md)
5
+ * [Projects Using RbBCC](projects_using_rbbcc.md)
4
6
 
5
7
  **Please see also [BCC itself's README](https://github.com/iovisor/bcc/#readme) and [docs](https://github.com/iovisor/bcc/tree/master/docs).**
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ # Original hello_world.py:
3
+ # Copyright (c) PLUMgrid, Inc.
4
+ # Licensed under the Apache License, Version 2.0 (the "License")
5
+ #
6
+ # This Ruby version follows the Apache License 2.0
7
+
8
+ # run in project examples directory with:
9
+ # sudo ./hello_world.rb"
10
+ # see trace_fields.rb for a longer example
11
+
12
+ require "rbbcc"
13
+ include RbBCC
14
+
15
+ # This may not work for 4.17 on x64, you need replace kprobe__sys_clone with kprobe____x64_sys_clone
16
+ BCC.new(text: 'int kprobe__sys_clone(void *ctx) { bpf_trace_printk("Hello, World!\\n"); return 0; }').trace_print
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+ # Licensed under the Apache License, Version 2.0 (the "License")
3
+
4
+ require "rbbcc"
5
+ include RbBCC
6
+
7
+ puts "Tracing sys_sync()... Ctrl-C to end."
8
+ begin
9
+ BCC.new(text: <<~BPF).trace_print
10
+ int kprobe__sys_sync(void *ctx) {
11
+ bpf_trace_printk("sys_sync() called\\n");
12
+ return 0;
13
+ }
14
+ BPF
15
+ rescue Interrupt
16
+ puts
17
+ puts "Done"
18
+ end
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+ # Licensed under the Apache License, Version 2.0 (the "License")
3
+
4
+ require "rbbcc"
5
+ include RbBCC
6
+
7
+ # define BPF program
8
+ prog = <<BPF
9
+ int hello(void *ctx) {
10
+ bpf_trace_printk("Hello, World!\\n");
11
+ return 0;
12
+ }
13
+ BPF
14
+
15
+ # load BPF program
16
+ b = BCC.new(text: prog)
17
+ b.attach_kprobe(event: b.get_syscall_fnname("clone"), fn_name: "hello")
18
+
19
+ # header
20
+ puts("%-18s %-16s %-6s %s" % ["TIME(s)", "COMM", "PID", "MESSAGE"])
21
+
22
+ # format output
23
+ begin
24
+ b.trace_fields do |task, pid, cpu, flags, ts, msg|
25
+ print("%-18.9f %-16s %-6d %s" % [ts, task, pid, msg])
26
+ end
27
+ rescue Interrupt
28
+ puts
29
+ puts "Done"
30
+ rescue => e
31
+ p e
32
+ retry
33
+ end
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env ruby
2
+ # Original sync_timing.py:
3
+ # Licensed under the Apache License, Version 2.0 (the "License")
4
+ #
5
+ # This Ruby version follows the Apache License 2.0
6
+
7
+ require "rbbcc"
8
+ include RbBCC
9
+
10
+ # load BPF program
11
+ b = BCC.new(text: <<BPF)
12
+ #include <uapi/linux/ptrace.h>
13
+
14
+ BPF_HASH(last);
15
+
16
+ int do_trace(struct pt_regs *ctx) {
17
+ u64 ts, *tsp, delta, key = 0;
18
+
19
+ // attempt to read stored timestamp
20
+ tsp = last.lookup(&key);
21
+ if (tsp != 0) {
22
+ delta = bpf_ktime_get_ns() - *tsp;
23
+ if (delta < 1000000000) {
24
+ // output if time is less than 1 second
25
+ bpf_trace_printk("%d\\n", delta / 1000000);
26
+ }
27
+ last.delete(&key);
28
+ }
29
+
30
+ // update stored timestamp
31
+ ts = bpf_ktime_get_ns();
32
+ last.update(&key, &ts);
33
+ return 0;
34
+ }
35
+ BPF
36
+
37
+ b.attach_kprobe(event: b.get_syscall_fnname("sync"), fn_name: "do_trace")
38
+ puts("Tracing for quick sync's... Ctrl-C to end")
39
+
40
+ # format output
41
+ start = 0
42
+ b.trace_fields do |task, pid, cpu, flags, ts, ms|
43
+ start = ts.to_f if start.zero?
44
+ ts = ts.to_f - start
45
+ puts("At time %.2f s: multiple syncs detected, last %s ms ago" % [ts, ms.chomp])
46
+ end
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env ruby
2
+ # Licensed under the Apache License, Version 2.0 (the "License")
3
+
4
+ require "rbbcc"
5
+ include RbBCC
6
+
7
+ # load BPF program
8
+ b = BCC.new(text: <<BPF)
9
+ #include <uapi/linux/ptrace.h>
10
+
11
+ BPF_HASH(last);
12
+
13
+ int do_trace(struct pt_regs *ctx) {
14
+ u64 ts, *tsp, delta, key = 0, counter_key = 1, zero = 0;
15
+
16
+ // initialize counter key
17
+ if (last.lookup_or_try_init(&counter_key, &zero))
18
+ last.increment(counter_key);
19
+
20
+ // attempt to read stored timestamp
21
+ tsp = last.lookup(&key);
22
+ if (tsp != 0) {
23
+ delta = bpf_ktime_get_ns() - *tsp;
24
+ if (delta < 1000000000) {
25
+ // output if time is less than 1 second
26
+ bpf_trace_printk("%d\\n", delta / 1000000);
27
+ }
28
+ last.delete(&key);
29
+ }
30
+
31
+ // update stored timestamp
32
+ ts = bpf_ktime_get_ns();
33
+ last.update(&key, &ts);
34
+ return 0;
35
+ }
36
+ BPF
37
+
38
+ COUNTER_KEY = 1
39
+
40
+ b.attach_kprobe(event: b.get_syscall_fnname("sync"), fn_name: "do_trace")
41
+ puts("Tracing for quick sync's... Ctrl-C to end")
42
+
43
+ # format output
44
+ start = 0
45
+ begin
46
+ b.trace_fields do |task, pid, cpu, flags, ts, ms|
47
+ start = ts.to_f if start.zero?
48
+ ts = ts.to_f - start
49
+ puts("At time %.2f s: multiple syncs detected, last %s ms ago" % [ts, ms.chomp])
50
+ end
51
+ rescue Interrupt
52
+ table = b["last"]
53
+ puts "Count of sys_sync: %d" % table[COUNTER_KEY].to_bcc_value
54
+ end
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # disksnoop.rb Trace block device I/O: basic version of iosnoop.
4
+ # For Linux, uses BCC, eBPF. Embedded C.
5
+ # This is ported from original disksnoop.py
6
+ #
7
+ # Written as a basic example of tracing latency.
8
+ #
9
+ # Licensed under the Apache License, Version 2.0 (the "License")
10
+ #
11
+ # 11-Aug-2015 Brendan Gregg Created disksnoop.py
12
+
13
+ require 'rbbcc'
14
+ include RbBCC
15
+
16
+ REQ_WRITE = 1 # from include/linux/blk_types.h
17
+
18
+ # load BPF program
19
+ b = BCC.new(text: <<CLANG)
20
+ #include <uapi/linux/ptrace.h>
21
+ #include <linux/blkdev.h>
22
+
23
+ BPF_HASH(start, struct request *);
24
+
25
+ void trace_start(struct pt_regs *ctx, struct request *req) {
26
+ // stash start timestamp by request ptr
27
+ u64 ts = bpf_ktime_get_ns();
28
+
29
+ start.update(&req, &ts);
30
+ }
31
+
32
+ void trace_completion(struct pt_regs *ctx, struct request *req) {
33
+ u64 *tsp, delta;
34
+
35
+ tsp = start.lookup(&req);
36
+ if (tsp != 0) {
37
+ delta = bpf_ktime_get_ns() - *tsp;
38
+ bpf_trace_printk("%d %x %d\\n", req->__data_len,
39
+ req->cmd_flags, delta / 1000);
40
+ start.delete(&req);
41
+ }
42
+ }
43
+ CLANG
44
+
45
+ b.attach_kprobe(event: "blk_start_request", fn_name: "trace_start") if BCC.get_kprobe_functions('blk_start_request')
46
+ b.attach_kprobe(event: "blk_mq_start_request", fn_name: "trace_start")
47
+ b.attach_kprobe(event: "blk_account_io_completion", fn_name: "trace_completion")
48
+
49
+ # header
50
+ puts("%-18s %-2s %-7s %8s" % ["TIME(s)", "T", "BYTES", "LAT(ms)"])
51
+
52
+ # format output
53
+ loop do
54
+ begin
55
+ task, pid, cpu, flags, ts, msg = b.trace_fields
56
+ bytes_s, bflags_s, us_s = msg.split
57
+
58
+ if (bflags_s.to_i(16) & REQ_WRITE).nonzero?
59
+ type_s = "W"
60
+ elsif bytes_s == "0" # see blk_fill_rwbs() for logic
61
+ type_s = "M"
62
+ else
63
+ type_s = "R"
64
+ end
65
+ ms = us_s.to_i.to_f / 1000
66
+
67
+ puts("%-18.9f %-2s %-7s %8.2f" % [ts, type_s, bytes_s, ms])
68
+ rescue Interrupt
69
+ exit
70
+ end
71
+ end
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This is a Hello World example that uses BPF_PERF_OUTPUT.
4
+ # Ported from hello_perf_output.py
5
+
6
+ require 'rbbcc'
7
+ include RbBCC
8
+
9
+ # define BPF program
10
+ prog = """
11
+ #include <linux/sched.h>
12
+
13
+ // define output data structure in C
14
+ struct data_t {
15
+ u32 pid;
16
+ u64 ts;
17
+ char comm[TASK_COMM_LEN];
18
+ };
19
+ BPF_PERF_OUTPUT(events);
20
+
21
+ int hello(struct pt_regs *ctx) {
22
+ struct data_t data = {};
23
+
24
+ data.pid = bpf_get_current_pid_tgid();
25
+ data.ts = bpf_ktime_get_ns();
26
+ bpf_get_current_comm(&data.comm, sizeof(data.comm));
27
+
28
+ events.perf_submit(ctx, &data, sizeof(data));
29
+
30
+ return 0;
31
+ }
32
+ """
33
+
34
+ # load BPF program
35
+ b = BCC.new(text: prog)
36
+ b.attach_kprobe(event: b.get_syscall_fnname("clone"), fn_name: "hello")
37
+
38
+ # header
39
+ puts("%-18s %-16s %-6s %s" % ["TIME(s)", "COMM", "PID", "MESSAGE"])
40
+
41
+ # process event
42
+ start = 0
43
+ print_event = lambda { |cpu, data, size|
44
+ event = b["events"].event(data)
45
+ if start == 0
46
+ start = event.ts
47
+ end
48
+
49
+ time_s = ((event.ts - start).to_f) / 1000000000
50
+ puts("%-18.9f %-16s %-6d %s" % [time_s, event.comm, event.pid,
51
+ "Hello, perf_output!"])
52
+ }
53
+
54
+ # loop with callback to print_event
55
+ b["events"].open_perf_buffer(&print_event)
56
+
57
+ loop do
58
+ b.perf_buffer_poll()
59
+ end
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env ruby
2
+ # Licensed under the Apache License, Version 2.0 (the "License")
3
+
4
+ require "rbbcc"
5
+ include RbBCC
6
+
7
+ # load BPF program
8
+ b = BCC.new(text: <<BPF)
9
+ #include <uapi/linux/ptrace.h>
10
+
11
+ struct data_t {
12
+ u32 pid;
13
+ u64 ts;
14
+ u64 delta;
15
+ };
16
+ BPF_PERF_OUTPUT(events);
17
+ BPF_HASH(last);
18
+
19
+ int do_trace(struct pt_regs *ctx) {
20
+ u64 ts, *tsp, delta, key = 0;
21
+
22
+ // attempt to read stored timestamp
23
+ tsp = last.lookup(&key);
24
+ if (tsp != 0) {
25
+ struct data_t data = {};
26
+ delta = bpf_ktime_get_ns() - *tsp;
27
+ if (delta < 1000000000) {
28
+ data.pid = bpf_get_current_pid_tgid();
29
+ data.ts = bpf_ktime_get_ns();
30
+ data.delta = delta;
31
+ events.perf_submit(ctx, &data, sizeof(data));
32
+ }
33
+ last.delete(&key);
34
+ }
35
+
36
+ // update stored timestamp
37
+ ts = bpf_ktime_get_ns();
38
+ last.update(&key, &ts);
39
+ return 0;
40
+ }
41
+ BPF
42
+
43
+ b.attach_kprobe(event: b.get_syscall_fnname("sync"), fn_name: "do_trace")
44
+ puts("Tracing for quick sync's... Ctrl-C to end")
45
+
46
+ # format output
47
+ start = 0
48
+ b["events"].open_perf_buffer do |_, data, _|
49
+ event = b["events"].event(data)
50
+ if start == 0
51
+ start = event.ts
52
+ end
53
+
54
+ time_s = ((event.ts - start).to_f) / 1_000_000_000
55
+ puts("At time %.2f s: multiple syncs detected, last %s ms ago" % [time_s, event.delta / 1_000_000])
56
+ end
57
+
58
+ loop do
59
+ b.perf_buffer_poll()
60
+ end
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env ruby
2
+ # Licensed under the Apache License, Version 2.0 (the "License")
3
+
4
+ require 'rbbcc'
5
+ include RbBCC
6
+
7
+ # load BPF program
8
+ b = BCC.new(text: <<BPF)
9
+ #include <uapi/linux/ptrace.h>
10
+ #include <linux/blkdev.h>
11
+
12
+ BPF_HISTOGRAM(dist);
13
+
14
+ int kprobe__blk_account_io_completion(struct pt_regs *ctx, struct request *req)
15
+ {
16
+ dist.increment(bpf_log2l(req->__data_len / 1024));
17
+ return 0;
18
+ }
19
+ BPF
20
+
21
+ # header
22
+ puts("Tracing... Hit Ctrl-C to end.")
23
+
24
+ # trace until Ctrl-C
25
+ begin
26
+ loop { sleep 0.1 }
27
+ rescue Interrupt
28
+ puts
29
+ end
30
+
31
+ # output
32
+ b["dist"].print_log2_hist("kbytes")
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env ruby
2
+ # Licensed under the Apache License, Version 2.0 (the "License")
3
+
4
+ require 'rbbcc'
5
+ include RbBCC
6
+
7
+ b = BCC.new(text: <<BPF)
8
+ #include <uapi/linux/ptrace.h>
9
+ #include <linux/blkdev.h>
10
+
11
+ BPF_HASH(start, struct request *);
12
+ BPF_HISTOGRAM(dist);
13
+
14
+ // note this program mixes R/W
15
+ // For next step, handle req->cmd_flags and prepare hist hash per op.
16
+
17
+ void trace_start(struct pt_regs *ctx, struct request *req) {
18
+ // stash start timestamp by request ptr
19
+ u64 ts = bpf_ktime_get_ns();
20
+
21
+ start.update(&req, &ts);
22
+ }
23
+
24
+ void trace_completion(struct pt_regs *ctx, struct request *req) {
25
+ u64 *tsp, delta;
26
+
27
+ tsp = start.lookup(&req);
28
+ if (tsp != 0) {
29
+ delta = bpf_ktime_get_ns() - *tsp;
30
+ dist.increment(bpf_log2l(delta / 1000)); // us
31
+ start.delete(&req);
32
+ }
33
+ }
34
+ BPF
35
+
36
+ b.attach_kprobe(event: "blk_start_request", fn_name: "trace_start") if BCC.get_kprobe_functions('blk_start_request')
37
+ b.attach_kprobe(event: "blk_mq_start_request", fn_name: "trace_start")
38
+ b.attach_kprobe(event: "blk_account_io_completion", fn_name: "trace_completion")
39
+
40
+ # header
41
+ puts("Tracing... Hit Ctrl-C to end.")
42
+
43
+ # trace until Ctrl-C
44
+ begin
45
+ loop { sleep 0.1 }
46
+ rescue Interrupt
47
+ puts
48
+ end
49
+
50
+ # output
51
+ b["dist"].print_log2_hist("usec")
@@ -0,0 +1,46 @@
1
+ /*
2
+ * From: https://github.com/iovisor/bcc/blob/master/examples/tracing/vfsreadlat.c
3
+ *
4
+ * vfsreadlat.c VFS read latency distribution.
5
+ * For Linux, uses BCC, eBPF. See .py/.rb file.
6
+ *
7
+ * Copyright (c) 2013-2015 PLUMgrid, http://plumgrid.com
8
+ * This program is free software; you can redistribute it and/or
9
+ * modify it under the terms of version 2 of the GNU General Public
10
+ * License as published by the Free Software Foundation.
11
+ *
12
+ * 15-Aug-2015 Brendan Gregg Created this.
13
+ */
14
+
15
+ #include <uapi/linux/ptrace.h>
16
+
17
+ BPF_HASH(start, u32);
18
+ BPF_HISTOGRAM(dist);
19
+
20
+ int do_entry(struct pt_regs *ctx)
21
+ {
22
+ u32 pid;
23
+ u64 ts, *val;
24
+
25
+ pid = bpf_get_current_pid_tgid();
26
+ ts = bpf_ktime_get_ns();
27
+ start.update(&pid, &ts);
28
+ return 0;
29
+ }
30
+
31
+ int do_return(struct pt_regs *ctx)
32
+ {
33
+ u32 pid;
34
+ u64 *tsp, delta;
35
+
36
+ pid = bpf_get_current_pid_tgid();
37
+ tsp = start.lookup(&pid);
38
+
39
+ if (tsp != 0) {
40
+ delta = bpf_ktime_get_ns() - *tsp;
41
+ dist.increment(bpf_log2l(delta / 1000));
42
+ start.delete(&pid);
43
+ }
44
+
45
+ return 0;
46
+ }
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Original: from vfsreadlat.py
4
+ # Copyright (c) 2015 Brendan Gregg.
5
+ # Licensed under the Apache License, Version 2.0 (the "License")
6
+ # Ruby version follows.
7
+ #
8
+ # vfsreadlat.rb VFS read latency distribution.
9
+ # For Linux, uses BCC, eBPF. See .c file.
10
+ #
11
+ # Written as a basic example of a function latency distribution histogram.
12
+ #
13
+ # USAGE: vfsreadlat.rb [interval [count]]
14
+ #
15
+ # The default interval is 5 seconds. A Ctrl-C will print the partially
16
+ # gathered histogram then exit.
17
+
18
+ require "rbbcc"
19
+ include RbBCC
20
+
21
+ def usage
22
+ puts("USAGE: %s [interval [count]]" % $0)
23
+ exit
24
+ end
25
+
26
+ # arguments
27
+ interval = 5
28
+ count = -1
29
+ if ARGV.size > 0
30
+ begin
31
+ interval = ARGV[0].to_i
32
+ raise if interval == 0
33
+ count = ARGV[1].to_i if ARGV[1]
34
+ rescue => e # also catches -h, --help
35
+ usage()
36
+ end
37
+ end
38
+
39
+ # load BPF program
40
+ b = BCC.new(src_file: "11-vfsreadlat.c")
41
+ b.attach_kprobe(event: "vfs_read", fn_name: "do_entry")
42
+ b.attach_kretprobe(event: "vfs_read", fn_name: "do_return")
43
+
44
+ # header
45
+ print("Tracing... Hit Ctrl-C to end.")
46
+
47
+ # output
48
+ cycle = 0
49
+ do_exit = false
50
+ loop do
51
+ if count > 0
52
+ cycle += 1
53
+ exit if cycle > count
54
+ end
55
+
56
+ begin
57
+ sleep(interval)
58
+ rescue Interrupt
59
+ do_exit = true
60
+ end
61
+
62
+ puts
63
+ b["dist"].print_log2_hist("usecs")
64
+ b["dist"].clear
65
+ exit if do_exit
66
+ end
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # urandomread.rb Example of instrumenting a kernel tracepoint.
4
+ # For Linux, uses BCC, BPF. Embedded C.
5
+ #
6
+ # REQUIRES: Linux 4.7+ (BPF_PROG_TYPE_TRACEPOINT support).
7
+ #
8
+ # Test by running this, then in another shell, run:
9
+ # dd if=/dev/urandom of=/dev/null bs=1k count=5
10
+ #
11
+ # Original urandomread.py Copyright 2016 Netflix, Inc.
12
+ # Licensed under the Apache License, Version 2.0 (the "License")
13
+ # Ruby version follows.
14
+
15
+ require 'rbbcc'
16
+ include RbBCC
17
+
18
+ b = BCC.new(text: <<BPF)
19
+ TRACEPOINT_PROBE(random, urandom_read) {
20
+ // args is from /sys/kernel/debug/tracing/events/random/urandom_read/format
21
+ bpf_trace_printk("%d\\n", args->got_bits);
22
+ return 0;
23
+ }
24
+ BPF
25
+
26
+ # header
27
+ puts("%-18s %-16s %-6s %s" % ["TIME(s)", "COMM", "PID", "GOTBITS"])
28
+
29
+ # format output
30
+ loop do
31
+ begin
32
+ b.trace_fields do |task, pid, cpu, flags, ts, msg|
33
+ puts("%-18.9f %-16s %-6d %s" % [ts, task, pid, msg])
34
+ end
35
+ rescue Interrupt
36
+ exit
37
+ end
38
+ end