1 #!/usr/bin/perl -w 2 # SPDX-License-Identifier: GPL-2.0-only 3 # (c) 2010, Tom Zanussi <tzanussi@gmail.com> 4 5 # read/write top 6 # 7 # Periodically displays system-wide r/w call activity, broken down by 8 # pid. If an [interval] arg is specified, the display will be 9 # refreshed every [interval] seconds. The default interval is 3 10 # seconds. 11 12 use 5.010000; 13 use strict; 14 use warnings; 15 16 use lib "$ENV{'PERF_EXEC_PATH'}/scripts/perl/Perf-Trace-Util/lib"; 17 use lib "./Perf-Trace-Util/lib"; 18 use Perf::Trace::Core; 19 use Perf::Trace::Util; 20 use POSIX qw/SIGALRM SA_RESTART/; 21 22 my $default_interval = 3; 23 my $nlines = 20; 24 my $print_thread; 25 my $print_pending = 0; 26 27 my %reads; 28 my %writes; 29 30 my $interval = shift; 31 if (!$interval) { 32 $interval = $default_interval; 33 } 34 35 sub syscalls::sys_exit_read 36 { 37 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs, 38 $common_pid, $common_comm, $common_callchain, 39 $nr, $ret) = @_; 40 41 print_check(); 42 43 if ($ret > 0) { 44 $reads{$common_pid}{bytes_read} += $ret; 45 } else { 46 if (!defined ($reads{$common_pid}{bytes_read})) { 47 $reads{$common_pid}{bytes_read} = 0; 48 } 49 $reads{$common_pid}{errors}{$ret}++; 50 } 51 } 52 53 sub syscalls::sys_enter_read 54 { 55 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs, 56 $common_pid, $common_comm, $common_callchain, 57 $nr, $fd, $buf, $count) = @_; 58 59 print_check(); 60 61 $reads{$common_pid}{bytes_requested} += $count; 62 $reads{$common_pid}{total_reads}++; 63 $reads{$common_pid}{comm} = $common_comm; 64 } 65 66 sub syscalls::sys_exit_write 67 { 68 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs, 69 $common_pid, $common_comm, $common_callchain, 70 $nr, $ret) = @_; 71 72 print_check(); 73 74 if ($ret <= 0) { 75 $writes{$common_pid}{errors}{$ret}++; 76 } 77 } 78 79 sub syscalls::sys_enter_write 80 { 81 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs, 82 $common_pid, $common_comm, $common_callchain, 83 $nr, $fd, $buf, $count) = @_; 84 85 print_check(); 86 87 $writes{$common_pid}{bytes_written} += $count; 88 $writes{$common_pid}{total_writes}++; 89 $writes{$common_pid}{comm} = $common_comm; 90 } 91 92 sub trace_begin 93 { 94 my $sa = POSIX::SigAction->new(\&set_print_pending); 95 $sa->flags(SA_RESTART); 96 $sa->safe(1); 97 POSIX::sigaction(SIGALRM, $sa) or die "Can't set SIGALRM handler: $!\n"; 98 alarm 1; 99 } 100 101 sub trace_end 102 { 103 print_unhandled(); 104 print_totals(); 105 } 106 107 sub print_check() 108 { 109 if ($print_pending == 1) { 110 $print_pending = 0; 111 print_totals(); 112 } 113 } 114 115 sub set_print_pending() 116 { 117 $print_pending = 1; 118 alarm $interval; 119 } 120 121 sub print_totals 122 { 123 my $count; 124 125 $count = 0; 126 127 clear_term(); 128 129 printf("\nread counts by pid:\n\n"); 130 131 printf("%6s %20s %10s %10s %10s\n", "pid", "comm", 132 "# reads", "bytes_req", "bytes_read"); 133 printf("%6s %-20s %10s %10s %10s\n", "------", "--------------------", 134 "----------", "----------", "----------"); 135 136 foreach my $pid (sort { ($reads{$b}{bytes_read} || 0) <=> 137 ($reads{$a}{bytes_read} || 0) } keys %reads) { 138 my $comm = $reads{$pid}{comm} || ""; 139 my $total_reads = $reads{$pid}{total_reads} || 0; 140 my $bytes_requested = $reads{$pid}{bytes_requested} || 0; 141 my $bytes_read = $reads{$pid}{bytes_read} || 0; 142 143 printf("%6s %-20s %10s %10s %10s\n", $pid, $comm, 144 $total_reads, $bytes_requested, $bytes_read); 145 146 if (++$count == $nlines) { 147 last; 148 } 149 } 150 151 $count = 0; 152 153 printf("\nwrite counts by pid:\n\n"); 154 155 printf("%6s %20s %10s %13s\n", "pid", "comm", 156 "# writes", "bytes_written"); 157 printf("%6s %-20s %10s %13s\n", "------", "--------------------", 158 "----------", "-------------"); 159 160 foreach my $pid (sort { ($writes{$b}{bytes_written} || 0) <=> 161 ($writes{$a}{bytes_written} || 0)} keys %writes) { 162 my $comm = $writes{$pid}{comm} || ""; 163 my $total_writes = $writes{$pid}{total_writes} || 0; 164 my $bytes_written = $writes{$pid}{bytes_written} || 0; 165 166 printf("%6s %-20s %10s %13s\n", $pid, $comm, 167 $total_writes, $bytes_written); 168 169 if (++$count == $nlines) { 170 last; 171 } 172 } 173 174 %reads = (); 175 %writes = (); 176 } 177 178 my %unhandled; 179 180 sub print_unhandled 181 { 182 if ((scalar keys %unhandled) == 0) { 183 return; 184 } 185 186 print "\nunhandled events:\n\n"; 187 188 printf("%-40s %10s\n", "event", "count"); 189 printf("%-40s %10s\n", "----------------------------------------", 190 "-----------"); 191 192 foreach my $event_name (keys %unhandled) { 193 printf("%-40s %10d\n", $event_name, $unhandled{$event_name}); 194 } 195 } 196 197 sub trace_unhandled 198 { 199 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs, 200 $common_pid, $common_comm, $common_callchain) = @_; 201 202 $unhandled{$event_name}++; 203 }
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.