/proc/swaps
/proc/swapsはswap_info[]のswap_info_structからswap情報を表示します。なおswapon -aコマンドは/proc/swapsを参照することで実現しています。
PAGE_SHIFTは通常12で、1pageは4Kバイトで、PAGE_SHIFT - 10はpageをkバイト単位で表示するためで、上記Size/UsedはKバイトです。
[root@localhost kitamura]# cat /proc/swaps Filename Type Size Used Priority /dev/dm-0 partition 1671164 0 0 [root@localhost kitamura]# swapon -s Filename Type Size Used Priority /dev/mapper/VolGroup-lv_swap partition 1671164 0 0 [root@localhost kitamura]# ls -l /dev/mapper/VolGroup-lv_swap lrwxrwxrwx 1 root root 7 2月 8 01:23 /dev/mapper/VolGroup-lv_swap -> ../dm-0nr_swapfilesでswap_info[]内のif (!(si->flags & SWP_USED) || !si->swap_map)でないswap_info_structを取得します。nr_swapfilesはswapoffしてもがデクリメントされることはありません。(対応するswap_info[]のメモリも解放されません。ただし使用可能スロットのsi->swap_mapは解放されます。) その使用されなくなったswap_info_structは、新たなswapに再利用することで無駄なメモリ取得/解放を無くすような実装となっています。
PAGE_SHIFTは通常12で、1pageは4Kバイトで、PAGE_SHIFT - 10はpageをkバイト単位で表示するためで、上記Size/UsedはKバイトです。
static const struct seq_operations swaps_op = { .start = swap_start, .next = swap_next, .stop = swap_stop, .show = swap_show }; static int swap_show(struct seq_file *swap, void *v) { struct swap_info_struct *si = v; struct file *file; int len; if (si == SEQ_START_TOKEN) { seq_puts(swap,"Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n"); return 0; } file = si->swap_file; len = seq_path(swap, &file->f_path, " \t\n\\"); seq_printf(swap, "%*s%s\t%u\t%u\t%d\n", len < 40 ? 40 - len : 1, " ", S_ISBLK(file->f_path.dentry->d_inode->i_mode) ? "partition" : "file\t", si->pages << (PAGE_SHIFT - 10), si->inuse_pages << (PAGE_SHIFT - 10), si->prio); return 0; } static void *swap_start(struct seq_file *swap, loff_t *pos) { struct swap_info_struct *si; int type; loff_t l = *pos; mutex_lock(&swapon_mutex); if (!l) return SEQ_START_TOKEN; for (type = 0; type < nr_swapfiles; type++) { smp_rmb(); /* read nr_swapfiles before swap_info[type] */ si = swap_info[type]; if (!(si->flags & SWP_USED) || !si->swap_map) continue; if (!--l) return si; } return NULL; } static void *swap_next(struct seq_file *swap, void *v, loff_t *pos) { struct swap_info_struct *si = v; int type; if (v == SEQ_START_TOKEN) type = 0; else type = si->type + 1; for (; type < nr_swapfiles; type++) { smp_rmb(); /* read nr_swapfiles before swap_info[type] */ si = swap_info[type]; if (!(si->flags & SWP_USED) || !si->swap_map) continue; ++*pos; return si; } return NULL; }