Linux内核进程详解之一:sync_supers

来源:互联网 发布:天刀捏脸数据女 包子脸 编辑:程序博客网 时间:2024/04/27 22:29

先说下环境,CentOS 6.0/Linux kernel 2.6.38.8/X86-64,后面提到的代码也都来之kernel 2.6.38.8。这个环节下的进程列表具体如下所示,后续将有一系列的文章分析各个进程(主要是内核进程)的功能:

[root@localhost ~]# cat /etc/issueCentOS Linux release 6.0 (Final)Kernel \r on an \m[root@localhost ~]# uname -aLinux 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 auxUSER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMANDroot         1  0.0  0.1  19284  1368 ?        Ss   Feb06   0:02 /sbin/initroot         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 -droot       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 -droot       924  0.0  0.2  12356  2648 ?        S<   Feb06   0:00 /sbin/udevd -droot      1114  0.0  0.1 242492  1540 ?        Sl   Feb06   0:05 /sbin/rsyslogd -c 4root      1143  0.0  0.0   9104   428 ?        Ss   Feb06   1:04 irqbalancerpc       1162  0.0  0.0  18920   816 ?        Ss   Feb06   0:01 rpcbindroot      1176  0.0  0.0   6604   260 ?        Ss   Feb06   0:00 mdadm --monitor --scan -f --pid-file=/var/run/mdadm/mdadm.piddbus      1185  0.0  0.1  29964  1448 ?        Ssl  Feb06   0:00 dbus-daemon --systemroot      1196  0.0  0.3  95412  3468 ?        Ssl  Feb06   0:00 NetworkManager --pid-file=/var/run/NetworkManager/NetworkManager.pidroot      1202  0.0  0.1  55792  2000 ?        S    Feb06   0:00 /usr/sbin/modem-manageravahi     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 helperroot      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 eth3root      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.pidrpcuser   1236  0.0  0.1  23088  1124 ?        Ss   Feb06   0:00 rpc.statdroot      1251  0.0  0.0   4020   508 tty1     Ss+  Feb11   0:00 /sbin/mingetty /dev/tty1root      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.idmapdroot      1297  0.0  0.2 178584  2840 ?        Ss   Feb06   0:00 cupsd -C /etc/cups/cupsd.confroot      1322  0.0  0.0   4036   604 ?        Ss   Feb06   0:00 /usr/sbin/acpid68        1331  0.0  0.3  26184  3252 ?        Ss   Feb06   0:03 haldroot      1332  0.0  0.1  18068  1136 ?        S    Feb06   0:00 hald-runnerroot      1375  0.0  0.0  20184   832 ?        S    Feb06   0:00 hald-addon-input: Listening on /dev/input/event0 /dev/input/event1root      1376  0.0  0.0  20180   856 ?        S    Feb06   0:18 hald-addon-storage: no polling on /dev/fd0 because it is explicitly disabled68        1377  0.0  0.0  17760   988 ?        S    Feb06   0:00 hald-addon-acpi: listening on acpid socket /var/run/acpid.socketroot      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 pcscdroot      1418  0.0  0.3 381500  3368 ?        Ssl  Feb06   0:38 automount --pid-file /var/run/autofs.pidroot      1452  0.0  0.1  63804  1316 ?        Ss   Feb06   0:00 /usr/sbin/sshdroot      1478  0.0  0.0  22020   880 ?        Ss   Feb06   0:00 xinetd -stayalive -pidfile /var/run/xinetd.pidroot      1579  0.0  0.2  62020  2716 ?        Ss   Feb06   0:03 /usr/libexec/postfix/masterpostfix   1586  0.0  0.2  62168  2436 ?        S    Feb06   0:00 qmgr -l -t fifo -uroot      1590  0.0  0.8 263516  8848 ?        Ss   Feb06   1:25 /usr/sbin/abrtdroot      1604  0.0  0.0 108292   944 ?        S    Feb06   0:47 /bin/bash /usr/sbin/ksmtunedqpidd     1616  0.0  0.2 314868  3052 ?        Ssl  Feb06   0:27 /usr/sbin/qpidd --data-dir /var/lib/qpidd --daemonroot      1646  0.0  0.1 117072  1324 ?        Ss   Feb06   0:06 crondroot      1657  0.0  0.0  21360   156 ?        Ss   Feb06   0:00 /usr/sbin/atdroot      1668  0.0  1.0 268400 10880 ?        Sl   Feb06   0:01 libvirtd --daemonroot      1733  0.0  0.0   4020   504 tty2     Ss+  Feb06   0:00 /sbin/mingetty /dev/tty2root      1737  0.0  0.0   4020   508 tty3     Ss+  Feb06   0:00 /sbin/mingetty /dev/tty3root      1740  0.0  0.0   4020   504 tty4     Ss+  Feb06   0:00 /sbin/mingetty /dev/tty4root      1742  0.0  0.0   4020   504 tty5     Ss+  Feb06   0:00 /sbin/mingetty /dev/tty5root      1745  0.0  0.0   4020   500 tty6     Ss+  Feb06   0:00 /sbin/mingetty /dev/tty6nobody    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-overrideroot      1780  0.0  0.2 4111744 2592 ?        Sl   Feb06   0:00 /usr/sbin/console-kit-daemon --no-daemonroot      1886  0.0  0.0  25536   704 ?        S<sl Feb06   0:01 auditdroot     14757  0.0  0.3  97484  3636 ?        Ss   14:57   0:00 sshd: root@pts/0root     14761  0.0  0.1 108296  1832 pts/0    Ss   14:57   0:00 -bashroot     14858  0.0  0.3  97484  3640 ?        Ss   15:01   0:00 sshd: root@pts/1root     14862  0.0  0.1 108424  1868 pts/1    Ss+  15:01   0:00 -bashroot     14987  0.0  0.3  97484  3636 ?        Ss   15:04   0:00 sshd: root@pts/2root     14991  0.0  0.1 108296  1680 pts/2    Ss+  15:04   0:00 -bashroot     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 -uroot     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 60root     15793  0.0  0.1 107968  1052 pts/0    R+   16:07   0:00 ps auxroot     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));elsees->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