Linux驱动基础 | proc文件系统

embedded/2024/11/9 16:43:09/

文章目录

    • 前言
    • 思考
    • proc文件系统简介
      • proc文件系统是什么
      • proc文件系统的作用和特点
    • 列举procfs常用节点
    • procfs接口使用
      • procfs常用的API
      • procfs操作函数
      • 代码实验
    • 总结

前言

在Linux系统中,有一些特殊文件系统,用于进行文件接口统一的操作来完成各种功能,proc文件系统就是其中一个,记录有关Linux系统的所有详细信息,包括其内核、进程和配置参数。所以本篇就带大家一起学习下,本篇内核版本5.10

思考

看本篇内容之前思考两个问题:

  1. 你了解proc文件系统常用节点有哪些

  2. 尝试自己写一个内核模块,在/proc中创建名为"test"的目录,在"test"目录下创建个节点data,写进去字符后可以读出写入的数据

proc文件系统简介

proc文件系统是什么

Linux系统上的/proc目录是一种文件系统,即proc文件系统。

/与其它常见的文件系统不同的是,/proc是虚拟文件系统,它不是实际的存储设备中的文件,而是存在于内存中。

在Linux中存在着一类特殊的伪文件系统,进行文件接口统一的操作来完成各种功能,例如ptyfs、devfs、sysfs和procfs。而procfs就是其中应用最广泛的一种伪文件系统。

proc 文件系统的挂载点是 /proc,它可以获取进程的有用信息、系统的有用信息等,可以查看具体某个进程号的相关信息,也可以查看系统的信息,比如CPU,内存信息,中断信息,设备映射状态信息,内核日志信息等

proc文件系统的作用和特点

proc 文件系统提供了一些内核中各个子系统的信息,所以procfs中的文件通常是只读的,只在一些特殊情况下允许写入,例如禁用nmi_watchdog

echo 1 > /proc/sys/kernel/nmi_watchdog

或者用户自己单独写驱动程序创建自定义读写的proc节点,简单地使用 cat 和 echo 命令写入查看信息。

列举procfs常用节点

我们看看/proc目录下面的节点

这里总结下我常用的proc文件系统一些节点如下。

  • /proc/cpuinfo:CPU信息(型号、家族、缓存大小等)
  • /proc/meminfo:物理内存交换空间的列表
  • /proc/mounts:已挂载的文件系统列表
  • /proc/filesystems:被支持的文件系统
  • /proc/modules:内核中已插入的内核模块列表(类似于lsmod命令的输出)。
  • /proc/version:内核版本
  • /proc/cmdline:系统启动时输入的内核命令行参数
  • /proc/pid: pid表示进程的PID,这些子目录中包含的文件可以提供有关进程的状态和环境的重要细节信息
  • /proc/interrupts: 已注册的中断请求号
  • /proc/softirqs:已注册的软中断请求号
  • /proc/kmsg: 内核日志信息
  • /proc/devices:可用的设备驱动。如字符设备和块设备
  • /proc/slabinfo: slab系统的统计信息
  • /proc/uptime: 系统正常运行时间
  • /proc/kallsyms: 查看所有符合表
  • /proc/partitions:系统中的块设备分区表信息
  • /proc/iomem: 系统中的物理RAM和总线设备地址

procfs接口使用

procfs常用的API

下面介绍下本实验会用到的一些API函数,这些API函数定义在fs/proc/internal.h和fs/proc/generic.c

创建目录函数

在parent目录创建一个名为name的目录

struct proc_dir_entry *proc_mkdir(const char *name,struct proc_dir_entry *parent)

参数:

  • name 要创建的目录名称
  • parent 父目录,如果为NULL,表示直接在/proc下面创建目录。
struct proc_dir_entry *proc_mkdir_data(const char *name, umode_t mode,struct proc_dir_entry *parent, void *data)

参数:

  • name 要创建的目录名称
  • mode 指定要创建目录的权限
  • parent 父目录,如果为NULL,表示直接在/proc下面创建目录。
  • data 保存私有数据的指针,如不要为NULL。

注:这个接口和proc_mkdir_data的区别在于他不能保存私有数据指针。

创建文件函数

Linux v5.6之后,可以通过下面的API来创建一个procfs条目:

struct proc_dir_entry *proc_create(const char *name, umode_t mode, struct proc_dir_entry *parent, const struct proc_ops *proc_fops)

参数:

  • name 要创建的目录名称。
  • mode 指定要创建目录的权限,例如S_IRUGO | S_IWUSR表示文件对所有用户可读,对文件所有者可写。
  • parent 父目录,如果为NULL,表示直接在/proc下面创建目录。
  • proc_fops 指向file_operations结构体的指针,定义了对这个文件执行诸如open、read、write、ioctl等操作时的回调函数。

注:在Linux v3.10到 v5.6之间的版本,const struct proc_ops *proc_fops参数改成了const struct file_operations *proc_ops。

Linux v5.6之后,可以通过下面的API来创建一个procfs条目:

struct proc_dir_entry *proc_create_data(const char *name, umode_t mode,struct proc_dir_entry *parent,   const struct proc_fops *p                roc_fops, void *data)
  • name 要创建的目录名称
  • mode 指定要创建目录的权限
  • parent 父目录,如果为NULL,表示直接在/proc下面创建目录。
  • proc_fops 指向file_operations结构体的指针,定义了对这个文件执行诸如open、read、write、ioctl等操作时的回调函数。
  • data 保存私有数据的指针,如不要为NULL。

注:1、在Linux v3.10到 v5.6之间的版本,const struct proc_ops *proc_fops参数改成了const struct file_operations *proc_ops。
2.这个接口和proc_create_data的区别在于他不能保存私有数据指针。

创建符合链接函数

在parent目录创建指定dest目录的名为name的符合链接

struct proc_dir_entry *proc_symlink(const char *name, struct proc_dir_entry *parent, const char *dest)

参数:

  • name 原始符号。
  • parent 符号所在的目录。
  • dest 所要创建的符号链接名字。

删除目录/文件函数

删除parent目录中名为name的文件或者目录

void remove_proc_entry(const char *name, struct proc_dir_entry *parent)

参数:

  • name 要删除的文件或者目录名。
  • parent 符号所在的目录,如果为NULL,表示在/proc目录下。

也可以一次性移除整个proc目录及其下面的所有条目

void proc_remove(struct proc_dir_entry *parent);

参数:

  • parent 符号所在的目录,如果为NULL,表示在/proc目录下。

procfs操作函数

接下来就是要实现以下的procfs操作函数:

// Linux v3.10 ~ v5.5
static struct file_operations proc_fops = {.open = open_proc,.read = read_proc,.write = write_proc,.release = release_proc
};// Linux v5.6及之后
static struct proc_ops proc_fops = {.proc_open = open_proc,.proc_read = read_proc,.proc_write = write_proc,.proc_release = release_proc
};

代码实验

需求:尝试自己写一个内核模块,在/proc中创建名为"test"的目录,在"test"目录下创建两个节点,分别是"read"和"write"节点。从"read"节点中可以读取内核模块的某个全局变量的值,通过往"write"节点中写数据可以修改某个全局变量的值

代码实现

file:proc_test.c
#include <linux/proc_fs.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/printk.h>
#include <linux/uaccess.h>#define PROCFS_DIR_NAME  "test"
#define PROCFS_FILE_NAME "data"
#define BUFFER_SIZE 128static char example_buffer[BUFFER_SIZE] = {0};
static struct proc_dir_entry *example_dir = NULL;static ssize_t test_proc_write(struct file *file, const char __user *buf,size_t count, loff_t *pos)
{if (count > BUFFER_SIZE)return -EFAULT;memset(example_buffer, 0, BUFFER_SIZE);if (copy_from_user(example_buffer, buf, count))return -EFAULT;return count;
}static ssize_t test_proc_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
{return simple_read_from_buffer(buf, size, ppos, example_buffer, strlen(example_buffer));
}static const struct proc_ops proc_test_fops = {.proc_read      = test_proc_read,.proc_write     = test_proc_write,
};static int __init proc_test_init(void)
{example_dir = proc_mkdir(PROCFS_DIR_NAME, NULL);if (!example_dir)return -1;proc_create_data(PROCFS_FILE_NAME, 0644, example_dir, &proc_test_fops, NULL);return 0;
}static void __exit proc_test_exit(void)
{if (example_dir)proc_remove(example_dir);
}module_init(proc_test_init);
module_exit(proc_test_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("pan");
MODULE_DESCRIPTION("A simple example of procfs usage");

Makefile

KERNELDIR ?= /home/forlinx/OK3588_Linux_fs/kernelobj-m += proc_test.oall: modulesmodules:$(MAKE) ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- -C $(KERNELDIR) M=$(shell pwd) modulesmodules_install:$(MAKE) -C $(KERNELDIR) M=$(shell pwd) modules_installclean:$(MAKE) -C $(KERNELDIR) M=$(shell pwd) modules clean

测试验证:

# insmod proc_test.ko
# echo hello > /proc/test/data
# cat /proc/test/data
hello

总结

本篇我们学会了常用的procfs节点信息以及实践操作procfs节点例子,本篇学会的同学可以一键支持三连下,欢迎关注公众号[Linux随笔录],持续分享干货!


http://www.ppmy.cn/embedded/105118.html

相关文章

教你轻松玩转大学校园洗衣洗鞋市场

今天我们来讲讲轻松月入过万的洗鞋行业&#xff0c;是怎么样的商业模式。 首先在大学市场是一个很大的消费群体&#xff0c;而且现在绝大数年轻人都为洗鞋发愁&#xff0c;衣服可以放洗衣机&#xff0c;鞋子又不能直接扔进洗衣机去洗&#xff0c;从而就诞生了校园洗鞋这个行业风…

STM32嵌入式面试知识点总结

一、STM32F1和F4的区别&#xff1f; 解答&#xff1a; 参看&#xff1a;STM32开发 – STM32初识内核不同&#xff1a;F1是Cortex-M3内核&#xff0c;F4是Cortex-M4内核&#xff1b;主频不同&#xff1a;F1主频72MHz&#xff0c;F4主频168MHz&#xff1b;浮点运算&#xff1a;…

为什么说网络安全行业是IT行业最后的红利?

前言 2023年网络安全行业的前景看起来非常乐观。根据当前的趋势和发展&#xff0c;一些趋势和发展可能对2023年网络安全行业产生影响&#xff1a; 5G技术的广泛应用&#xff1a;5G技术的普及将会使互联网的速度更快&#xff0c;同时也将带来更多的网络威胁和安全挑战。网络安全…

探索贪心算法:解决优化问题的高效策略

贪心算法是一种在每一步选择中都采取当前最佳选择的算法&#xff0c;以期在整体上达到最优解。它广泛应用于各种优化问题&#xff0c;如最短路径、最小生成树、活动选择等。本文将介绍贪心算法的基本概念、特点、应用场景及其局限性。 贪心算法的基本概念 贪心算法的核心思想是…

【Docker镜像转存阿里云脚本】

脚本 #!/bin/bash# 设置环境变量 ALIYUN_REGISTRY"镜像仓库地址" ALIYUN_NAME_SPACE"命名空间" ALIYUN_REGISTRY_USER"用户名" ALIYUN_REGISTRY_PASSWORD"密码"# 文件路径 IMAGES_FILE_PATH"./images.txt" READY_IMAGE_FIL…

VM Workstation虚拟机AlmaLinux 9.4操作系统安装(桌面版安装详细教程)(宝塔面板的安装),填补CentOS终止支持维护的空白

目录 AlmaLinux介绍 AlmaLinux操作系统的安装 1、下载镜像文件 2、新建虚拟机 &#xff08;1&#xff09;点击创建新的虚拟机 &#xff08;2&#xff09;打开虚拟机向导后&#xff0c;选择“自定义”安装&#xff0c;然后点击“下一步” &#xff08;3&#xff09;选择虚…

解决npm下载依赖速度慢的问题

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

Git创建项目

方法一 1.在gitee中新建仓库demo01&#xff0c;并勾选开源许可证&#xff0c;完成后gitee上面的项目demo01里只包含一个LICENSE文件 2.直接在本地电脑中新建项目文件夹demo01&#xff0c;双击进入这个文件夹&#xff0c;右键Git bash here&#xff0c;输入 git clone https:…