目录

简介

一、 procfs

1、proc文件系统的功能

2、proc文件值的修改与查看

3、procfs文件系统的优缺点

二、 API

三、procfs编程示例

1、实现的功能:

2、源码


简介

用户空间与内核的交互方式,使用copy_from_user(), copy_to_user().

除了这两种交互方式,内核还提供了其他高级的方式,对于写驱动来说很重要。有proc、sysfs、debugfs、netlink、ioctl。

本文学习procfs


一、 procfs

在命令行下可以看到procfs下的内容,整数代表当前活动的进程。

root@ubuntu:/proc# ls
1     128    144    15868  18    1914  2030   2119   2310   25028  2540  277  295  311   328   41    4667  53   860  963            fb           misc               sysvipc
10    13     145    159    180   1922  2038   2127   23152  25062  2561  278  296  312   329   42    467   54   862  996            filesystems  modules            thread-self
1020  130    146    15951  1809  1938  2045   2133   23154  25064  2565  28   297  313   330   424   469   55   866  997            fs           mounts             timer_list
1061  1308   147    16     181   1940  2048   2137   2384   25068  2566  280  298  314   34    4261  47    553  867  acpi           interrupts   mpt                tty
6    873  bus            kallsyms     partitions         vmallocinfo

文件夹下/proc/PID 包含有关进程的信息。通过man 5 proc可以查看相应的文档介绍。

1、proc文件系统的功能

  • 接口简单,能够获得内核中的进程、硬件信息;
  • 在root权限下,子文件下有各种内核参数,这个特性叫sysctl,如IPV4网络参数的目录/proc/sys/net/ipv4;

2、proc文件值的修改与查看

# cat /proc/sys/kernel/threads-max
15741
# echo 10000 > /proc/sys/kernel/threads-max
# cat /proc/sys/kernel/threads-max
10000
#

备注: 修改的值是临时的,系统重启后将恢复到默认值。

3、procfs文件系统的优缺点

优点:

功能强大,容易编程的接口。通常用来输出状态,调试内核系统。

缺点:

在2.6内核后,不再使用proc 文件系统,其原因是不保证正确性和稳定性。


二、 API

头文件:

#include <linux/proc_fs.h>
  • 在proc文件系统下创建目录
struct proc_dir_entry *proc_mkdir(const char *name,struct proc_dir_entry *parent);
  • 创建procfs的文件
struct proc_dir_entry *proc_create(const char *name, umode_t mode,struct proc_dir_entry *parent,const struct file_operations *proc_fops);
  • 删除目录
void remove_proc_entry(const char *name, struct proc_dir_entry *parent)

三、procfs编程示例

1、实现的功能:

通过proc文件系统,动态控制debug_level的值

创建 procfs_simple_dir文件夹,

  • 创建debug_level文件,动态查询、设置debug_level
  • 创建debug_only_read文件,只读;

2、源码


#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mutex.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>  /* procfs APIs etc */
#include <linux/seq_file.h>#include <linux/uaccess.h>
MODULE_AUTHOR("wy");
MODULE_DESCRIPTION("simple procfs interfacing demo");
MODULE_LICENSE("Dual MIT/GPL");
MODULE_VERSION("0.1");//文件夹
#define PROC_DIR "procfs_simple_dir"
//文件
#define PROC_FILE "debug_level"
//属性
#define PROC_FILE_PARAMS 0600#define PROC_FILE1 "debug_only_read"
#define PROC_FILE1_PARAMS1 0444//互斥体
DEFINE_MUTEX(mtx);//全局的debug_level,可动态修改
static int debug_level;//debug_level的调整范围
#define DEBUG_LEVEL_MIN         0
#define DEBUG_LEVEL_MAX         2
#define DEBUG_LEVEL_DEFAULT     DEBUG_LEVEL_MIN
static ssize_t proc_write_dbg_level(struct file * filp,const char __user *ubuf,size_t count,loff_t *off)
{char buf[12];int ret = count;//互斥体保护数据if(mutex_lock_interruptible(&mtx))return -ERESTARTSYS;if(count == 0 || count > 12){ret = -EINVAL;goto out;}//从用户接收数据if(copy_from_user(buf,ubuf,count)){ret = -EFAULT;goto out;}buf[count - 1]='\0';pr_debug("user sent mesg=%s\n",buf);//内核中奖字符型转化为int型ret = kstrtoint(buf,0,&debug_level);if(ret)goto out;//debug_level的范围验证if(debug_level < DEBUG_LEVEL_MIN || debug_level > DEBUG_LEVEL_MAX){pr_info("set vaild value");debug_level = DEBUG_LEVEL_DEFAULT;ret = -EFAULT;goto out;}//use userspace value//xxxxxret = count;
out://解锁mutex_unlock(&mtx);return ret;
}
//显示debug_level的函数
static int proc_show_debug_level(struct seq_file *seq,void *v)
{if(mutex_lock_interruptible(&mtx))return -ERESTARTSYS;//通过seq_printf,将debug_level参数赋赋值到seqseq_printf(seq,"debug_level:%d\n",debug_level);mutex_unlock(&mtx);return 0;
}static int proc_open_dbg_level(struct inode *inode,struct file *file)
{//打开文件file,回调函数proc_show_debug_levelreturn single_open(file,proc_show_debug_level,NULL);
}//fops的函数 seq_xxx是内核提供的函数,
static const struct proc_ops fops_dbg_level =
{.proc_open = proc_open_dbg_level,.proc_read = seq_read,.proc_write= proc_write_dbg_level,.proc_lseek = seq_lseek,.proc_release = single_release,
};//read only
static int proc_show_pgoff(struct seq_file *seq, void *v)
{seq_printf(seq, "%s:PAGE_OFFSET:0x%px\n", PROC_DIR, PAGE_OFFSET);return 0;
}//函数的初始化
static int __init procfs_simple_intf_init(void)
{int stat = 0;static struct proc_dir_entry * procdir;//检测procfs文件系统有没有配置if(unlikely(!(IS_ENABLED(CONFIG_PROC_FS)))){pr_warn("procfs not supported!\n");return -EINVAL;}//创建proc下的目录procdir = proc_mkdir(PROC_DIR,NULL);if(!procdir){pr_warn("proc_mkdir failed,aborting...\n");stat = -ENOMEM;goto out_fail_1;}pr_debug("proc dir (/proc/%s) created\n",PROC_DIR);//创建文件PROC_FILE,属性为PROC_FILE_PARAMS, fops_dbg_level函数注册if(!proc_create(PROC_FILE,PROC_FILE_PARAMS,procdir,&fops_dbg_level)){pr_warn("proc_create failed,aborting...\n");stat = -ENOMEM;goto out_fail_1;}pr_debug("proc file (/proc/%s/%s) created\n",PROC_DIR,PROC_FILE);//read only                              PROC_FILE1_PARAMS1//API  proc_create_single_dataif (!proc_create_single_data(PROC_FILE1, PROC_FILE1_PARAMS1,procdir, proc_show_pgoff, 0)) {pr_warn("proc_create [2] failed, aborting...\n");stat = -ENOMEM;goto out_fail_1;}pr_debug("proc file 3 (/proc/%s/%s) created\n", PROC_DIR, PROC_FILE1);out_fail_1:return stat;
}//退出时处理
static void __exit procfs_simple_intf_cleanup(void)
{remove_proc_subtree(PROC_DIR, NULL);pr_info("removed\n");
}module_init(procfs_simple_intf_init);
module_exit(procfs_simple_intf_cleanup);

Linux用户与内核空间交互—procfs相关推荐

  1. Linux用户与内核空间交互—netlink

    目录 简介 一.netlink soket 优点 二.用户空间 1.API 2.编程流程 3.源码 三.内核编程 1.API 2.内核空间编程流程 3.内核源码 简介 用户空间与内核的交互方式,使用c ...

  2. Linux用户与内核空间交互—sysfs

    目录 简介 一.sysfs 1./sys 目录 2.API 3.platform  API 4.创建platform总线设备文件 二.程序源码 简介 用户空间与内核的交互方式,使用copy_from_ ...

  3. linux 用户态 内核态 通信,procfs(从0开始,内核态和用户态通信charpter2)

    这篇博文将针对linux内核态与用户态通信方式中的procfs进行详细的学习. /proc主要存放内核的一些控制信息,所以这些信息大部分的逻辑位置位于内核控制的内存,在/proc下使用ls -l你会发 ...

  4. 跟踪 linux 内核调用_Linux用户和内核空间中的动态跟踪

    跟踪 linux 内核调用 您是否曾经遇到过这样的情况,即您意识到没有在代码中的某些点插入调试打印 ,所以现在您将不知道您的CPU是否命中了特定的代码行来执行,直到您重新编译该代码为止.调试语句? 不 ...

  5. linux内核dma内存分配,Linux 4.x 内核空间 DMA 虚拟内存地址

    Architecture: i386 32bit Machine Ubuntu 16.04 Linux version: 4.15.0-39-generic 目录 DMA 虚拟内存区 在 IA32 体 ...

  6. Linux 用户进程内存空间详解

    经常使用top命令了解进程信息,其中包括内存方面的信息.命令top帮助文档是这么解释各个字段的. VIRT , Virtual Image (kb) RES, Resident size (kb) S ...

  7. linux内存非线性映射到文件,Linux 4.x 内核空间 FIXUP 固定映射和临时映射虚拟内存...

    Architecture: i386 32bit Machine Ubuntu 16.04 Linux version: 4.15.0-39-generic 目录 FIXUP 虚拟内存区 在 IA32 ...

  8. 用户空间和内核空间通讯之【proc文件系统】

    今天我们介绍另一种用户内核空间通信的方法:proc文件系统. proc文件系统作为linux提供的一种虚拟文件系统并不占用实际外围存储空间,它仅存在于内存中,系统断电即消失.proc文件系统最开始的设 ...

  9. linux内核空间和用户空间的是怎样区别的,如何交互,如何从用户空间进入内核空间

    linux驱动程序一般工作在内核空间,但也可以工作在用户空间.下面我们将详细解析,什么是内核空间,什么是用户空间,以及如何判断他们. Linux简化了分段机制,使得虚拟地址与线性地址总是一致,因此,L ...

  10. linux 内核空间 sy,在 Linux 下用户空间与内核空间数据交换的方式,第 1 部分: 内核启动参数、模块参数与sysf...

    级别: 初级 燚 杨 (), 计算机科学硕士 2006 年 2 月 16 日 本系列文章包括两篇,它们文详细地介绍了 Linux 系统下用户空间与内核空间数据交换的九种方式,包括内核启动参数.模块参数 ...

最新文章

  1. 【里程碑式证明】同时解决了量子物理学和理论数学的难题!
  2. SQL实现分组查询取前几条记录
  3. 用c语言实现单链表的初始化,建表,查找,求长度,插入,删除等操作,【YTU+2430+C语言习题+链表建立+插入+删除+输(5)...
  4. MySQL 高级 - 索引 - 索引语法
  5. Zookeeper分布式锁的使用
  6. Vue自定义指令原来这么简单
  7. 排序算法以及基本数据结构
  8. php5.6 xdebug 配置,php5.5+apache2.4+mysql5.6+xdebug配置
  9. 扒一扒面向对象编程的另一面
  10. OO Summary (Homework 5-7)
  11. response.setHeader()的用法 (转别人转的)
  12. 几款好用的敏捷开发工具
  13. 复变函数的极限和连续
  14. MindManager 思维导图全面介绍
  15. (两百五十六)学习perfetto(一)
  16. HTML5期末大作业:美妆网页主题网站设计——清新的手工肥皂网站展示(4页)HTML+CSS+JavaScript...
  17. 仿网易云音乐源码html5
  18. Java 实现HTTP请求的四种方式总结
  19. IPC分类—2018最新版IPC分类查询工具
  20. CSS3JavaScript 电池充电

热门文章

  1. 江西师范大学教育心理测量计算机,江西师范大学重点和特色专业介绍
  2. 什么是云服务器?什么是阿里云服务器管理?
  3. java小练习:乘法表的实现(不止是9)
  4. neu计算机硕士,BC省可直接移民的硕士专业-NEU-Align计算机硕士
  5. linux连接蓝牙设备,Linux 下连接蓝牙设备
  6. IMX6Q上蓝牙设备测试
  7. Android 12 WiFi 架构
  8. Android 2 时代到来了,敢为天下先是我等求知若渴的程序员的优秀品质
  9. 【JVM系列JKD8】参数参考表
  10. Ubuntu菜鸟入门(七)—— 微信安装