procfs是通过动态可加载内核模块的方式实现的 。系统启动时自动加载
/kernel/fs/procfs,/etc/vfstab文件中存在缺省/proc入口,系统启动过程中/proc将被mount上来 。mount过程中将调用procfs的prinit()和prmount()函数,它们为procfs初始化vfs(虚拟文件系统)结构,为根目录/proc/创建并初始化一个vnode 。vfs结构定义在/usr/include/sys/vfs.h文件中,vnode结构定义在/usr/include/sys/vnode.h文件中 。
/proc目录所涉及的内核内存空间绝大部分是动态分配的 。但是系统支持的最大
进程数(可以通过/etc/system的max_nprocs参数配置)决定了/proc下子目录插槽数目,这个是静态分配初始化的 。内核变量procdir是一个指向procent结构数组的指针,每个procent结构对应一个procfs目录入口,procent结构数组元素数量源自系统启动时初始化的v.v_proc变量的值,也就是系统支持的最大进程数 。
scz注:在Solaris Kernel Hacking过程中,应该习惯使用下面这两种命令,很多未公开内核数据结构在/usr/include下的头文件中有相当体现,然后利用nm命
令确认当前内核正在使用这些内核数据结构或者内核函数 。
# find /usr/include -name "*" | xargs grep -i "procdir"
# /usr/ccs/bin/nm -x /dev/ksyms | grep -i "|procdir"
[1433] |0x0000104570d0|0x000000000008|OBJT |LOCL |0 |ABS |procdir
# /usr/ccs/bin/nm -x /dev/ksyms | grep -i "|v$"
[8741] |0x00001041e1f4|0x00000000003c|OBJT |GLOB |0 |ABS |v
[6634] |0x00001041e1f4|0x00000000003c|OBJT |GLOB |0 |ABS |v
每个procent结构中pe_proc成员指向对应的proc结构,pe_next成员指向数组的下一个元素(scz:不但是数组,也形成链表) 。整个procdir数组由进程PID结构的pid_prslot成员索引 。创建进程时(fork())系统在procdir数组中为之分配一个元素,参看图1 。
--------------------------------------------------------------------------
------------> --------- <----procdir(procent结构数组)
| proc |<-----------------------|-----| pe_proc |
| | | | pe_next |--0
| p_pidp |---->------------|---------| |
内--------| pid_prslot |----| pe_proc |<-|
| ^ | pid_id | | pe_next |--|
核 V |---------------------| |
--------| pe_proc |<-|
进 | proc | | pe_next |--|
| |----> ---------| |
程 | p_pidp |---->------------| | pe_proc |<-|
--------| pid_prslot |----| pe_next |--|
表 | ^ | pid_id |---------| |
V |-----------------| pe_proc |<-|
--------| | pe_next | |
| proc |<--------------------------------|
| | | | |
| p_pidp | | | V
--------| | v.v_proc
图1. 进程PID结构的pid_prslot成员用于索引procdir数组
--------------------------------------------------------------------------
下面是在我的Sun工作站上找到的相应头文件内容:
/usr/include/sys/proc.h
struct proc
{
struct proc * p_next; /* active chain link next */
struct proc * p_prev; /* active chain link prev */
struct pid * p_pidp; /* process ID info */
struct vnode * p_trace; /* pointer to primary /proc vnode */
struct vnode * p_plist; /* list of /proc vnodes for process */
}
/* process ID info */
struct pid
{
unsigned int pid_prslot :24;
pid_t pid_id;
};
procfs内核代码描述了procfs目录入口的精确格式,这个格式以典型的磁盘文件
系统为模板,内核中每个入口对应一个目录名 。目录入口包含在目录中的偏移(第几个入口)、长度域以及inode号 。/proc下文件对象的inode号源自文件对象类型和进程号 。注意,/proc目录入口不会出现在目录名搜索缓存中,根据定义,/proc目录入口总是位于物理内存中(不会被扇出?) 。
因为procfs是一个文件系统,它构建在虚拟文件系统VFS和Solaris vnode构架之上,文件系统实例作为一个VFS对象存在,其中的文件通过vnode描述 。procfs创建VFS和vnode结构,通过它们可以针对procfs进行文件系统相关操作,比如mount和umount,可以针对/proc目录及文件对象进行open、read和write操作 。
推荐阅读
- Intel 平台版本 Solaris 8 安装指南 --6.故障排除
- 关于Solaris的syslog机制
- Solaris9的jumpstart服务器配置中文详解
- configure TCP Wrappers in Solaris 9
- SPARC/Solaris 8下快速终结TCP有限状态机的TIME_WAIT状态
- Solaris上的域名系统配置
- SUN Solaris 7重新安装手记
- SOLARIS+QMAIL+VPOPMAIL+IGENUS+QMAILAMDIN
- Solaris中的磁盘设备
- Solaris 的引导与初始化