http://blog.chinaunix.net/uid-1835494-id-3070465.html proc/x:1/sched
http://bbs.chinaunix.net/thread-2002769-1-1.html proc文件系统详解
Linux系统上的/proc目录是一种文件系统,即proc文件系统。与其它常见的文件系统不同的是,/proc是一种伪文件系统(也即虚拟文件系统),存储的是当前内核运行状态的一系列特殊文件,用户可以通过这些文件查看有关系统硬件及当前正在运行进程的信息,甚至可以通过更改其中某些文件来改变内核的运行状态。
大多数虚拟文件可以使用文件查看命令如cat、more或者less进行查看,有些文件信息表述的内容可以一目了然,但也有文件的信息却不怎么具有可读性。不过,这些可读性较差的文件在使用一些命令如apm、free、lspci或top查看时却可以有着不错的表现。
/proc/sched_debug
/proc/schedstat 总
/proc/pid/schedstat 分
/proc/pid/sched
[root@250-shiyan 27227]# cat sched mfsmount (27227, #threads: 13) --------------------------------------------------------- se.exec_start : 4298337843.907125 se.vruntime : 4714787.554887 se.sum_exec_runtime : 23.716516 se.wait_start : 0.000000 se.sleep_start : 4298337843.907125 se.block_start : 0.000000 se.sleep_max : 1.655287 se.block_max : 0.000000 se.exec_max : 1.003137 se.slice_max : 3.550532 se.wait_max : 0.310097 se.wait_sum : 0.745722 se.wait_count : 11 se.iowait_sum : 494.469927 se.iowait_count : 131 sched_info.bkl_count : 1 se.nr_migrations : 0 se.nr_migrations_cold : 0 se.nr_failed_migrations_affine : 0 se.nr_failed_migrations_running : 0 se.nr_failed_migrations_hot : 0 se.nr_forced_migrations : 0 se.nr_wakeups : 1 se.nr_wakeups_sync : 1 se.nr_wakeups_migrate : 0 se.nr_wakeups_local : 1 se.nr_wakeups_remote : 0 se.nr_wakeups_affine : 0 se.nr_wakeups_affine_attempts : 0 se.nr_wakeups_passive : 0 se.nr_wakeups_idle : 0 avg_atom : 2.371651 avg_per_cpu : 0.000001 nr_switches : 10 nr_voluntary_switches : 2 nr_involuntary_switches : 8 se.load.weight : 71755 policy : 0 prio : 101 clock-delta : 135 [root@250-shiyan 27227]# cat schedstat 23716516 745722 10 [root@250-shiyan 27227]# cat /proc/schedstat version 15 timestamp 9130051710 cpu0 0 0 90294274 19486189 49453373 49453373 5270546755145 379982355396 70804217 [root@250-shiyan 27227]# cat /proc/sched_debug Sched Debug Version: v0.09, 2.6.32-431.el6.x86_64 #1 now at 4835548701.686494 msecs .jiffies : 9130215997 .sysctl_sched_latency : 5.000000 .sysctl_sched_min_granularity : 1.000000 .sysctl_sched_wakeup_granularity : 1.000000 .sysctl_sched_child_runs_first : 0.000000 .sysctl_sched_features : 3183 .sysctl_sched_tunable_scaling : 1 (logaritmic) cpu#0, 3092.974 MHz .nr_running : 1 .load : 1024 .nr_switches : 90292999 .nr_load_updates : 21243167 .nr_uninterruptible : 0 .next_balance : 9130.216230 .curr->pid : 1037 .clock : 4834502548.387724 .cpu_load[0] : 1024 .cpu_load[1] : 512 .cpu_load[2] : 256 .cpu_load[3] : 128 .cpu_load[4] : 64 .yld_count : 0 .sched_switch : 0 .sched_count : 90296954 .sched_goidle : 19487350 .avg_idle : 994034 .ttwu_count : 49454858 .ttwu_local : 49454858 .bkl_count : 706 cfs_rq[0]:/ .exec_clock : 5263171.784834 .MIN_vruntime : 0.000001 .min_vruntime : 5035599.468468 .max_vruntime : 0.000001 .spread : 0.000000 .spread0 : 0.000000 .nr_spread_over : 7543 .nr_running : 1 .load : 1024 .load_avg : 0.000000 .load_period : 0.000000 .load_contrib : 0 .load_tg : 0 rt_rq[0]:/ .rt_nr_running : 0 .rt_throttled : 0 .rt_time : 0.000000 .rt_runtime : 950.000000 runnable tasks: task PID tree-key switches prio exec-runtime sum-exec sum-sleep ---------------------------------------------------------------------------------------------------------- R cat 1037 5035599.468468 1 120 5035599.468468 0.470952 0.000000 / [root@250-shiyan 27227]# /proc/pid/schedstat /proc/pid/sched /proc/schedstat /proc/sched_debug proc的调度相关字段解释 2.6.32内核 CONFIG_SCHED_DEBUG (需要配置CONFIG_SCHEDSTAT才能显示更多信息) /proc/pid/sched 显示信息解释如下: ata/2 (111, #threads: 1) --------------------------------------------------------- se.exec_start : 1159.482823 //此进程最近被调度到的开始执行时刻 ns se.vruntime : -1.044234 //虚拟运行时间,cfs调度用 se.sum_exec_runtime : 0.000000 //累计运行时间 se.avg_overlap : 0.000000 se.avg_wakeup : 3.617187 //当前进程最近一次调用try_to_wake_up为止的单次执行时间 se.avg_running : 0.000000 //平均单次执行时间 //以下开始需要同时配置CONFIG_SCHEDSTATS才能显示 se.wait_start : 0.000000 //最近一次当前进程被入队的时刻 cfs使用 se.sleep_start : 1159.482823 //此进程最近一次被从队列里取出,并被置S状态的时刻 se.block_start : 0.000000 //此进程最近一次被从队列里取出,并被置D状态的时刻 se.sleep_max : 0.000000 //最长处于S状态时间 se.block_max : 0.482651 //最长处于D状态时间 se.exec_max : 0.000000 //最长单次执行时间 se.slice_max : 0.000000 //曾经获得时间片的最长时间 (当cpu load过高时开始计算) se.wait_max : 0.000000 //最长在就绪队列里的等待时间 se.wait_sum : 0.000000 //累计在就绪队列里的等待时间 se.wait_count : 2 //累计等待次数 (被出队的次数) cfs使用,当被选中做下一个待运行进程时(set_next_entity),等待结束 se.iowait_sum : 0.000000 //io等待时间 se.iowait_count : 0 //io等待次数 io_schedule调用次数 sched_info.bkl_count : 0 //此进程大内核锁调用次数 se.nr_migrations : 2 //需要迁移当前进程到其他cpu时累加此字段 se.nr_migrations_cold : 0 //2.6.32 代码里赋值都是0 se.nr_failed_migrations_affine : 0 //进程设置了cpu亲和,进程迁移时检查失败的次数 se.nr_failed_migrations_running : 0 //当前进程出入R,不运行迁移的次数 se.nr_failed_migrations_hot : 0 //当前进程因为是cache hot导致迁移失败的次数 se.nr_forced_migrations : 0 //在当前进程cache hot下,由于负载均衡尝试多次失败,强行进行迁移的次数 se.nr_forced2_migrations : 1 //在当前进程是cache hot下,设置此进程进行迁移的次数 se.nr_wakeups : 1 // 被唤醒的累计次数 se.nr_wakeups_sync : 0 // 同步唤醒次数,即a唤醒b,a立刻睡眠,b被唤醒的次数 /* waker goes to sleep after wakup */ se.nr_wakeups_migrate : 0 //被唤醒得到调度的当前cpu,不是之前睡眠的cpu的次数 se.nr_wakeups_local : 0 //被本地唤醒的次数 se.nr_wakeups_remote : 1 //其他唤醒累计次数 se.nr_wakeups_affine : 0 //考虑了任务的cache亲和性的唤醒次数 se.nr_wakeups_affine_attempts : 0 //尝试进行考虑了任务的cache亲和性的唤醒次数 se.nr_wakeups_passive : 0 //2.6.32 代码里赋值都是0 se.nr_wakeups_idle : 0 //2.6.32 代码里赋值都是0 avg_atom : 0.000000 //本进程平均切换耗时 avg_per_cpu : 0.000000 //如果本进程曾经被推或者拉到其他cpu上,则计算每个cpu上的平均耗时 nr_switches : 2 //主动切换和被动切换的累计次数 nr_voluntary_switches : 2 //主动切换次数 nr_involuntary_switches : 0 //被动切换次数 se.load.weight : 1024 //权重,和负载均衡有关 policy : 0 //进程属性,0为非实时 #define SCHED_NORMAL 0 #define SCHED_FIFO 1 #define SCHED_RR 2 #define SCHED_BATCH 3 #define SCHED_IDLE 5 prio : 120 //优先级 clock-delta : 165 //测试用 /proc/sched_debug 此为cpu15运行队列的调度信息: cpu#15, 1595.968 MHz .nr_running : 0 //运行队列里处于就绪态进程的数目 .load : 0 //当前cpu负载 .nr_switches : 120820818 //切换累计次数 .nr_load_updates : 674238115 //cpu权重更新的次数,和负载均衡有关 .nr_uninterruptible : -30 .next_balance : 8012.054504 //下次执行定时负载均衡的时间 .curr->pid : 0 //当前运行进程 .clock : 3717386659.081997 //当前cpu运行队列时刻 .cpu_load[0] : 0 //以下为cpu历史负载数组 .cpu_load[1] : 0 .cpu_load[2] : 0 .cpu_load[3] : 0 .cpu_load[4] : 0 //以下开始需要同时配置CONFIG_SCHEDSTATS才记录 .yld_count : 8236 //调yield的次数 .sched_switch : 0 .sched_count : 122061248 //调用schedule的次数,>=nr_switches .sched_goidle : 30689623 //切换到idle进程的次数 .avg_idle : 1000000 //cpu处于idle的平均时间 .ttwu_count : 46238267 //此cpu try_to_wake_up唤醒进程的次数 .ttwu_local : 30988951 //本地唤醒的次数,即进程睡眠前所在cpu为当前cpu .bkl_count : 2090 //此cpu上大内核锁调用次数 cfs_rq[15]:/ .exec_clock : 545099081.498339 //非实时线程得到调度的累计时间 .MIN_vruntime : 0.000001 //当前cfs 运行队列里虚拟时间最小的那个进程的vtime .min_vruntime : 770437019.732761 //当前cfs 运行队列虚拟时间下限,当处于rb树最左边进程运行虚拟时间,减去此值大于一个阈值后抢占当前进程 .max_vruntime : 0.000001 // 2.6.32里没有找到这个字段 .spread : 0.000000 .spread0 : 407973445.279093 //cpu0上的min_vruntime与当前cpu的min_vruntime差值 .nr_running : 0 //当前cpu非实时进程在就绪队列中的个数 .load : 0 //非实时进程负载 .nr_spread_over : 6811 //当前cpu中,长时间非实时进程由一个进程占有的次数 s64 d = se->vruntime - cfs_rq->min_vruntime; if (d > 3*sysctl_sched_latency) schedstat_inc(cfs_rq, nr_spread_over); .shares : 0 rt_rq[15]:/ .rt_nr_running : 0 //处于就绪队列的实时进程个数 .rt_throttled : 0 //是否限制实时进程的带宽运行时间,实时进程是否需要让出cpu .rt_time : 0.000000 //做实时进程带宽分析用 .rt_runtime : 950.000000 //做实时进程带宽分析用 另外,还有一个: /proc/schedstat 字段详细解释文档在内核目录的: documentation/scheduler/sched-stats.txt
http://blog.chinaunix.net/uid-27411029-id-3522299.html sysfs
http://www.iteedu.com/os/grub/grubdiary/1.php 多重操作系统
Debugfs文件系统目的是为开发人员提供更多内核数据,方便调试内容. 我们知道/proc文件系统关注的是进程信息,/sysfs关注是one-value-per-file策略集,而Debugfs文件系统没有如此多限制,可是任何内核要输出的信息。
内核中有三个常用的伪文件系统:procfs,debugfs和sysfs。
procfs — The proc filesystem is a pseudo-filesystem which provides an interface to kernel data structures.
sysfs — The filesystem for exporting kernel objects.
debugfs — Debugfs exists as a simple way for kernel developers to make information available to user space.
它们都用于Linux内核和用户空间的数据交换,但是适用的场景有所差异:
procfs 历史最早,最初就是用来跟内核交互的唯一方式,用来获取处理器、内存、设备驱动、进程等各种信息。
sysfs 跟 kobject 框架紧密联系,而 kobject 是为设备驱动模型而存在的,所以 sysfs 是为设备驱动服务的。
debugfs 从名字来看就是为debug而生,所以更加灵活。
它们仨的挂载方式类似,做个实验:
标准形式
mount -t type device dir
Debugfs没有物理设备,其挂载方式:
mount -t debugfs none /sys/kernel/debug
这样后,用df -a可以看到filesystem列为none的都是无物理设备即虚拟文件系统的挂载方式
$ sudo mkdir /tmp/{proc,sys,debug}
$ sudo mount -t proc none|nonedev|任意名字都可以 /tmp/proc/
$ sudo mount -t sys nondev /tmp/sys/
$ sudo mount -t debugfs nondev /tmp/debug/
不过,默认情况下,它们分别挂载在/proc,/sys/,/sys/kernel/debug/。
通过比较发现,上述三个文件系统的 API 用法类似,而其中 debugfs 和 procfs 几乎有相同的参数,用的主要结构体是 struct file_operations,蛮多操作可以用 seq_* 家族的函数来实现。而 sysfs 则用到比较简单一些的 struct global_attr 结构体。对于提供给用户空间的节点,都可以轻松实现读写操作。
在创建目录方面,debugfs 和 procfs 类似,且比较简单。而 sysfs 要创建一级目录,需要先创建一个 kobject 对象。
为了简化设备模型依据总线创建的访问节点路径,sysfs 提供了API用于创建更简易的符号链接,可以创建到自己指定的目录下,也可以用设备类(Class)提供的API创建到设备类所属的目录下。
对于 sysfs,由于 kobject 与 device 的一对一依存关系,也可以直接用 device_create_file 来创建节点。
http://www.ibm.com/developerworks/cn/linux/l-cn-sysfs/#sysfs-rules.txt
是 Linux 内核中设计较新的一种虚拟的基于内存的文件系统,它的作用与 proc 有些类似,但除了与 proc
相同的具有查看和设定内核参数功能之外,还有为 Linux 统一设备模型作为管理之用。相比于 proc 文件系统,使用 sysfs
导出内核数据的方式更为统一,并且组织的方式更好,它的设计从 proc 中吸取了很多教训。本文就 sysfs 的挂载点 /sys 目录结构、其与
Linux 统一设备模型的关系、常见属性文件的用法等方面对 sysfs 作入门介绍,并且就内核编程方面,以具体的例子来展示如何添加 sysfs
支持。
sysfs 本身并不是一项很新的技术,但笔者发现,虽然 sysfs 从2003年诞生至今已有5年,但人们对 sysfs
依然缺乏了解;一个很重要的原因可能是缺乏文档, Linux 内核方面最重要的理论书籍“Linux 设备驱动第3版”和“理解 Linux
内核第2版”都诞生于2003年前后,并且从那以后尚未有再版过,其它一些重要文章则多对 sysfs 与 proc 相提并论且举例常常只有
proc,这导致了 sysfs 的很多重要概念至今仍鲜为人知,因此有必要对 sysfs 作更多介绍,这是写作本文的初衷。
sysfs文件系统总是被挂载在 /sys 挂载点上。虽然在较早期的2.6内核系统上并没有规定 sysfs 的标准挂载位置,可以把 sysfs
挂载在任何位置,但较近的2.6内核修正了这一规则,要求 sysfs 总是挂载在 /sys 目录上;针对以前的 sysfs
挂载位置不固定或没有标准被挂载,有些程序从 /proc/mounts 中解析出 sysfs
是否被挂载以及具体的挂载点,这个步骤现在已经不需要了。
sysfs 与 proc 相比有很多优点,最重要的莫过于设计上的清晰。一个 proc 虚拟文件可能有内部格式,如 /proc/scsi/scsi,它是可读可写的,(其文件权限被错误地标记为了 0444!,这是内核的一个BUG),并且读写格式不一样,代表不同的操作,应用程序中读到了这个文件的内容一般还需要进行字符串解析,而在写入时需要先用字符串
格式化按指定的格式写入字符串进行操作;相比而言, sysfs 的设计原则是一个属性文件只做一件事情, sysfs
属性文件一般只有一个值,直接读取或写入。整个 /proc/scsi 目录在2.6内核中已被标记为过时(LEGACY),它的功能已经被相应的 /sys 属性文件所完全取代。新设计的内核机制应该尽量使用 sysfs 机制,而将 proc 保留给纯净的“进程文件系统”。
可以看到在 /sys 目录下有 block, bus, class, dev, devices, firmware, fs, kernel, module, power这些子目录,
在 /sys/devices下是所有设备的真实对象,包括如视频卡和以太网卡等真实的设备,也包括 ACPI 等不那么显而易见的真实设备、还有 tty, bonding等纯粹虚拟的设备;在其它目录如 class, bus 等中则在分类的目录中含有大量对 devices 中真实对象引用的符号链接文件;
/sys/devices这是内核对系统中所有设备的分层次表达模型,也是 /sys 文件系统管理设备的最重要的目录结构
/sys/dev这个目录下维护一个按字符设备和块设备的主次号码 (major:minor)链接到真实的设备(/sys/devices下)的符号链接文件,它是在内核 2.6.26 首次引入
/sys/bus这是内核设备按总线类型分层放置的目录结构,devices 中的所有设备都是连接于某种总线之下,在这里的每一种具体总线之下可以找到每一个具体设备的符号链接,它也是构成 Linux 统一设备模型的一部分
/sys/class这是按照设备功能分类的设备模型,如系统所有输入设备都会出现在 /sys/class/input 之下,而不论它们是以何种总线连接到系统。它也是构成 Linux 统一设备模型的一部分
/sys/block这里是系统中当前所有的块设备所在,按照功能来说放置在 /sys/class 之下会更合适,但只是由于历史遗留因素而一直存在于/sys/block, 但从 2.6.22 开始就已标记为过时,只有在打开了 CONFIG_SYSFS_DEPRECATED配置下编译才会有这个目录的存在,并且在 2.6.26 内核中已正式移到 /sys/class/block, 旧的接口 /sys/block为了向后兼容保留存在,但其中的内容已经变为指向它们在 /sys/devices/ 中真实设备的符号链接文件
/sys/firmware这里是系统加载固件机制的对用户空间的接口,关于固件有专用于固件加载的一套API
/sys/fs这里按照设计是用于描述系统中所有文件系统,包括文件系统本身和按文件系统分类存放的已挂载点,但目前只有 fuse,gfs2 等少数文件系统支持sysfs 接口,一些传统的虚拟文件系统(VFS)层次控制参数仍然在 sysctl (/proc/sys/fs) 接口中
/sys/kernel这里是内核所有可调整参数的位置,目前只有 uevent_helper, kexec_loaded, mm, 和新式的 slab 分配器等几项较新的设计在使用它,其它内核可调整参数仍然位于 sysctl (/proc/sys/kernel) 接口中
/sys/module这里有系统中所有模块的信息,不论这些模块是以内联(inlined)方式编译到内核映像文件(vmlinuz)中还是编译为外部模块(ko文件),都可能会出现在 /sys/module 中
编译为外部模块(ko文件)在加载后会出现对应的 /sys/module//, 并且在这个目录下会出现一些属性文件和属性目录来表示此外部模块的一些信息,如版本号、加载状态、所提供的驱动程序等;
编译为内联方式的模块则只在当它有非0属性的模块参数时会出现对应的 /sys/module/, 这些模块的可用参数会出现在 /sys/modules//parameters/ 中,
如 /sys/module/printk/parameters/time 这个可读写参数控制着内联模块 printk 在打印内核消息时是否加上时间前缀;
所有内联模块的参数也可以由
".="
的形式写在内核启动参数上,如启动内核时加上参数 "printk.time=1" 与向
"/sys/module/printk/parameters/time" 写入1的效果相同;
没有非0属性参数的内联模块不会出现于此。
/sys/power这里是系统中电源选项,这个目录下有几个属性文件可以用于控制整个机器的电源状态,如可以向其中写入控制命令让机器关机、重启等。 /sys/slab (对应 2.6.23 内核,在 2.6.24 以后移至 /sys/kernel/slab)从2.6.23
开始可以选择 SLAB 内存分配器的实现,并且新的 SLUB(Unqueued Slab Allocator)被设置为缺省值;如果编译了此选项,在 /sys 下就会出现 /sys/slab ,里面有每一个 kmem_cache
结构体的可调整参数。对应于旧的 SLAB 内存分配器下的 /proc/slabinfo 动态调整接口,新式的/sys/kernel/slab/ 接口中的各项信息和可调整项显得更为清晰。