chordStats.pl 程序
一般策略
節拍、音色、和音以及通知速率的選擇綜合了藝術與科學兩個方面,而這種綜合的方式已經遠遠超出本文討論范圍。為了簡化開發及信息分發,此程序的主要特性包括 1-Hz 刷新率和基于八度音階的通知標準。vmstat 程序為基本系統數據提供了一個簡單接口,而且創建了一個 1-Hz “心跳” 并以它為節拍。
清單 2. 主程序參數
#!/usr/bin/perl -w
# chordStats.pl - create music based on system status
use strict;
my $vmStatCmd = "vmstat 1"; # run vmstat every second
my $totalPackets = 0; # total of packets received and transmitted
my $lineCount = 0; # count number of vmstat output lines
my %fields = ();
my $count = 0;
# the field headers in the vmstat output, useful for referring to them by name
for( split " ", "r b swpd free buff cache si so bi bo in cs us sy id wa" ){
$fields{$_} = $count;
$count++;
}
# buffering output must be turned off because fluidsynth does not appear to
# accept buffered input from stdin
$|=1;
|
在腳本的開頭,我們選擇 vmstat 1 作為要被執行的命令并且每秒讀取一次。為各次讀取之間記錄的信息包總數設置一個變量并記錄從 vmstat 程序中讀取到的行數,接下來定義標題。每秒都會從 vmstat 程序中讀取字段標題 bi(磁盤塊入)、bo(磁盤塊出)和 us(用戶 CPU 使用量)。字段散列允許稍后在程序中按名稱引用這些數據字段。請注意 $|=1 行。如果刪除此行,您將會遇到一些難以診斷的行為;還需要為緩沖而頭疼!
清單 3. 主程序開始
# open the vmstat program to read from
open( INPIPE, "$vmStatCmd |" ) || die "can't read from vmstat";
# wait while the fluidsynth program opens
sleep(3);
while(my $statLine = <INPIPE> ){
# ignore the header display, and the fieldname display lines
if( $statLine !~ /\-\-\-\-/ && $statLine !~ /swpd/ ){
# the first line of vmstat data is a recent average, ignore
if( $lineCount > 2 ){
|
代碼的下一部分將通過 vmstat 命令創建一個管道,程序將在其中每秒讀取一次數據。等待幾秒待 FluidSynth 程序激活后,即可開始處理 vmstat 輸出。輸出的前三行將被忽略,因為它們分別包含分隔符、標題信息和最新的平均值。
清單 4. 主程序通知處理
# reset wavetable synthesis
if( $totalTime % 10 == 0 ){ print "reset\n" }
$totalTime ++;
my $note = "";
my @currLine = split " ", $statLine;
# user cpu usage
$note = $currLine[ $fields{us} ];
sendNote( $note, 14, 12, 96 );
# conglomerate disk i/o fields to one stat
$note = $currLine[ $fields{bi} ] + $currLine[ $fields{bo} ];
if( $note > 1000 ){ $note = 1000; }
$note = $note/10;
sendNote( $note, 8, 12, 96 );
# network throughput on eth0
$note = getNetworkStats();
sendNote( $note, 5, 12, 84 );
}#if not first 3 lines to ignore
}#if not a header line
$lineCount++;
}#while reading the pipe
close(INPIPE);
|


