procfs是比较老的一种用户态与内核态的数据交换方式,内核的很多数据都是通过这种方式出口给用户的,内核的很多参数也是通过这种方式来让用户方便设置的。除了sysctl出口到/proc下的参数,procfs提供的大部分内核参数是只读的。实际上,很多应用严重地依赖于procfs,因此它几乎是必不可少的组件。本节将讲解如何使用procfs。
Procfs提供了如下API:

struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode, struct proc_dir_entry *parent)

该函数用于创建一个正常的proc条目,参数name给出要建立的proc条目的名称,参数mode给出了建立的该proc条目的访问权限,参数 parent指定建立的proc条目所在的目录。如果要在/proc下建立proc条目,parent应当为NULL。否则它应当为proc_mkdir 返回的struct proc_dir_entry结构的指针。

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

该函数用于删除上面函数创建的proc条目,参数name给出要删除的proc条目的名称,参数parent指定建立的proc条目所在的目录。

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

该函数用于创建一个proc目录,参数name指定要创建的proc目录的名称,参数parent为该proc目录所在的目录。

extern struct proc_dir_entry *proc_mkdir_mode(const char *name, mode_t mode, struct proc_dir_entry *parent)
 struct proc_dir_entry *proc_symlink(const char * name, struct proc_dir_entry* parent, const char *dest)

该函数用于建立一个proc条目的符号链接,参数name给出要建立的符号链接proc条目的名称,参数parent指定符号连接所在的目录,参数dest指定链接到的proc条目名称。

struct proc_dir_entry *create_proc_read_entry(const char *name, mode_t mode, struct proc_dir_entry *base,
read_proc_t *read_proc, void * data);

该函数用于建立一个规则的只读proc条目,参数name给出要建立的proc条目的名称,参数mode给出了建立的该proc条目的访问权限,参 数base指定建立的proc条目所在的目录,参数read_proc给出读去该proc条目的操作函数,参数data为该proc条目的专用数据,它将 保存在该proc条目对应的struct file结构的private_data字段中。

struct proc_dir_entry *create_proc_info_entry(const char *name, mode_t mode, struct proc_dir_entry *base,
get_info_t *get_info);

该函数用于创建一个info型的proc条目,参数name给出要建立的proc条目的名称,参数mode给出了建立的该proc条目的访问权限, 参数base指定建立的proc条目所在的目录,参数get_info指定该proc条目的get_info操作函数。实际上get_info等同于 read_proc,如果proc条目没有定义个read_proc,对该proc条目的read操作将使用get_info取代,因此它在功能上非常类似于函数create_proc_read_entry。

struct proc_dir_entry *proc_net_create(const char *name, mode_t mode, get_info_t *get_info)

该函数用于在/proc/net目录下创建一个proc条目,参数name给出要建立的proc条目的名称,参数mode给出了建立的该proc条目的访问权限,参数get_info指定该proc条目的get_info操作函数。

struct proc_dir_entry *proc_net_fops_create(const char *name, mode_t mode, struct file_operations *fops)

该函数也用于在/proc/net下创建proc条目,但是它也同时指定了对该proc条目的文件操作函数。

void proc_net_remove(const char *name)

该函数用于删除前面两个函数在/proc/net目录下创建的proc条目。参数name指定要删除的proc名称。
除了这些函数,值得一提的是结构struct proc_dir_entry,为了创建一了可写的proc条目并指定该proc条目的写操作函数,必须设置上面的这些创建proc条目的函数返回的指针 指向的struct proc_dir_entry结构的write_proc字段,并指定该proc条目的访问权限有写权限。
为了使用这些接口函数以及结构struct proc_dir_entry,用户必须在模块中包含头文件linux/proc_fs.h。
在源代码包中给出了procfs示例程序procfs_exam.c,它定义了三个proc文件条目和一个proc目录条目,读者在插入该模块后应当看到如下结构:

$ ls /proc/myproctest
aint astring bigprocfile
$

读者可以通过cat和echo等文件操作函数来查看和设置这些proc文件。特别需要指出,bigprocfile是一个大文件(超过一个内存
页),对于这种大文件,procfs有一些限制,因为它提供的缓存,只有一个页,因此必须特别小心,并对超过页的部分做特别的考虑,处理起来比较复杂并且
很容易出错,所有procfs并不适合于大数据量的输入输出,后面一节seq_file就是因为这一缺陷而设计的,当然seq_file依赖于 procfs的一些基础功能。

//kernel module: procfs_exam.c
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <asm/uaccess.h>

#define STR_MAX_SIZE 255
static int int_var;
static char string_var[256];
static char big_buffer[65536];
static int big_buffer_len = 0;
static struct proc_dir_entry * myprocroot;
static int first_write_flag = 1;

int int_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
{
count = sprintf(page, "%d", *(int *)data);
return count;
}

int int_write_proc(struct file *file, const char __user *buffer,unsigned long count, void *data)
{
unsigned int c = 0, len = 0, val, sum = 0;
int * temp = (int *)data;

while (count) {
if (get_user(c, buffer)) //从用户空间中得到数据
 return -EFAULT;

len++;
buffer++;
count--;

if (c == 10 || c == 0)
break;
val = c - '0';
if (val > 9)
return -EINVAL;
sum *= 10;
sum += val;
}
* temp = sum;
return len;
}

int string_read_proc(char *page, char **start, off_t off,int count, int *eof, void *data)
{
count = sprintf(page, "%s", (char *)data);
return count;
}

int string_write_proc(struct file *file, const char __user *buffer, unsigned long count, void *data)
{
if (count > STR_MAX_SIZE) {
count = 255;
}
copy_from_user(data, buffer, count);
return count;
}

int bigfile_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
{
if (off > big_buffer_len) {
* eof = 1;
return 0;
}

if (count > PAGE_SIZE) {
count = PAGE_SIZE;
}

if (big_buffer_len - off < count) {
count = big_buffer_len - off;
}

memcpy(page, data, count);
*start = page;
return count;

}

int bigfile_write_proc(struct file *file, const char __user *buffer, unsigned long count, void *data)
{
char * p = (char *)data;

if (first_write_flag) {
big_buffer_len = 0;
first_write_flag = 0;
}

if (65536 - big_buffer_len < count) {
count = 65536 - big_buffer_len;
first_write_flag = 1;
}

copy_from_user(p + big_buffer_len, buffer, count);
big_buffer_len += count;
return count;
}
static int __init procfs_exam_init(void)
{
#ifdef CONFIG_PROC_FS
struct proc_dir_entry * entry;
myprocroot = proc_mkdir("myproctest", NULL);
entry = create_proc_entry("aint", 0644, myprocroot);
if (entry) {
entry->data = &int_var;
entry->read_proc = &int_read_proc;
entry->write_proc = &int_write_proc;
}

entry = create_proc_entry("astring", 0644, myprocroot);
if (entry) {
entry->data = &string_var;
entry->read_proc = &string_read_proc;
entry->write_proc = &string_write_proc;
}

entry = create_proc_entry("bigprocfile", 0644, myprocroot);
if (entry) {
entry->data = &big_buffer;
entry->read_proc = &bigfile_read_proc;
entry->write_proc = &bigfile_write_proc;
}
#else
printk("This module requires the kernel to support procfs,\n");
#endif

return 0;
}

static void __exit procfs_exam_exit(void)
{
#ifdef CONFIG_PROC_FS
remove_proc_entry("aint", myprocroot);
remove_proc_entry("astring", myprocroot);
remove_proc_entry("bigprocfile", myprocroot);
remove_proc_entry("myproctest", NULL);
#endif
}

module_init(procfs_exam_init);
module_exit(procfs_exam_exit);
MODULE_LICENSE("GPL");

用户空间与内核空间数据交换的方式(2)------procfs相关推荐

  1. 用户空间与内核空间数据交换的方式(zz)

    用户空间与内核空间数据交换的方式(1)------debugfs 用户空间与内核空间数据交换的方式(2)------procfs 用户空间与内核空间数据交换的方式(3)------seq_file 用 ...

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

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

  3. 用户空间与内核空间数据交换的方式(9)------netlink【转】

    转自:http://www.cnblogs.com/hoys/archive/2011/04/10/2011722.html Netlink 是一种特殊的 socket,它是 Linux 所特有的,类 ...

  4. 用户空间与内核空间数据交换的方式(1)------debugfs

    内核开发者经常需要向用户空间应用输出一些调试信息,在稳定的系统中可能根本不需要这些调试信息,但是在开发过程中,为了搞清楚内核的行为,调试信息非常必要,printk可能是用的最多的,但它并不是最好的,调 ...

  5. 用户空间与内核空间数据交换的方式------seq_file

    一般地,内核通过在procfs文件系统下建立文件来向用户空间提供输出信息,用户空间可以通过任何文本阅读应用查看该文件信息,但是procfs 有一个缺陷,如果输出内容大于1个内存页,需要多次读,因此处理 ...

  6. 用户空间与内核空间数据交换-2-generic netlink

    转载自 : http://blog.chinaunix.net/uid-28541347-id-5589868.html https://blog.csdn.net/ty3219/article/de ...

  7. linux 物理内存用完了_Linux用户空间与内核空间(理解高端内存)

    Linux内核地址映射模型 x86 CPU采用了段页式地址映射模型.进程代码中的地址为逻辑地址,经过段页式地址映射后,才真正访问物理内存. 段页式机制如下图. Linux内核地址空间划分 通常32位L ...

  8. (整理)用户空间_内核空间以及内存映射

    内核空间和用户空间   现代操作系统采用虚拟存储器,对于32位操作系统而言,它的寻址空间(虚拟存储空间)为4G(2的32次方).操作系统的核心是内核,独立于普通的应用程序,可以访问受保护的内存空间,也 ...

  9. linux 内核将两个设备相关联,linux用户空间和内核空间交换数据

    转载地址:http://www.poluoluo.com/server/201107/138420.html 在研究dahdi驱动的时候,见到了一些get_user,put_user的函数,不知道其来 ...

最新文章

  1. 最长不含重复字符的子字符串
  2. 【原创】项目管理得失经验总结
  3. linux开启内部路由转发功能
  4. Java程序员需要掌握的计算机底层知识(一):CPU基本组成、指令乱序执行、合并写技术、非同一访问内存 NUMA
  5. 游牧大地的诗意:看龙力游的草原油画
  6. asp.net core AuthenticationMiddleware 在WebApi中的的使用
  7. hackintosh黑苹果_为什么您的下一个Mac应该是Hackintosh?
  8. properties加载的几种方式
  9. BULK INSERT, 实战手记:让百万级数据瞬间导入SQL Server
  10. jQuery--捕获键盘敲击
  11. iconv的用法,'GBK'转'utf-8'
  12. 系统调用 操作系统课程设计 Linux内核编译 centos Ubuntu
  13. HTMl 实现用户的登录注册界面
  14. Android 最常用的设计模式十 安卓源码分析——策略模式(Strategy)
  15. centos、Windows双系统安装及修复引导启动项
  16. [动态树] HDOJ 5467 Clarke and hunger games
  17. 20180710使用gh
  18. 力扣 LCP 42. 玩具套圈 (数学公式反推)
  19. linux中安装redis 使用make install 命令报错
  20. Google Chrome浏览器的回退功能快捷键

热门文章

  1. Ubuntu禁用网卡步骤(重启依然生效)
  2. 为什么实验是领英 DNA 的核心部分?
  3. 从技术到产品,转型的这一年我明白了很多道理
  4. PHP和MySQL Web开发从新手到高手,第1天-搭建PHP开发环境
  5. 一步一步重写 CodeIgniter 框架 (2) —— 实现简单的路由功能
  6. 测测实际带宽,预防使用“假带宽”
  7. FLASH AS3 TextField
  8. Python : 反斜杠
  9. shared_ptr使用场景、陷阱、性能分析,使用建议
  10. mysql5.7延迟_[MySQL] 号称永久解决了复制延迟问题的并行复制,MySQL5.7-阿里云开发者社区...