rbbcc 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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