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
- Linux内核进程详解之一:sync_supers
- linux内核进程详解
- linux内核之进程管理详解
- linux内核笔记之一
- 《深入理解linux内核》读书笔记 (二): 进程task_struct详解
- Linux内核进程详解之二:bdi-default
- Linux内核进程详解之三:flush-x:y
- (进程篇 详解 中)--深入理解linux内核
- Linux 内核中RAID5源码详解之守护进程raid5d
- 读书笔记----进程管理(2.6内核)之一
- linux内核进程
- Linux内核进程切换
- Linux进程内核栈
- linux 内核进程 线程
- Linux内核进程调度
- Linux进程内核栈
- Linux内核-进程
- Linux内核-进程退出
- linux常用命令及杂项
- 代码 简单
- .NET/C#中的匿名类型
- Neo4j使用时的一些体会
- java.lang.ClassCastException: java.lang.String cannot be cast to java.sql.Clob
- Linux内核进程详解之一:sync_supers
- 代码1
- 音视频通讯中window平台的本地视频显示
- linux 下route命令
- 字符串转换成JSON的三种方式
- 王爽 汇编语言 实验九
- 获得刚插入的数据的 ID
- 基于UPD78F0511的单相电表解决方案
- JSP Servlet里相对路径问题的解决