​ 详解Linux内核通信-proc文件系统

news2024/12/23 4:01:07

使用 /proc 文件系统来访问 Linux 内核的内容,这个虚拟文件系统

在内核空间和用户空间之间打开了一个通信窗口:

/proc 文件系统是一个虚拟文件系统,通过它可以使用一种新的方法在 Linux内核空间和用户间之间进行通信。在 /proc 文件系统中,我们可以将对虚拟文件的读写作为与内核中实体进行通信的一种手段,但是与普通文件不同的是,这些虚拟文件的内容都是动态创建的。本文对 /proc 虚拟文件系统进行了介绍,并展示了它的用法。

最初开发 /proc 文件系统是为了提供有关系统中进程的信息。但是由于这个文件系统非常有用,因此内核中的很多元素也开始使用它来报告信息,或启用动态运行时配置。清单 1 是对 /proc 中部分元素进行一次交互查询的结果。它显示的是 /proc 文件系统的根目录中的内容。注意,在左边是一系列数字编号的文件。每个实际上都是一个目录,表示系统中的一个进程。由于在 GNU/Linux 中创建的第一个进程是 init 进程,因此它的 process-id 为 1。然后对这个目录执行一个 ls 命令,这会显示很多文件。每个文件都提供了有关这个特殊进程的详细信息。/proc 中另外一些有趣的文件有:cpuinfo,它标识了处理器的类型和速度;pci,显示在 PCI 总线上找到的设备;modules,标识了当前加载到内核中的模块。

另外,我们还可以使用 sysctl 来配置这些内核条目。/proc 文件系统并不是 GNU/Linux 系统中的惟一一个虚拟文件系统。在这种系统上,sysfs 是一个与 /proc 类似的文件系统,但是它的组织更好(从 /proc 中学习了很多教训)。不过 /proc 已经确立了自己的地位,因此即使 sysfs 与 /proc 相比有一些优点,/proc 也依然会存在。还有一个 debugfs 文件系统,不过(顾名思义)它提供的更多是调试接口。debugfs 的一个优点是它将一个值导出给用户空间非常简单(实际上这不过是一个调用而已)。

【文章福利】小编推荐自己的Linux内核技术交流群: 【977878001】整理一些个人觉得比较好得学习书籍、视频资料共享在群文件里面,有需要的可以自行添加哦!!!前100进群领取,额外赠送一份 价值699的内核资料包(含视频教程、电子书、实战项目及代码)

内核资料直通车:Linux内核源码技术学习路线+视频教程代码资料

  学习直通车:Linux内核源码/内存调优/文件系统/进程管理/设备驱动/网络协议栈

这些文件的解释和意义如下:

cmdline:系统启动时输入给内核命令行参数
cpuinfo:CPU的硬件信息 (型号, 家族, 缓存大小等)
devices:主设备号及设备组的列表,当前加载的各种设备(块设备/字符设备)
dma:使用的DMA通道
filesystems:当前内核支持的文件系统,当没有给 mount(1) 指明哪个文件系统的时候, mount(1) 就依靠该文件遍历不同的文件系统
interrupts :中断的使用及触发次数,调试中断时很有用
ioports I/O:当前在用的已注册 I/O 端口范围
kcore:该伪文件以 core 文件格式给出了系统的物理内存映象(比较有用),可以用 GDB 查探当前内核的任意数据结构。该文件的总长度是物理内存 (RAM) 的大小再加上 4KB
kmsg:可以用该文件取代系统调用 syslog(2) 来记录内核日志信息,对应dmesg命令
kallsym:内核符号表,该文件保存了内核输出的符号定义, modules(X)使用该文件动态地连接和捆绑可装载的模块
loadavg:负载均衡,平均负载数给出了在过去的 1、 5,、15 分钟里在运行队列里的任务数、总作业数以及正在运行的作业总数。
locks:内核锁 。
meminfo物理内存、交换空间等的信息,系统内存占用情况,对应df命令。
misc:杂项 。
modules:已经加载的模块列表,对应lsmod命令 。
mounts:已加载的文件系统的列表,对应mount命令,无参数。
partitions:系统识别的分区表 。
slabinfo:sla池信息。
stat:全面统计状态表,CPU内存的利用率等都是从这里提取数据。对应ps命令。
swaps:对换空间的利用情况。
version:指明了当前正在运行的内核版本。

可加载内核模块(LKM)是用来展示 /proc 文件系统的一种简单方法,这是因为这是一种用来动态地向 Linux 内核添加或删除代码的新方法。LKM 也是 Linux 内核中为设备驱动程序和文件系统使用的一种流行机制。如果你曾经重新编译过 Linux 内核,就可能会发现在内核的配置过程中,有很多设备驱动程序和其他内核元素都被编译成了模块。如果一个驱动程序被直接编译到了内核中,那么即使这个驱动程序没有运行,它的代码和静态数据也会占据一部分空间。但是如果这个驱动程序被编译成一个模块,就只有在需要内存并将其加载到内核时才会真正占用内存空间。

集成到 /proc 文件系统中

内核程序员可以使用的标准 API,LKM 程序员也可以使用。

方法一:(create_proc_entry创建proc文件)

1.1 .创建目录:

[c]  view plain  copy
struct proc_dir_entry *proc_mkdir(const char *name,  
                struct proc_dir_entry *parent);  

1.2 .创建proc文件:

[c]  view plain  copy
struct proc_dir_entry *create_proc_entry( const char *name,  mode_t mode,  
                struct proc_dir_entry *parent );  

create_proc_entry函数用于创建一个一般的proc文件,其中name是文件名,比如“hello”,mode是文件模式,parent是要创建的proc文件的父目录(若parent = NULL则创建在/proc目录下)。

create_proc_entry 的返回值是一个 proc_dir_entry 指针(或者为 NULL,说明在 create 时发生了错误)。然后就可以使用这个返回的指针来配置这个虚拟文件的其他参数,例如在对该文件执行读操作时应该调用的函数。

[html]  view plain  copy
struct proc_dir_entry {  
    ......  
    const struct file_operations *proc_fops;    <==文件操作结构体  
    struct proc_dir_entry *next, *parent, *subdir;  
    void *data;  
    read_proc_t *read_proc;                    <==读回调  
    write_proc_t *write_proc;                  <==写回调  
    ......  
}; 

1.3 .删除proc文件/目录:

[c] view plain copy
void remove_dir_entry(const char *name, struct proc_dir_entry *parent);  

要从 /proc 中删除一个文件,可以使用 remove_proc_entry 函数。要使用这个函数,我们需要提供文件名字符串,以及这个文件在 /proc 文件系统中的位置(parent)。

3、proc文件读回调函数

static int (*proc_read)(char *page, char **start, off_t off, int count, int *eof, void *data);

4、proc文件写回调函数

static int proc_write_foobar(struct file *file, const char *buffer, unsigned long count, void *data);

proc文件实际上是一个叫做proc_dir_entry的struct(定义在proc_fs.h),该struct中有int read_proc和int write_proc两个元素,要实现proc的文件的读写就要给这两个元素赋值。但这里不是简单地将一个整数赋值过去就行了,需要实现两个回调函数。在用户或应用程序访问该proc文件时,就会调用这个函数,实现这个函数时只需将想要让用户看到的内容放入page即可。在用户或应用程序试图写入该proc文件时,就会调用这个函数,实现这个函数时需要接收用户写入的数据(buff参数)。

写回调函数

我们可以使用 write_proc 函数向 /proc 中写入一项。这个函数的原型如下:

int mod_write( struct file *filp, const char __user *buff,
               unsigned long len, void *data );

filp 参数实际上是一个打开文件结构(我们可以忽略这个参数)。buff 参数是传递给您的字符串数据。缓冲区地址实际上是一个用户空间的缓冲区,因此我们不能直接读取它。len 参数定义了在 buff 中有多少数据要被写入。data 参数是一个指向私有数据的指针。在这个模块中,我们声明了一个这种类型的函数来处理到达的数据。

Linux 提供了一组 API 来在用户空间和内核空间之间移动数据。对于 write_proc 的情况来说,我们使用了 copy_from_user 函数来维护用户空间的数据。

读回调函数

int mod_read( char *page, char **start, off_t off,
              int count, int *eof, void *data );

page 参数是这些数据写入到的位置,其中 count 定义了可以写入的最大字符数。在返回多页数据(通常一页是 4KB)时,我们需要使用 start和 off 参数。当所有数据全部写入之后,就需要设置 eof(文件结束参数)。与 write 类似,data 表示的也是私有数据。此处提供的 page 缓冲区在内核空间中。因此,我们可以直接写入,而不用调用 copy_to_user。

实例代码:

#include <linux/module.h>  
#include <linux/kernel.h>  
#include <linux/init.h>  
#include <linux/proc_fs.h>  
#include <linux/jiffies.h>  
#include <asm/uaccess.h>  
  
  
#define MODULE_VERS "1.0"  
#define MODULE_NAME "procfs_example"  
  
#define FOOBAR_LEN 8  
  
struct fb_data_t {  
    char name[FOOBAR_LEN + 1];  
    char value[FOOBAR_LEN + 1];  
};  
  
  
static struct proc_dir_entry *example_dir, *foo_file;    
  
struct fb_data_t foo_data;  
    
static int proc_read_foobar(char *page, char **start,  
                off_t off, int count,   
                int *eof, void *data)  
{  
    int len;  
    struct fb_data_t *fb_data = (struct fb_data_t *)data;  
  
    /* DON'T DO THAT - buffer overruns are bad */  
    len = sprintf(page, "%s = '%s'\n",   
              fb_data->name, fb_data->value);  
  
    return len;  
}  
  
  
static int proc_write_foobar(struct file *file,  
                 const char *buffer,  
                 unsigned long count,   
                 void *data)  
{  
    int len;  
    struct fb_data_t *fb_data = (struct fb_data_t *)data;  
  
    if(count > FOOBAR_LEN)  
        len = FOOBAR_LEN;  
    else  
        len = count;  
  
    if(copy_from_user(fb_data->name, buffer, len))  
        return -EFAULT;  
  
    fb_data->value[len] = '\0';  
  
    return len;  
}  
  
  
static int __init init_procfs_example(void)  
{  
    int rv = 0;  
  
    /* create directory */  
    example_dir = proc_mkdir(MODULE_NAME, NULL);  
    if(example_dir == NULL) {  
        rv = -ENOMEM;  
        goto out;  
    }  
  
    /* create foo and bar files using same callback  
     * functions   
     */  
    foo_file = create_proc_entry("foo", 0644, example_dir);  
    if(foo_file == NULL) {  
        rv = -ENOMEM;  
        goto no_foo;  
    }  
  
    strcpy(foo_data.name, "foo");  
    strcpy(foo_data.value, "foo");  
    foo_file->data = &foo_data;  
    foo_file->read_proc = proc_read_foobar;  
    foo_file->write_proc = proc_write_foobar;  
         
    /* everything OK */  
    printk(KERN_INFO "%s %s initialised\n",  
           MODULE_NAME, MODULE_VERS);  
    return 0;  
  
 
no_foo:  
    remove_proc_entry("jiffies", example_dir);  
 
out:  
    return rv;  
}  
  
  
static void __exit cleanup_procfs_example(void)  
{  
  
    remove_proc_entry("foo", example_dir);    
    remove_proc_entry(MODULE_NAME, NULL);  
  
    printk(KERN_INFO "%s %s removed\n",  
           MODULE_NAME, MODULE_VERS);  
}  
  
  
module_init(init_procfs_example);  
module_exit(cleanup_procfs_example);  
  
MODULE_AUTHOR("Erik Mouw");  
MODULE_DESCRIPTION("procfs examples");  
MODULE_LICENSE("GPL");  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/12136.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL事务和索引

✏️作者&#xff1a;银河罐头 &#x1f4cb;系列专栏&#xff1a;MySQL &#x1f332;“种一棵树最好的时间是十年前&#xff0c;其次是现在” 目录索引概念使用索引在MySQL中的数据结构事务概念mysql的隔离级别索引 概念 索引是一种特殊的文件&#xff0c;包含着对数据表里所…

一图看懂,阿里云飞天企业版如何支持政企数智创新

杭州&#xff0c;2022年11月5日 – 今日&#xff0c;在云栖大会专有云技术和应用实践论坛&#xff0c;阿里云重磅发布飞天企业版在建云、管云、用云方面的全面升级&#xff0c;并邀请行业专家、政企客户代表和合作伙伴面向未来十年共话新一代政企IT发展趋势&#xff0c;分享阿里…

行业洞察 | AI贩卖的焦虑,我们该买单吗?

图片来源Midjourney Showcase 在过去的几个月里&#xff0c;人工智能生成的艺术在受欢迎程度和可访问性方面都经历了快速增长。随着DALL-E、Midjourney和Stable Diffusion等引擎刺激了 AI 生成的艺术品在在线平台上的大量涌入。 此前&#xff0c;一位美国39岁游戏设计师&#…

测试行业3年经验,面试想拿 15K,HR说你只值 7K,该如何回答或者反驳?

面试最尴尬的不是被拒绝&#xff0c;而是直接说你不值那个价格... 最近朋友在面试的时候&#xff0c;HR 突然来了句&#xff1a;你只值 7K。朋友后面和我说了这个事。我想如果是我处在这种情况下&#xff0c;自己并不能很好地回答或者反驳。不知道大家会怎么回答或者反驳&…

深入浅出了解MYSQL8特性注入是什么

前言 今天给大家带来的是MYSQL8版本的特性注入&#xff0c;说起SQL注入大家一定不陌生&#xff0c;可是你有没有想过&#xff0c;当SQL注入中最关键的函数SELECT被过滤后&#xff0c;我们要如何去执行SQL语句呢&#xff0c;这就是本文要讲的内容&#xff0c;即利用MYSQL8版本的…

智慧人社解决方案-最新全套文件

智慧人社解决方案-最新全套文件一、建设背景二、思路架构三、建设方案1、全局性数据整合2、综合数据分析平台3、一体化数据管控四、获取 - 智慧人社全套最新解决方案合集一、建设背景 智慧人社平台以建设智慧大社保服务体系为目标&#xff0c;全面践行“互联网&#xff0b;人社…

python基于PHP+MySQL的大学生交友社交网站

近年来,大学生的数量在逐步的增加,为了能够让这些大学生有一个更好的交友环境,需要创建一个基于大学生的社交交友网站。这样可以拉近彼此大学生之间的感情,让他们可以更好的进行学习和交流。 PHP大学生交友社交网站通过PHP&#xff1a;MySQL进行开发,分为前台和后台两部分,通过…

[附源码]SSM计算机毕业设计餐厅卫生安全系统JAVA

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

mariadb10.8 主主同步 相互复制

1. 配置说明 操作系统&#xff1a;CentOS7 CPU指令集&#xff1a;x86_64 host1 主机&#xff1a; 2 core 2G 40GIP&#xff1a;192.168.0.98 host2 主机&#xff1a; 2 core 2G 40GIP&#xff1a;192.168.0.166 2. 数据库安装 见 MariaDB官方下载文档 https://mariadb.or…

mysql“数据不存在插入,存在则更新”实现

参考文章:Mysql:如果数据存在则更新&#xff0c;不存在则插入 场景 工作中有遇到需要配置一些指定的字段数据&#xff0c;但数据量大&#xff0c;不清楚之前是否有配置过&#xff0c;正确的思路应该是如果有这条数据了&#xff0c;那么更新数据的值&#xff0c;如果没有这条数…

股票行情接口level2的盘口信息和level1有哪些区别?

普通的行情接口软件会有价格曲线、五档盘口、分时成交等等这些行情数据&#xff0c;但是股票行情接口level2所能够提供的行情数据远远不止这些&#xff0c;level2顾名思义其实就是level1的高配版&#xff0c;那么它包含的数据相对于比普通行情接口的会更精细也更丰富&#xff0…

华为 x 香格里拉集团|品质网络守护数字旅程

作者 | 曾响铃 文 | 响铃说 酒店行业正在快速推动数字化&#xff0c;其目标是对内提升酒店管理效率&#xff0c;对外提升宾客入住体验&#xff1b;而网络作为整个数字化变革的联接底座&#xff0c;迫切需要进行升级和优化。以香格里拉集团为例&#xff0c;作为成立超过半个世…

微信怎么使用手机号码收款转账?

微信怎么使用手机号码收款&#xff1f; 1、微信手机号码收款方&#xff0c;打开微信钱包&#xff0c;并点击钱包进入&#xff1b; 2、在微信钱包找到支付设置&#xff0c;并点击进入支付设置&#xff1b; 3、在微信钱包支付设置内&#xff0c;开启允许通过手机号向我转账&…

力荐,京东首席架构师:亿级流量架构的核心技术文档免费分享

学习是一种基础性的能力。然而&#xff0c;“吾生也有涯&#xff0c;而知也无涯。”&#xff0c;如果学习不注意方法&#xff0c;则会“以有涯随无涯&#xff0c;殆矣”。 学习就像吃饭睡觉一样&#xff0c;是人的一种本能&#xff0c;人人都有学习的能力。我们在刚出生的时候…

大厂敲门砖,在阿里工作十年的朋友,总结出这份java面试必看手册

眼看着时间一天一天地过去&#xff0c;距离过年也就二个月的日子了&#xff0c;还有多少程序员是两眼摸黑不知道面试要做哪些准备的朋友&#xff1f; 还不知道进大厂需要复习哪些资料的朋友可以看过来&#xff0c;知道有些朋友会没什么准备跟无头苍蝇一样所以博主早在一个月前…

[附源码]计算机毕业设计JAVA镐京学院教务管理系统

[附源码]计算机毕业设计JAVA镐京学院教务管理系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM my…

Python文件操作

文章目录文件操作打开文件关闭文件读文件写文件使用上下文管理器文件操作 打开文件 open函数 open函数的作用是打开一个文件&#xff0c;并返回打开的文件对象。该函数的常见调用方式如下&#xff1a; f open(file, mode, encoding)参数说明&#xff1a; file&#xff1a;待…

如何实现基于场景的接口自动化测试用例?

自动化本身是为了提高工作效率&#xff0c;不论选择何种框架&#xff0c;何种开发语言&#xff0c;我们最终想实现的效果&#xff0c;就是让大家用最少的代码&#xff0c;最小的投入&#xff0c;完成自动化测试的工作。 基于这个想法&#xff0c;我们的接口自动化测试思路如下…

Android App开发实战项目之大头贴App功能实现(附源码和演示 简单易上手)

需要图片集和源码请点赞关注收藏后评论区留言~~~ 一、需求描述 大头贴App有两个特征&#xff0c;第一个是头要大&#xff0c;拿来一张照片后把人像区域裁剪出来&#xff0c;这样新图片里的人头才会比较大&#xff0c;第二个是在周围贴上装饰物&#xff0c;而且装饰物还能随时更…

【Spring】——7、@Import注解给容器中快速导入一个组件

&#x1f4eb;作者简介&#xff1a;zhz小白 公众号&#xff1a;小白的Java进阶之路 专业技能&#xff1a; 1、Java基础&#xff0c;并精通多线程的开发&#xff0c;熟悉JVM原理 2、熟悉Java基础&#xff0c;并精通多线程的开发&#xff0c;熟悉JVM原理&#xff0c;具备⼀定的线…