Solaris内核目录( 六 )


| | pr_lookup_function-----------------------
程| | | pr_lookup_piddir() |
| | Construct full path name,-----------------------
| | looking up each element | pr_lookup_lwpdir() |
| | in the path.-----------------------prgetnode()
| | | pr_lookup_objectdir() | /
| |-----------------------/
| | | | |/
| | ...... | ......
| | |
|-------------------------------------------
| VOP_OPEN() -> propen()
V

图4. 打开一个procfs文件时的基本流程

--------------------------------------------------------------------------

图4中流程从应用程序开始,针对一个procfs文件做open(2)系统调用 。进入
vnode内核层(vn_open()),完成一系列查找以构建目标/proc文件的完整路径名 。通过vnode层的宏进入文件系统相关操作 。在上面的图例中,VOP_LOOKUP()解析成procfs的pr_lookup()函数 。pr_lookup()完成访问权限检查并根据目录文件类型调用相应的procfs函数,比如pr_lookup_piddir()针对/proc/目录进行查找工作 。每个pr_lookup_xxx()目录查找函数完成某些目录类型相关的工作,然后调用prgetnode()获取prnode 。

prgetnode()为/proc文件创建prnode(其中内嵌了vnode),并初始化prnode和vnode结构的某些成员 。对于/proc/和/proc//lwp/,还会创建
prcommon结构,挂接到prnode结构上,并部分初始化 。注意,对于/proc下的目录文件,为了正确反映目录文件类型,vnode类型从VPROC(初始设置)改变成VDIR,表示这是一个procfs目录文件 。

一旦完整路径名构建完毕,通过VOP_OPEN()宏进入文件系统相关的open()函数 。procfs的propen()函数完成prnode和vnode结构的其余初始化以及针对特定文件类型的访问测试工作 。一旦propen()完成,控制返回到vn_open() 。最终一个代表procfs文件的文件句柄返回给主调者 。

读取一个procfs数据文件(和目录文件相对)类型打开流程,read()系统调用最终
进入procfs的prread()函数 。procfs实现为每个可用文件对象(不同的数据结构)定义了一个数据文件对象相关的读函数,比如pr_read_psinfo()、pr_read_pstatus()、
pr_read_lwpsinfo()等等 。这些函数指针构成一个数组,以文件类型做下标进行索引,prread()最终调用了它们 。整个流程类似lookup操作 。

Solaris 7 的procfs实现是基于64-bit内核的,但是同时支持32-bit和64-bit应
用,在/proc层次结构上提供了32-bit版本的可用数据文件 。在64-bit Solaris 7内核中,描述每个/proc文件对象内容的数据结构同时拥有32-bit版本和64-bit版本,比如lwpstatus和lwpstatus32、psinfo和psinfo32等等 。针对每个32-bit版本的结构定义,相应pr_read_xxx()函数做了支持32-bit数据模式的编码 。

procfs用户并不会意识到64-bit内核中多种数据模式实现 。调用到prread()时,
它会检查主调者使用的数据模式,并激活相应数据模式的函数 。这里有一个例外,读取/proc//as(地址空间)文件时,主调者必须拥有与/proc//as文件一样的
数据模式,换句话说,64-bit内核中32-bit应用程序可以读取另外一个32-bit进程的AS(地址空间)文件,但是不能读取另外一个64-bit进程的AS文件 。

scz注:我觉得这里倒不如说,/proc//as本身是拥有单一数据模式的,要么
32-bit,要么64-bit,不可得兼 。而其他/proc数据文件对象可能同时支持两
种数据模式 。

pr_read_xxxx()函数从内核里读取相关数据,然后写入相应的procfs数据结构,最终返回给主调者 。例如,pr_read_psinfo()从目标进程的proc结构、cred结构和as结构读取数据,写入psinfo结构中相应成员 。访问内核数据时靠proc结构的p_lockp成员确定的互斥锁进行同步,这样确保每次只有一个客户线程能够访问per-process或per-lwp内核数据 。

很少需要写访问procfs文件 。姑且不考虑写目录创建数据文件,典型的写操作就

推荐阅读