一直以为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. CleanMyMac 3.7.5最强中文版_激活码_破解版_下载_注册码

    版权归作者所有,任何形式转载请联系作者.作者:缘来远去(来自豆瓣)来源:https://www.douban.com/note/612586476/ 最新版CleanMyMac 3中文版本已经发布快要 ...

  2. php error_log错误信息写入文件

  3. (转)Spring开启Annotation<context:annotation-config> 和 <context:component-scan>诠释及区别

    转自:https://www.cnblogs.com/leiOOlei/p/3713989.html <context:annotation-config> 和 <context:c ...

  4. Loadrunner的Socket脚本关联小技巧

    Socket脚本关联小技巧 我们在socket脚本调试的时候经常会遇到很多问题,比如:socket包中繁杂的二进制编码,socket数据如何进行截取,如何对socket数据包进行参数化等等,以下几点内 ...

  5. MathType在手,公式不求人!

    很多论文达人们的论文排版是相当漂亮的,页面也非常整齐美观,即使是理工类的论文,里面有很多的数学符号和公式,排版也是非常整洁,为什么达人们的公式论文能排版的这么完美,而自已却总是不得其门而入,最后只好救 ...

  6. mysql中,如何查看数据库元数据(metadata)的字符集?

    需求描述: mysql中,数据库的元数据也是有字符集的. 操作过程: 1.查看mysql数据库元数据的字符集 mysql> show variables like 'character_set_ ...

  7. 使用 MVVMLight 绑定数据

    如果你还不知道如何在VS中加入MVVMLight的引用,那么建议你先翻阅这篇文章:在VS中安装/使用 MVVMLight 这篇文章主要是介绍如何使用MVVMLight来绑定数据到界面中(View),以 ...

  8. [转]ASP.NET MVC 5 - 验证编辑方法(Edit method)和编辑视图(Edit view)

    在本节中,您将验证电影控制器生成的编辑方法(Edit action methods)和视图.但是首先将修改点代码,使得发布日期属性(ReleaseDate)看上去更好.打开Models \ Movie ...

  9. android开发源代码分析--多个activity调用多个jni库的方法

    android开发源代码分析--多个activity调用多个jni库的方法 有时候,我们在开发android项目时会遇到须要调用多个native c/jni库文件,下面是本人以前实现过的方法,假设有知 ...

  10. Java精选笔记_EL表达式

    EL表达式 初始EL EL是一种可以简化JSP页面的表达式,EL表达式的语法非常简单都是以"${"符号开始,以"}"符号结束的 EL表达式是一种简单的数据&qu ...