电玩城打鱼捕鱼-专业24小时上下分

简单介绍Linux,文件系统访问

六月 24th, 2019  |  电玩城捕鱼系统简介

sysfs 是 Linux 内核中设计较新的一种虚拟的基于内存的文件系统,它的作用与
proc 有些类似,但除了与 proc
相同的具有查看和设定内核参数功能之外,还有为 Linux
统一设备模型作为管理之用。相比于 proc 文件系统,使用 sysfs
导出内核数据的方式更为统一,并且组织的方式更好,它的设计从 proc
中吸取了很多教训。本文就 sysfs 的挂载点 /sys 目录结构、其与 Linux
统一设备模型的关系、常见属性文件的用法等方面对 sysfs
作入门介绍,并且就内核编程方面,以具体的例子来展示如何添加 sysfs 支持。

   proc/x:1/sched

本人对Linux系统很感兴趣,常见Linux sysfs
属性的功能Linux本身是这个操作系统的核心部分,也就是操作系统的内核。内核是完成那些最基本操作的程序,它负责其他程序如文本编辑器程序)的启动与终止、内存申请处理硬盘访问、网络连接管理等方面的工作。

sysfs 的历史,其与 proc 的关系?

  proc文件系统详解

使用 Linux sysfs 的关键就是掌握这些 sysfs 属性的用法,下面以一些常见的
sysfs 属性来展示它的用法;
使用设备(PCI)的 sysfs 属性文件以一份桌面系统上的视频卡为例,列举它对应的
kobject 上的属性文件的对应用途;一般来说,在 Linux
桌面上都有视频卡以支持 Xorg 软件包作为 XWindow 服务器来运行,因此先找到
Xorg 的进程号,查看这个进程所使用的所有文件注意查看这个进程属性需要 root
用户权限);
# ps xfa |grep Xorg
2001 tty1     Ss+    2:24      \_ /usr/bin/Xorg :0 -nr -verbose -auth
\
/var/run/gdm/auth-for-gdm-NPrkZK/database -nolisten tcp vt1
# lsof -nP -p 2001
Xorg    2001 root  mem    REG        8,3    617732     231033 \
/usr/lib/xorg/modules/drivers/sis_drv.so
[…]
Xorg    2001 root  mem    REG        0,0 134217728       5529 \
/sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/resource0
Xorg    2001 root  mem    REG        0,0    131072       5531 \
/sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/resource1
[…]
Xorg    2001 root    7u   REG        0,0       256       5504 \
/sys/devices/pci0000:00/0000:00:00.0/config
Xorg    2001 root    8u  unix 0xdbe66000       0t0       8756 socket
Xorg    2001 root    9u   REG        0,0       256       5528 \
/sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/config

sysfs 本身并不是一项很新的技术,但笔者发现,虽然 sysfs
从2003年诞生至今已有5年,但人们对 sysfs
依然缺乏了解;一个很重要的原因可能是缺乏文档, Linux
内核方面最重要的理论书籍“Linux 设备驱动第3版”和“理解 Linux
内核第2版”都诞生于2003年前后,并且从那以后尚未有再版过,其它一些重要文章则多对
sysfs 与 proc 相提并论且举例常常只有 proc,这导致了 sysfs
的很多重要概念至今仍鲜为人知,因此有必要对 sysfs
作更多介绍,这是写作本文的初衷。

Linux系统上的/proc目录是一种文件系统,即proc文件系统。与其它常见的文件系统不同的是,/proc是一种伪文件系统(也即虚拟文件系统),存储的是当前内核运行状态的一系列特殊文件,用户可以通过这些文件查看有关系统硬件及当前正在运行进程的信息,甚至可以通过更改其中某些文件来改变内核的运行状态。
大多数虚拟文件可以使用文件查看命令如cat、more或者less进行查看,有些文件信息表述的内容可以一目了然,但也有文件的信息却不怎么具有可读性。不过,这些可读性较差的文件在使用一些命令如apm、free、lspci或top查看时却可以有着不错的表现。

注意到此 Xorg 服务器是以内存映射 (mem) 的形式打开了
“/sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/resource0” 和
“/sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/resource1”
,同时以文件读写形式 (7u,9u) 打开了
“/sys/devices/pci0000:00/0000:00:00.0/config” 和
“/sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/config”
事实上, PCI 设备对应的 kobject 目录下的 config
正是代表PCI设备的“配置空间”,对于普通 PCI
(非PCI-E)设备而言,其配置空间大小一般是
256字节,这个空间可以使用十六进制工具 dump 出来,如下。(有关 PCI
设备本身的三种地址空间,请参考附录 LDD3)

sysfs 与 /sys

/proc/sched_debug
/proc/schedstat 总
/proc/pid/schedstat 分
/proc/pid/sched

# hexdump -C /sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/config
00000000  39 10 30 63 03 00 30 02  00 00 00 03 00 00 00 80 
|9.0c..0………|
00000010  08 00 00 d8 00 00 00 e1  01 d0 00 00 00 00 00 00 
|…………….|
00000020  00 00 00 00 00 00 00 00  00 00 00 00 19 10 30 1b 
|…………..0.|
00000030  00 00 00 00 40 00 00 00  00 00 00 00 00 00 00 00 
|[email protected]|
00000040  01 50 02 06 00 00 00 00  00 00 00 00 00 00 00 00 
|.P…………..|
00000050  02 00 30 00 0b 02 00 ff  00 00 00 00 00 00 00 00 
|..0………….|
00000060  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 
|…………….|
*
00000100 

sysfs 文件系统总是被挂载在 /sys
挂载点上。虽然在较早期的2.6内核系统上并没有规定 sysfs
的标准挂载位置,可以把 sysfs
挂载在任何位置,但较近的2.6内核修正了这一规则,要求 sysfs 总是挂载在
/sys 目录上;针对以前的 sysfs 挂载位置不固定或没有标准被挂载,有些程序从
/proc/mounts 中解析出 sysfs
是否被挂载以及具体的挂载点,这个步骤现在已经不需要了。请参考附录给出的
sysfs-rules.txt 文件链接。

[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

这个空间正好是 256字节大小,熟悉 PCI 的人们还可以知道,从 PCI
配置空间可以读到有关此 PCI 设备的很多有用信息,如厂商代码,设备代码,IRQ
号码等;前四个字节 0x39 0x10 0x30 0x63 就是按小端(little
endian)存放的2个短整数,因此其 PCI 厂商号码和 PCI 设备号码分别是 0x1039
和 0x6330
# lspci -v -d 1039:6330
01:00.0 VGA compatible controller: Silicon Integrated Systems [SiS]
661/741/760 PCI/AGP \
or 662/761Gx PCIE VGA Display Adapter (prog-if 00 [VGA controller])
Subsystem: Elitegroup Computer Systems Device 1b30
Flags: 66MHz, medium devsel
BIST result: 00
Memory at d8000000 (32-bit, prefetchable) [size=128M]
Memory at e1000000 (32-bit, non-prefetchable) [size=128K]
I/O ports at d000 [size=128]
Capabilities: [40] Power Management version 2
Capabilities: [50] AGP version 3.0 

sysfs 与 proc

 

在 PCI 设备上除了有 config 是配置空间对用户的接口以外,还有
resource{0,1,2,…} 是资源空间,对应着 PCI 设备的可映射内存空间;此外
PCI 设备还提供了很多接口,全部列表如下:

sysfs 与 proc 相比有很多优点,最重要的莫过于设计上的清晰。一个 proc
虚拟文件可能有内部格式,如 /proc/scsi/scsi
,它是可读可写的,(其文件权限被错误地标记为了 0444
!,这是内核的一个BUG),并且读写格式不一样,代表不同的操作,应用程序中读到了这个文件的内容一般还需要进行字符串解析,而在写入时需要先用字符串格式化按指定的格式写入字符串进行操作;相比而言,
sysfs 的设计原则是一个属性文件只做一件事情, sysfs
属性文件一般只有一个值,直接读取或写入。整个 /proc/scsi
目录在2.6内核中已被标记为过时(LEGACY),它的功能已经被相应的 /sys
属性文件所完全取代。新设计的内核机制应该尽量使用 sysfs 机制,而将 proc
保留给纯净的“进程文件系统”。

 

# ls -lU /sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/
总计 0
-rw-r–r– 1 root root      4096 12-09 00:28 uevent
-r–r–r– 1 root root      4096 12-09 00:27 resource
-r–r–r– 1 root root      4096 12-09 00:27 vendor
-r–r–r– 1 root root      4096 12-09 00:27 device
-r–r–r– 1 root root      4096 12-09 00:28 subsystem_vendor
-r–r–r– 1 root root      4096 12-09 00:28 subsystem_device
-r–r–r– 1 root root      4096 12-09 00:27 class
-r–r–r– 1 root root      4096 12-09 00:27 irq
-r–r–r– 1 root root      4096 12-09 00:28 local_cpus
-r–r–r– 1 root root      4096 12-09 00:28 local_cpulist
-r–r–r– 1 root root      4096 12-09 00:28 modalias
-rw——- 1 root root      4096 12-09 00:28 enable
-rw-r–r– 1 root root      4096 12-09 00:28 broken_parity_status
-rw-r–r– 1 root root      4096 12-09 00:28 msi_bus
lrwxrwxrwx 1 root root         0 12-09 00:28 subsystem ->
../../../../bus/pci
drwxr-xr-x 2 root root         0 12-09 00:28 power
-rw-r–r– 1 root root       256 12-08 23:03 config
-rw——- 1 root root 134217728 12-08 23:03 resource0
-rw——- 1 root root 134217728 12-09 00:28 resource0_wc
-rw——- 1 root root    131072 12-08 23:03 resource1
-rw——- 1 root root       128 12-09 00:28 resource2
-r——– 1 root root         0 12-09 00:28 rom 

初识 /sys

   sysfs

可以看到很多其它属性文件,这些属性文件的权限位也都是正确的,有 w
权限位的才是可以写入。其中大小为
4096字节的属性一般是纯文本描述的属性,可以直接 cat 读出和用 echo
字符串的方法写入;其它非 4096字节大小的一般是二进制属性,类似于上面的
config 属性文件;关于纯文本属性和二进制属性,在下文 编程实践:添加Linux
sysfs支持 一节会进一步说明。

清单 1. 与 /sys
文件系统的一次交互(视内核版本号和外接设备的不同,在您的系统上执行这些命令的结果可能与此有所不同)

  多重操作系统

从 vendor, device, subsystem_vendor, subsystem_device, class, resource
这些只读属性上分别可以读到此 PCI
设备的厂商号、设备号、子系统厂商号、子系统设备号、PCI类别、资源表等,这些都是相应
PCI 设备的属性,其实就是直接从 config
二进制文件读出来,按照配置空间的格式读出这些号码;
使用 enable 这个可写属性可以禁用或启用这个 PCI
设备,设备的过程很直观,写入1代表启用,写入0则代表禁用;
subsystem 和 driver 符号链接文件分别指向对应的 sysfs 位置;(这里缺少
driver 符号链接说明这个设备当前未使用内核级的驱动程序)
resource0, resource0_wc, resource1, resource2 等是从”PCI
配置空间”解析出来的资源定义段落分别生成的,它们是 PCI 总线驱动在 PCI
设备初始化阶段加上去的,都是二进制属性,但没有实现读写接口,只支持 mmap
内存映射接口,尝试进行读写会提示 IO 错误,其中 _wc 后缀表示
“合并式写入(write combined)”
,它们用于作应用程序的内存映射,就可以访问对应的 PCI
设备上相应的内存资源段落;
有了 PCI 核心对 Linux sysfs
的完善支持,每个设备甚至不用单独的驱动程序,如这里的 “0000:01:00.0”
不需要一个内核级的驱动程序,有了 PCI
核心对该设备的配置空间发现机制,可以自动发现它的各个不同段落的资源属性,在
Xorg 应用程序中可以直接以 “/usr/lib/xorg/modules/drivers/sis_drv.so”
这个用户空间的驱动程序对其进行映射,就可以直接操作此视频卡了;有了这一个
PCI 设备的示例可以知道,有了一个 PCI 设备的 /sys/devices/
设备对象,去访问它的各项属性和设置属性都非常简单。以上介绍Linux
sysfs桌面系统应用。

标签:,

Your Comments

近期评论

    功能


    网站地图xml地图