sarファイルのソースコードを読んでみよう
sarコマンド
sarコマンドはどこからネットワークの受信や送信情報を取得しているのだろうか。
気になったらコマンドのソースコードを読んでみよう。
ネットワークの情報は、/proc/netから読み込んでいると予想をたてさくらエディタでの
探検開始。
どうも「/proc/net/dev」が情報源と見える。
Every 2.0s: cat /proc/net/dev Thu Jul 9 22:01:07 2015
Inter-| Receive | Transmit
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
lo: 3770 45 0 0 0 0 0 0 3770 45 0 0 0 0 0 0
eth0: 149037 1724 0 0 0 0 0 13 337074 1287 0 0 0 0 0 0
ちなみにsar -n DEV の結果
22時01分35秒 IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s
22時01分36秒 lo 0.00 0.00 0.00 0.00 0.00 0.00 0.00
22時01分36秒 eth0 2.00 2.00 0.12 0.54 0.00 0.00 0.00
さくらエディタでのgrep検索結果
sysstat-11.1.5\rd_stats.h(56,19) [SJIS]: #define NET_DEV "/proc/net/dev"
以下のコードで"/proc/net/dev"(NET_DEV)を読み込んでいる。
どうもソースからNIC数をカウントしている模様。
int get_iface_nr(void)
{
FILE *fp;
char line[128];
int iface = 0;
if *1 == NULL)
return 0; /* No network device file */
while (fgets(line, sizeof(line), fp) != NULL) {
if (strchr(line, ':')) {
iface++;
}
}
fclose(fp);
return iface;
}
次にここが総本山。この構造体がデータの格納場所のよう。間違いなさそう。
int read_net_dev(struct stats_net_dev *st_net_dev, int nbr)
{
FILE *fp;
struct stats_net_dev *st_net_dev_i;
char line[256];
char iface[MAX_IFACE_LEN];
int dev = 0;
int pos;
if *2 == NULL)
return 0;
while *3 {
pos = strcspn(line, ":");
if (pos < strlen(line)) {
st_net_dev_i = st_net_dev + dev;
strncpy(iface, line, MINIMUM(pos, MAX_IFACE_LEN - 1));
iface[MINIMUM(pos, MAX_IFACE_LEN - 1)] = '\0';
sscanf(iface, "%s", st_net_dev_i->interface); /* Skip heading spaces */
sscanf(line + pos + 1, "%llu %llu %*u %*u %*u %*u %llu %llu %llu %llu "
"%*u %*u %*u %*u %*u %llu",
&st_net_dev_i->rx_bytes,
&st_net_dev_i->rx_packets,
&st_net_dev_i->rx_compressed,
&st_net_dev_i->multicast,
&st_net_dev_i->tx_bytes,
&st_net_dev_i->tx_packets,
&st_net_dev_i->tx_compressed);
dev++;
}
}
fclose(fp);
return dev;
}
まずはこの関数「read_net_dev」を調べてみる
このあたりから少しわからなくなる。
なんとなくsarの表示の定義のよう。
activity.cから
* Network interfaces activity */
struct activity net_dev_act = {
.id = A_NET_DEV,
.options = AO_COLLECTED,
.magic = ACTIVITY_MAGIC_BASE + 2,
.group = G_DEFAULT,
#ifdef SOURCE_SADC
.f_count_index = 4, /* wrap_get_iface_nr() */
.f_count2 = NULL,
.f_read = ,
#endif
#ifdef SOURCE_SAR
.f_print = print_net_dev_stats,
.f_print_avg = print_net_dev_stats,
#endif
#ifdef SOURCE_SADF
.f_render = render_net_dev_stats,
.f_xml_print = xml_print_net_dev_stats,
.f_json_print = json_print_net_dev_stats,
.hdr_line = "IFACE;rxpck/s;txpck/s;rxkB/s;txkB/s;rxcmp/s;txcmp/s;rxmcst/s;%ifutil",
.name = "A_NET_DEV",
#endif
.nr = -1,
.nr2 = 1,
.fsize = STATS_NET_DEV_SIZE,
.msize = STATS_NET_DEV_SIZE,
.opt_flags = 0,
.buf = {NULL, NULL, NULL},
.bitmap = NULL
};
ちなみにintervalは
sysstat-11.1.5\sar.c(1179,14) [SJIS]: int main(int argc, char **argv)のなかの
intervalから取得していた。
else if (interval < 0) {
/* Get interval */
if (strspn(argv[opt], DIGITS) != strlen(argv[opt])) {
usage(argv[0]);
}
interval = atol(argv[opt++]);
if (interval < 0) {
usage(argv[0]);
}
ふむふむ。
結論として
受信と送信は「"/proc/net/dev"」から取得する。