一直以为PROC文件系统很是晦涩难懂,平时仅仅是使用它,不愿意去触碰内核中的具体实现。今天突发奇想,想看看里面究竟是怎么实现的,结果……真是大跌眼镜,没想到里面并不复杂

关于PROC文件系统的功能以及在Linux中的地位就不多说了,在用户空间和内核空间交互的界面也扮演者举足轻重的地位。我们今天就从proc_create函数开始,看看其中的实现。该函数会创建一个PROC entry,用户可以通过对文件系统中的该文件,和内核进行数据的交互。

static inline struct proc_dir_entry *proc_create(
const char *name, umode_t mode, struct proc_dir_entry *parent,
const struct file_operations *proc_fops)
{
return proc_create_data(name, mode, parent, proc_fops, NULL);
}

简要介绍下参数:

name:名字

mod:模式

parent:父entry,为NULL的话,默认父entry是/proc

struct proc_dir_entry proc_root = {
.low_ino = PROC_ROOT_INO,
.namelen = 5,
.mode = S_IFDIR | S_IRUGO | S_IXUGO,
.nlink = 2,
.count = ATOMIC_INIT(1),
.proc_iops = &proc_root_inode_operations,
.proc_fops = &proc_root_operations,
.parent = &proc_root,
.name = "/proc",
};

proc_fops:操作函数表

函数返回一个proc_dir_entry。可以看到proc_create中直接调用了proc_create_data,而该函数主要完成2个功能1、调用__proc_create完成具体proc_dir_entry的创建。2、调用proc_register把entry注册进系统。

struct proc_dir_entry *proc_create_data(const char *name, umode_t mode,
struct proc_dir_entry *parent,
const struct file_operations *proc_fops,
void *data)
{
struct proc_dir_entry *pde;
if ((mode & S_IFMT) == )
mode |= S_IFREG; if (!S_ISREG(mode)) {
WARN_ON(); /* use proc_mkdir() */
return NULL;
} if ((mode & S_IALLUGO) == )
mode |= S_IRUGO;
pde = __proc_create(&parent, name, mode, );
if (!pde)
goto out;
pde->proc_fops = proc_fops;
pde->data = data;
if (proc_register(parent, pde) < )
goto out_free;
return pde;
out_free:
kfree(pde);
out:
return NULL;
}

先看proc_dir_entry的创建,这里通过__proc_create函数,其实该函数内部也很简单,就是为entry分配了空间,并对相关字段进行设置,主要包含name,namelen,mod,nlink等。创建好后,就设置操作函数proc_fops和data。然后就调用proc_register进行注册,

static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
{
struct proc_dir_entry *tmp;
int ret; ret = proc_alloc_inum(&dp->low_ino);
if (ret)
return ret;
/*如果是 目录*/
if (S_ISDIR(dp->mode)) {
dp->proc_fops = &proc_dir_operations;
dp->proc_iops = &proc_dir_inode_operations;
dir->nlink++;
/*如果是链接*/
} else if (S_ISLNK(dp->mode)) {
dp->proc_iops = &proc_link_inode_operations;
/*如果是文件*/
} else if (S_ISREG(dp->mode)) {
BUG_ON(dp->proc_fops == NULL);
dp->proc_iops = &proc_file_inode_operations;
} else {
WARN_ON();
return -EINVAL;
} spin_lock(&proc_subdir_lock); for (tmp = dir->subdir; tmp; tmp = tmp->next)
if (strcmp(tmp->name, dp->name) == ) {
WARN(, "proc_dir_entry '%s/%s' already registered\n",
dir->name, dp->name);
break;
}
/*子dir链接成链表,且子dir中含有父dir的指针*/
dp->next = dir->subdir;
dp->parent = dir;
dir->subdir = dp;
spin_unlock(&proc_subdir_lock); return ;
}

函数首先分配一个inode number,然后根据entry的类型对其进行操作函数赋值,主要分为目录、链接、文件。这里我们只关注文件,文件的操作函数一般由用户自己定义,即上面我们设置的ops,这里仅仅是设置inode操作函数表,设置成了全局的proc_file_inode_operations,然后插入到父目录的子文件链表中,注意是头插法。基本结构如下,其中每个子节点都有指向父节点的指针。

其实创建entry的过程就这么简单,由于PROC也是一种文件系统,所以可以和ext2/ext3等文件系统一样,作为一个实体文件系统,通过VFS给用户提供统一的接口。相对于实体的文件系统而言,PROC文件系统要简单的多。因为其不需要管理具体磁盘上的文件,不需要和硬件打交道。正常情况下用户发起文件操作流程为:用户层序->系统调用->VFS层->具体文件系统->磁盘驱动程序。而针对PROC文件系统而言,其不需要和磁盘驱动打交道,最低层的部分就是操作系统各个子模块提供的操作函数表。这个就需要根据不同的模块进行不同的操作了,所以都是某个模块自己通过PROC的接口,向PROC注册内容,针对我们普通用户添加的entry,最低层的操作自然是我们注册的ops函数表了。

以马内利

参考资料:

LInux内核3.10.1源码

proc_create函数内幕初探的更多相关文章

  1. 基于Vue、web3的以太坊项目开发及交易内幕初探 错误解决总结

    基于Vue.web3的以太坊项目开发及交易内幕初探 本文通过宏观和微观两个层面窥探以太坊底层执行逻辑. 宏观层面描述创建并运行一个小型带钱包的发币APP的过程,微观层面是顺藤摸瓜从http api深入 ...

  2. c/c++ 函数模板初探

    函数模板初探 1,由来:有时候,函数的逻辑是一样的,只是参数的类型不同,比如下面 int Max(int a, int b){ return a > b ? a : b; } double Ma ...

  3. python之绘制函数pyplot初探

    我们想将我们手里的数据通过图形的方式展示出来,这样我们更直观的,更可以发现数据带给我们的信息.今天给大家介绍要给python中pyplot绘制函数.一般我们想将手里的数据绘制成图形,分为四大步:1.准 ...

  4. Arcade初探[0] 目录与导航

    2017年6月,ESRI开发者页面出现了一个新玩意儿:Arcade. 连接:点我 这是什么东西呢?有什么用呢? 1. 是什么 Arcade一种表达语言,可以在ArcGIS平台上使用.不管是编写简单的脚 ...

  5. 【黑客免杀攻防】读书笔记7 - 软件逆向工程基础1(函数调用约定、Main函数查找)

    0x1 准备工作 1.1.准备工具 IDA:交互式反汇编工具 OllyDbg:用户层调试工具 Visual Studio:微软开发工具 1.2.基础知识 C++开发 汇编语言 0x2 查找真正的mai ...

  6. CO-PRIME(初探 莫比乌斯)NYOJ1066(经典)gcd(a,b)=1

    CO-PRIME 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描写叙述 This problem is so easy! Can you solve it? You are ...

  7. C++中的函数重载分析(一)

    1,重载是 C 语言到 C++ 语言的一个飞跃,C 语言中没有重载的概念,所有的函数 名是不允许有重复的,在 C++ 中因为引进了重载,所以函数名可以重复: 2,自然语言中的上下文: 1,你知道上面词 ...

  8. linux 驱动入门3

    不吃苦中苦,难为人上人.努力,给老婆孩子提供个良好的生活居住环境. http://www.cnblogs.com/nan-jing/articles/5806399.html 上文提到.可以自动创建了 ...

  9. proc-virtual-file-system

    内核代码中分别找出一处 proc 和 seq_file 的完整使用过程,记录下来 在用户空间进行相应"读"."写" 介绍 Proc 虚拟文件系统 操作 proc ...

随机推荐

  1. 【Java面试题】40 你所知道的集合类都有哪些?主要方法?

    线性表,链表,哈希表是常用的数据结构,在进行Java开发时,JDK已经为我们提供了一系列相应的类来实现基本的数据结构.这些类均在java.util包中.本文试图通过简单的描述,向读者阐述各个类的作用以 ...

  2. c++ const enum #define

    最后的最后,我们略微总结一下:        1.只是声明单一固定值,尽可能采用const.        2.如果是一组固定值,并且互相有关联,则采用enum.        3.不涉及条件编译,只 ...

  3. 父div高度不能自适应子div高度的解决方案

    <div id="parent"><div id="content"> </div></div> 当conten ...

  4. Jquery实现上下移动和排序代码

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/ ...

  5. linux中sftp默认登录的端口号是多少? sftp通过指定的端口号连接?sftp默认端口号

    需求描述: 今天一个同事,遇到个问题,程序连接sftp服务器连接不上,问我端口号是多少, 我想了一下是21还是22,所以就做了测试,发现sftp默认的连接端口号是22, 在此做下记录. 操作过程: 1 ...

  6. oracle中REF Cursor用法

    from:http://www.111cn.net/database/Oracle/42873.htm 1,什么是 REF游标 ? 动态关联结果集的临时对象.即在运行的时候动态决定执行查询. 2,RE ...

  7. docker中文、手册、教程

    Docker资源 Docker官方英文资源: docker官网:http://www.docker.com Docker windows入门:https://docs.docker.com/windo ...

  8. eclipse的.properties文件中文显示问题

    eclipse的.properties文件,默认的编码方式是iso-8859-1. 所以中文显示有问题. 按照下面的方式,把Default Encoding修改成UTF-8就可以了.

  9. Size Balanced Tree

    Size Balanced Tree(SBT)是目前速度最快的平衡二叉搜索树,且能够进行多种搜索操作,区间操作:和AVL.红黑树.伸展树.Treap类似,SBT也是通过对节点的旋转来维持树的平衡,而相 ...

  10. 【PHP】算法: 获取满足给定值的最优组合

    PHP 获取给定值的最优组合 方法 -   (蓝洛提供,博客地址: www.zhaorui.info) <?php ini_set('error_reporting','E_ALL^E_NOTI ...