我们知道在linux中,proc系统中对于每个进程都有一个进程相关的目录,里面描述了该进程各个方面详细的信息,本文探讨3个问题:
1: /proc目录下每进程子目录的形成[动态遍历当前进程列表形成]
2:每进程子目录下子目录/子文件的形成[静态数组]
3:/proc/net/子目录下子目录、子文件形成[系统初始化时形成]
内容: 点击打开链接
0 首先介绍proc_dir_entry的层次结构
struct proc_dir_entry {
unsignedint low_ino;
unsignedshort namelen;
constchar *name;
mode_tmode;
nlink_tnlink;
uid_tuid;
gid_tgid;
loff_tsize;
const struct inode_operations *proc_iops;
/*
* NULL ->proc_fops means "PDE is goingaway RSN" or
* "PDE is just created". In eithercase, e.g. ->read_proc won't be
* called because it's too late or too early,respectively.
*
* If you're allocating ->proc_fopsdynamically, save a pointer
* somewhere.
*/
const struct file_operations *proc_fops;
structmodule *owner;
struct proc_dir_entry *next, *parent, *subdir;
…
};
所有的proc目录项都是通过next,parent,subdir组成树状连接结构,目录层次组织如下:
Root
|
A –> B –>C.. –>Root
|
A1–>A2…–>A
1 内核中如何遍历当前进程列表
我们知道当前系统中的所有进程在进程终止前都会存在于各种链表中,但是只有当进程处于就绪态时会被调度器调度执行,否则永远无法被调度;当进程终止时从链表中清除,从而结束其生命过程;linux中的进程有两个派系组成:内核线程,其根线程是kthreadd线程,进程号是2;用户进程,其根进程是init进程,进程号是1,1号和2号进程是并列的,在系统初始化后期有内核同时创建;用pstree无法看到kthreadd派系,用ps、top等命令、以及在
Proc系统下可以看到当前所有的用户进程和内核线程,遍历原理如下:
1.1 proc顶层目录结构的接口
/proc目录的遍历函数位由proc目录的file_operations->readdir函数实现
static const struct file_operationsproc_root_operations = {
.read = generic_read_dir,
.readdir =proc_root_readdir,
};
注:proc目录下的内容大致如下:
该目录下的文件形成有以下特点:
1 内容一部分应该是静态形成的,比如fs目录,fb文件等等,这部分子目录、子文件在系统初始化时候,应该挂载在proc目录对应的proc_dir_entry链表下;
2 另外还有.和..子目录,分别是对当前目录和父目录的连接[ls –al可以显示],内核对于上述猜测的实现为;
3 由数字组成的子目录显然是在每次读取proc内容时动态生成的,其表示当前系统所有进程的一些信息情况;
static int proc_root_readdir(struct file * filp,void* dirent, filldir_t filldir)
{
unsignedint nr = filp->f_pos;
intret;
lock_kernel();
if(nr < FIRST_PROCESS_ENTRY) {
int error =proc_readdir(filp, dirent, filldir); //1,2部分形成原理
if(error <= 0) {
unlock_kernel();
returnerror;
}
filp->f_pos= FIRST_PROCESS_ENTRY;
}
unlock_kernel();
ret = proc_pid_readdir(filp, dirent, filldir); //3部分形成
returnret;
}
系统中对于一个目录有多中读取子目录的方式,比如ls和ls –al显示的结果不同,这是由传入过程中对file->f_ops设定不同的偏移决定的,对于proc根目录而言,有以下特定:
f_ops = 0 为.目录链接,接连接到自身
f_ops = 1 为..目录链接,接连接到父目录
f_ops=[ 2 --- (FIRST_PROCESS_ENTRY-1) ]为proc下的静态目录或者静态文件
f_ops=[ FIRST_PROCESS_ENTRY --- (FIRST_PROCESS_ENTRY+ ARRAY_SIZE(proc_base_stuff)-1) ] 为self子目录内容
f_ops=[ FIRST_PROCESS_ENTRY+ ARRAY_SIZE(proc_base_stuff)] 为init_task即0号初始进程,至少可以这么认为
f_pos = PID_MAX_LIMIT + TGID_OFFSET; 标志着目录遍历结束, FIRST_PROCESS_ENTRY= 256
proc_readdir(filp, dirent, filldir)的实现比较简单,下面分析proc_pid_readdir(filp,dirent, filldir)的实现过程:
int proc
1: /proc目录下每进程子目录的形成[动态遍历当前进程列表形成]
2:每进程子目录下子目录/子文件的形成[静态数组]
3:/proc/net/子目录下子目录、子文件形成[系统初始化时形成]
内容: 点击打开链接
0 首先介绍proc_dir_entry的层次结构
struct proc_dir_entry {
unsignedint low_ino;
unsignedshort namelen;
constchar *name;
mode_tmode;
nlink_tnlink;
uid_tuid;
gid_tgid;
loff_tsize;
const struct inode_operations *proc_iops;
/*
* NULL ->proc_fops means "PDE is goingaway RSN" or
* "PDE is just created". In eithercase, e.g. ->read_proc won't be
* called because it's too late or too early,respectively.
*
* If you're allocating ->proc_fopsdynamically, save a pointer
* somewhere.
*/
const struct file_operations *proc_fops;
structmodule *owner;
struct proc_dir_entry *next, *parent, *subdir;
…
};
所有的proc目录项都是通过next,parent,subdir组成树状连接结构,目录层次组织如下:
Root
|
A –> B –>C.. –>Root
|
A1–>A2…–>A
1 内核中如何遍历当前进程列表
我们知道当前系统中的所有进程在进程终止前都会存在于各种链表中,但是只有当进程处于就绪态时会被调度器调度执行,否则永远无法被调度;当进程终止时从链表中清除,从而结束其生命过程;linux中的进程有两个派系组成:内核线程,其根线程是kthreadd线程,进程号是2;用户进程,其根进程是init进程,进程号是1,1号和2号进程是并列的,在系统初始化后期有内核同时创建;用pstree无法看到kthreadd派系,用ps、top等命令、以及在
Proc系统下可以看到当前所有的用户进程和内核线程,遍历原理如下:
1.1 proc顶层目录结构的接口
/proc目录的遍历函数位由proc目录的file_operations->readdir函数实现
static const struct file_operationsproc_root_operations = {
.read = generic_read_dir,
.readdir =proc_root_readdir,
};
注:proc目录下的内容大致如下:
![](https://img-my.csdn.net/uploads/201204/04/1333527955_9449.png)
该目录下的文件形成有以下特点:
1 内容一部分应该是静态形成的,比如fs目录,fb文件等等,这部分子目录、子文件在系统初始化时候,应该挂载在proc目录对应的proc_dir_entry链表下;
2 另外还有.和..子目录,分别是对当前目录和父目录的连接[ls –al可以显示],内核对于上述猜测的实现为;
3 由数字组成的子目录显然是在每次读取proc内容时动态生成的,其表示当前系统所有进程的一些信息情况;
static int proc_root_readdir(struct file * filp,void* dirent, filldir_t filldir)
{
unsignedint nr = filp->f_pos;
intret;
lock_kernel();
if(nr < FIRST_PROCESS_ENTRY) {
int error =proc_readdir(filp, dirent, filldir); //1,2部分形成原理
if(error <= 0) {
unlock_kernel();
returnerror;
}
filp->f_pos= FIRST_PROCESS_ENTRY;
}
unlock_kernel();
ret = proc_pid_readdir(filp, dirent, filldir); //3部分形成
returnret;
}
系统中对于一个目录有多中读取子目录的方式,比如ls和ls –al显示的结果不同,这是由传入过程中对file->f_ops设定不同的偏移决定的,对于proc根目录而言,有以下特定:
f_ops = 0 为.目录链接,接连接到自身
f_ops = 1 为..目录链接,接连接到父目录
f_ops=[ 2 --- (FIRST_PROCESS_ENTRY-1) ]为proc下的静态目录或者静态文件
f_ops=[ FIRST_PROCESS_ENTRY --- (FIRST_PROCESS_ENTRY+ ARRAY_SIZE(proc_base_stuff)-1) ] 为self子目录内容
f_ops=[ FIRST_PROCESS_ENTRY+ ARRAY_SIZE(proc_base_stuff)] 为init_task即0号初始进程,至少可以这么认为
f_pos = PID_MAX_LIMIT + TGID_OFFSET; 标志着目录遍历结束, FIRST_PROCESS_ENTRY= 256
proc_readdir(filp, dirent, filldir)的实现比较简单,下面分析proc_pid_readdir(filp,dirent, filldir)的实现过程:
int proc