先说下环境,CentOS 6.0/Linux kernel 2.6.38.8/X86-64,后面提到的代码也都来之kernel 2.6.38.8。这个环节下的进程列表具体如下所示,后续将有一系列的文章分析各个进程(主要是内核进程)的功能:
[root@localhost ~]# cat /etc/issue
CentOS Linux release 6.0 (Final)
Kernel \r on an \m
[root@localhost ~]# uname -a
Linux localhost.localdomain 2.6.38.8 #4 SMP Mon Oct 31 20:49:48 CST 2011 x86_64 x86_64 x86_64 GNU/Linux
[root@localhost ~]# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.1 19284 1368 ? Ss Feb06 0:02 /sbin/init
root 2 0.0 0.0 0 0 ? S Feb06 0:00 [kthreadd]
root 3 0.0 0.0 0 0 ? S Feb06 0:00 [ksoftirqd/0]
root 5 0.0 0.0 0 0 ? S Feb06 0:20 [kworker/u:0]
root 6 0.0 0.0 0 0 ? S Feb06 0:00 [migration/0]
root 7 0.0 0.0 0 0 ? S Feb06 0:00 [migration/1]
root 9 0.0 0.0 0 0 ? S Feb06 0:00 [ksoftirqd/1]
root 11 0.0 0.0 0 0 ? S< Feb06 0:00 [cpuset]
root 12 0.0 0.0 0 0 ? S< Feb06 0:00 [khelper]
root 13 0.0 0.0 0 0 ? S< Feb06 0:00 [netns]
root 14 0.0 0.0 0 0 ? S Feb06 0:01 [sync_supers]
root 15 0.0 0.0 0 0 ? S Feb06 0:00 [bdi-default]
root 16 0.0 0.0 0 0 ? S< Feb06 0:00 [kintegrityd]
root 17 0.0 0.0 0 0 ? S< Feb06 0:00 [kblockd]
root 18 0.0 0.0 0 0 ? S< Feb06 0:00 [kacpid]
root 19 0.0 0.0 0 0 ? S< Feb06 0:00 [kacpi_notify]
root 20 0.0 0.0 0 0 ? S< Feb06 0:00 [kacpi_hotplug]
root 21 0.0 0.0 0 0 ? S< Feb06 0:00 [ata_sff]
root 22 0.0 0.0 0 0 ? S Feb06 0:00 [khubd]
root 23 0.0 0.0 0 0 ? S< Feb06 0:00 [md]
root 24 0.0 0.0 0 0 ? S Feb06 0:00 [khungtaskd]
root 25 0.0 0.0 0 0 ? S Feb06 0:05 [kswapd0]
root 26 0.0 0.0 0 0 ? SN Feb06 0:00 [ksmd]
root 27 0.0 0.0 0 0 ? SN Feb06 0:02 [khugepaged]
root 28 0.0 0.0 0 0 ? S Feb06 0:00 [fsnotify_mark]
root 29 0.0 0.0 0 0 ? S< Feb06 0:00 [aio]
root 30 0.0 0.0 0 0 ? S< Feb06 0:00 [crypto]
root 35 0.0 0.0 0 0 ? S Feb06 0:20 [kworker/u:1]
root 37 0.0 0.0 0 0 ? S< Feb06 0:00 [kpsmoused]
root 175 0.0 0.0 0 0 ? S Feb06 0:00 [scsi_eh_0]
root 176 0.0 0.0 0 0 ? S Feb06 0:42 [scsi_eh_1]
root 182 0.0 0.0 0 0 ? S< Feb06 0:00 [mpt_poll_0]
root 183 0.0 0.0 0 0 ? S< Feb06 0:00 [mpt/0]
root 184 0.0 0.0 0 0 ? S Feb06 0:00 [scsi_eh_2]
root 240 0.0 0.0 0 0 ? S< Feb06 0:00 [kdmflush]
root 247 0.0 0.0 0 0 ? S< Feb06 0:00 [kdmflush]
root 259 0.0 0.0 0 0 ? S Feb06 0:19 [jbd2/dm-0-8]
root 260 0.0 0.0 0 0 ? S< Feb06 0:00 [ext4-dio-unwrit]
root 297 0.0 0.0 0 0 ? S Feb06 0:01 [kauditd]
root 346 0.0 0.1 11700 1820 ? S<s Feb06 0:00 /sbin/udevd -d
root 565 0.0 0.0 0 0 ? S Feb06 0:05 [flush-253:0]
root 681 0.0 0.0 0 0 ? S< Feb06 0:00 [vmmemctl]
root 757 0.0 0.0 0 0 ? S< Feb06 0:00 [kdmflush]
root 801 0.0 0.0 0 0 ? S Feb06 0:00 [jbd2/sda1-8]
root 802 0.0 0.0 0 0 ? S< Feb06 0:00 [ext4-dio-unwrit]
root 803 0.0 0.0 0 0 ? S Feb06 0:00 [jbd2/dm-2-8]
root 804 0.0 0.0 0 0 ? S< Feb06 0:00 [ext4-dio-unwrit]
root 912 0.0 0.3 12880 3108 ? S< Feb06 0:00 /sbin/udevd -d
root 924 0.0 0.2 12356 2648 ? S< Feb06 0:00 /sbin/udevd -d
root 1114 0.0 0.1 242492 1540 ? Sl Feb06 0:05 /sbin/rsyslogd -c 4
root 1143 0.0 0.0 9104 428 ? Ss Feb06 1:04 irqbalance
rpc 1162 0.0 0.0 18920 816 ? Ss Feb06 0:01 rpcbind
root 1176 0.0 0.0 6604 260 ? Ss Feb06 0:00 mdadm --monitor --scan -f --pid-file=/var/run/mdadm/mdadm.pid
dbus 1185 0.0 0.1 29964 1448 ? Ssl Feb06 0:00 dbus-daemon --system
root 1196 0.0 0.3 95412 3468 ? Ssl Feb06 0:00 NetworkManager --pid-file=/var/run/NetworkManager/NetworkManager.pid
root 1202 0.0 0.1 55792 2000 ? S Feb06 0:00 /usr/sbin/modem-manager
avahi 1212 0.0 0.1 27820 1392 ? S Feb06 0:00 avahi-daemon: running [linux.local]
avahi 1213 0.0 0.0 27696 188 ? Ss Feb06 0:00 avahi-daemon: chroot helper
root 1221 0.0 0.1 9064 1360 ? S Feb06 0:04 /sbin/dhclient -d -4 -sf /usr/libexec/nm-dhcp-client.action -pf /var/run/dhclient-eth3.pid -lf /var/lib/dhclient/dhclient-aacaa3a9-81be-441d-ba72-cec0c023b1f8-eth3.lease -cf /var/run/nm-dhclient-eth3.conf eth3
root 1235 0.0 0.0 39232 388 ? Ss Feb06 0:00 /usr/sbin/wpa_supplicant -c /etc/wpa_supplicant/wpa_supplicant.conf -B -u -f /var/log/wpa_supplicant.log -P /var/run/wpa_supplicant.pid
rpcuser 1236 0.0 0.1 23088 1124 ? Ss Feb06 0:00 rpc.statd
root 1251 0.0 0.0 4020 508 tty1 Ss+ Feb11 0:00 /sbin/mingetty /dev/tty1
root 1280 0.0 0.0 0 0 ? S< Feb06 0:00 [rpciod]
root 1287 0.0 0.0 27336 396 ? Ss Feb06 0:00 rpc.idmapd
root 1297 0.0 0.2 178584 2840 ? Ss Feb06 0:00 cupsd -C /etc/cups/cupsd.conf
root 1322 0.0 0.0 4036 604 ? Ss Feb06 0:00 /usr/sbin/acpid
68 1331 0.0 0.3 26184 3252 ? Ss Feb06 0:03 hald
root 1332 0.0 0.1 18068 1136 ? S Feb06 0:00 hald-runner
root 1375 0.0 0.0 20184 832 ? S Feb06 0:00 hald-addon-input: Listening on /dev/input/event0 /dev/input/event1
root 1376 0.0 0.0 20180 856 ? S Feb06 0:18 hald-addon-storage: no polling on /dev/fd0 because it is explicitly disabled
68 1377 0.0 0.0 17760 988 ? S Feb06 0:00 hald-addon-acpi: listening on acpid socket /var/run/acpid.socket
root 1380 0.0 0.0 20180 856 ? S Feb06 1:29 hald-addon-storage: polling /dev/sr0 (every 2 sec)
root 1397 0.0 0.1 89180 1420 ? Ssl Feb06 0:00 pcscd
root 1418 0.0 0.3 381500 3368 ? Ssl Feb06 0:38 automount --pid-file /var/run/autofs.pid
root 1452 0.0 0.1 63804 1316 ? Ss Feb06 0:00 /usr/sbin/sshd
root 1478 0.0 0.0 22020 880 ? Ss Feb06 0:00 xinetd -stayalive -pidfile /var/run/xinetd.pid
root 1579 0.0 0.2 62020 2716 ? Ss Feb06 0:03 /usr/libexec/postfix/master
postfix 1586 0.0 0.2 62168 2436 ? S Feb06 0:00 qmgr -l -t fifo -u
root 1590 0.0 0.8 263516 8848 ? Ss Feb06 1:25 /usr/sbin/abrtd
root 1604 0.0 0.0 108292 944 ? S Feb06 0:47 /bin/bash /usr/sbin/ksmtuned
qpidd 1616 0.0 0.2 314868 3052 ? Ssl Feb06 0:27 /usr/sbin/qpidd --data-dir /var/lib/qpidd --daemon
root 1646 0.0 0.1 117072 1324 ? Ss Feb06 0:06 crond
root 1657 0.0 0.0 21360 156 ? Ss Feb06 0:00 /usr/sbin/atd
root 1668 0.0 1.0 268400 10880 ? Sl Feb06 0:01 libvirtd --daemon
root 1733 0.0 0.0 4020 504 tty2 Ss+ Feb06 0:00 /sbin/mingetty /dev/tty2
root 1737 0.0 0.0 4020 508 tty3 Ss+ Feb06 0:00 /sbin/mingetty /dev/tty3
root 1740 0.0 0.0 4020 504 tty4 Ss+ Feb06 0:00 /sbin/mingetty /dev/tty4
root 1742 0.0 0.0 4020 504 tty5 Ss+ Feb06 0:00 /sbin/mingetty /dev/tty5
root 1745 0.0 0.0 4020 500 tty6 Ss+ Feb06 0:00 /sbin/mingetty /dev/tty6
nobody 1761 0.0 0.0 12840 564 ? S Feb06 0:00 /usr/sbin/dnsmasq --strict-order --bind-interfaces --pid-file=/var/run/libvirt/network/default.pid --conf-file= --listen-address 192.168.122.1 --except-interface lo --dhcp-range 192.168.122.2,192.168.122.254 --dhcp-lease-max=253 --dhcp-no-override
root 1780 0.0 0.2 4111744 2592 ? Sl Feb06 0:00 /usr/sbin/console-kit-daemon --no-daemon
root 1886 0.0 0.0 25536 704 ? S<sl Feb06 0:01 auditd
root 14757 0.0 0.3 97484 3636 ? Ss 14:57 0:00 sshd: root@pts/0
root 14761 0.0 0.1 108296 1832 pts/0 Ss 14:57 0:00 -bash
root 14858 0.0 0.3 97484 3640 ? Ss 15:01 0:00 sshd: root@pts/1
root 14862 0.0 0.1 108424 1868 pts/1 Ss+ 15:01 0:00 -bash
root 14987 0.0 0.3 97484 3636 ? Ss 15:04 0:00 sshd: root@pts/2
root 14991 0.0 0.1 108296 1680 pts/2 Ss+ 15:04 0:00 -bash
root 15049 0.0 0.0 0 0 ? S 15:08 0:00 [kworker/1:0]
postfix 15321 0.0 0.2 62100 2656 ? S 15:31 0:00 pickup -l -t fifo -u
root 15401 0.1 0.0 0 0 ? S 15:38 0:01 [kworker/0:1]
root 15518 0.0 0.0 0 0 ? S 15:48 0:00 [kworker/0:0]
root 15556 0.0 0.0 0 0 ? S 15:50 0:00 [kworker/1:2]
root 15582 0.0 0.0 0 0 ? S 15:53 0:00 [kworker/0:2]
root 15727 0.0 0.0 0 0 ? S 16:03 0:00 [kworker/1:1]
root 15791 0.0 0.0 100864 456 ? S 16:07 0:00 sleep 60
root 15793 0.0 0.1 107968 1052 pts/0 R+ 16:07 0:00 ps aux
root 25845 0.0 0.0 0 0 ? S Feb07 0:00 [jbd2/sdb1-8]
root 25846 0.0 0.0 0 0 ? S< Feb07 0:00 [ext4-dio-unwrit]
sync_supers内核线程功能专一,用来同步操作系统当前挂载的各个文件系统的超级块数据,由于超级块对于文件系统的特殊性,所以这对保证文件系统的完整性至关重要。
在源文件mm/backing-dev.c内可以看到sync_supers内核线程的创建:
static int __init default_bdi_init(void)
{
int err;
sync_supers_tsk = kthread_run(bdi_sync_supers, NULL, "sync_supers");
BUG_ON(IS_ERR(sync_supers_tsk));
setup_timer(&sync_supers_timer, sync_supers_timer_fn, 0);
bdi_arm_supers_timer();
err = bdi_init(&default_backing_dev_info);
if (!err)
bdi_register(&default_backing_dev_info, NULL, "default");
err = bdi_init(&noop_backing_dev_info);
return err;
}
subsys_initcall(default_bdi_init);
void bdi_arm_supers_timer(void)
{
unsigned long next;
if (!dirty_writeback_interval)
return;
next = msecs_to_jiffies(dirty_writeback_interval * 10) + jiffies;
mod_timer(&sync_supers_timer, round_jiffies_up(next));
}
/*
* The interval between `kupdate'-style writebacks
*/
unsigned int dirty_writeback_interval = 5 * 100; /* centiseconds */
通过函数bdi_arm_supers_timer()设置定时器,默认每隔5秒唤醒sync_supers内核线程执行具体的操作函数sync_supers():
/*
* kupdated() used to do this. We cannot do it from the bdi_forker_thread()
* or we risk deadlocking on ->s_umount. The longer term solution would be
* to implement sync_supers_bdi() or similar and simply do it from the
* bdi writeback thread individually.
*/
static int bdi_sync_supers(void *unused)
{
set_user_nice(current, 0);
while (!kthread_should_stop()) {
set_current_state(TASK_INTERRUPTIBLE);
schedule();
/*
* Do this periodically, like kupdated() did before.
*/
sync_supers();
}
return 0;
}
/**
* sync_supers - helper for periodic superblock writeback
*
* Call the write_super method if present on all dirty superblocks in
* the system. This is for the periodic writeback used by most older
* filesystems. For data integrity superblock writeback use
* sync_filesystems() instead.
*
* Note: check the dirty flag before waiting, so we don't
* hold up the sync while mounting a device. (The newly
* mounted device won't need syncing.)
*/
void sync_supers(void)
{
struct super_block *sb, *p = NULL;
spin_lock(&sb_lock);
list_for_each_entry(sb, &super_blocks, s_list) {
if (list_empty(&sb->s_instances))
continue;
if (sb->s_op->write_super && sb->s_dirt) {
sb->s_count++;
spin_unlock(&sb_lock);
down_read(&sb->s_umount);
if (sb->s_root && sb->s_dirt)
sb->s_op->write_super(sb);
up_read(&sb->s_umount);
spin_lock(&sb_lock);
if (p)
__put_super(p);
p = sb;
}
}
if (p)
__put_super(p);
spin_unlock(&sb_lock);
}
sync_supers函数逻辑非常简单,遍历所有超级块(通过内核提供的全局链表super_blocks,这个全局链表保存了操作系统当前所有挂载文件系统的super_block实例),如果实例不存在则continue下一个,如果实例存在则接着判断同步回写函数write_super是否存在(有些文件系统,例如虚拟的文件系统或基于物理内存的文件系统并不需要进行同步操作,所以可以不提供回写函数write_super,典型示例就是/proc文件系统)以及超级块是否脏而需要进行同步。
各个需要进行超级块数据同步的文件系统都会提供适当的回写函数,比如ext4:
static void ext4_write_super(struct super_block *sb)
{
lock_super(sb);
ext4_commit_super(sb, 1);
unlock_super(sb);
}
static int ext4_commit_super(struct super_block *sb, int sync)
{
struct ext4_super_block *es = EXT4_SB(sb)->s_es;
struct buffer_head *sbh = EXT4_SB(sb)->s_sbh;
int error = 0;
if (!sbh)
return error;
if (buffer_write_io_error(sbh)) {
/*
* Oh, dear. A previous attempt to write the
* superblock failed. This could happen because the
* USB device was yanked out. Or it could happen to
* be a transient write error and maybe the block will
* be remapped. Nothing we can do but to retry the
* write and hope for the best.
*/
ext4_msg(sb, KERN_ERR, "previous I/O error to "
"superblock detected");
clear_buffer_write_io_error(sbh);
set_buffer_uptodate(sbh);
}
/*
* If the file system is mounted read-only, don't update the
* superblock write time. This avoids updating the superblock
* write time when we are mounting the root file system
* read/only but we need to replay the journal; at that point,
* for people who are east of GMT and who make their clock
* tick in localtime for Windows bug-for-bug compatibility,
* the clock is set in the future, and this will cause e2fsck
* to complain and force a full file system check.
*/
if (!(sb->s_flags & MS_RDONLY))
es->s_wtime = cpu_to_le32(get_seconds());
if (sb->s_bdev->bd_part)
es->s_kbytes_written =
cpu_to_le64(EXT4_SB(sb)->s_kbytes_written +
((part_stat_read(sb->s_bdev->bd_part, sectors[1]) -
EXT4_SB(sb)->s_sectors_written_start) >> 1));
else
es->s_kbytes_written =
cpu_to_le64(EXT4_SB(sb)->s_kbytes_written);
ext4_free_blocks_count_set(es, percpu_counter_sum_positive(
&EXT4_SB(sb)->s_freeblocks_counter));
es->s_free_inodes_count =
cpu_to_le32(percpu_counter_sum_positive(
&EXT4_SB(sb)->s_freeinodes_counter));
sb->s_dirt = 0;
BUFFER_TRACE(sbh, "marking dirty");
mark_buffer_dirty(sbh);
if (sync) {
error = sync_dirty_buffer(sbh);
if (error)
return error;
error = buffer_write_io_error(sbh);
if (error) {
ext4_msg(sb, KERN_ERR, "I/O error while writing "
"superblock");
clear_buffer_write_io_error(sbh);
set_buffer_uptodate(sbh);
}
}
return error;
}
int sync_dirty_buffer(struct buffer_head *bh)
{
return __sync_dirty_buffer(bh, WRITE_SYNC);
}
EXPORT_SYMBOL(sync_dirty_buffer);
转载请保留地址:http://lenky.info/2012/02/15/linux%e5%86%85%e6%a0%b8%e8%bf%9b%e7%a8%8b%e8%af%a6%e8%a7%a3%e4%b9%8b%e4%b8%80%ef%bc%9async_supers/ 或 http://lenky.info/?p=1095