Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4213210
  • 博文数量: 1148
  • 博客积分: 25453
  • 博客等级: 上将
  • 技术积分: 11949
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-06 21:14
文章分类

全部博文(1148)

文章存档

2012年(15)

2011年(1078)

2010年(58)

分类: LINUX

2011-12-16 19:09:18


《linux kernel procfs guide》手册: Linux+Kernel+Procfs+Guide.rar   

在《linux kernel procfs guide》手册的 reading data 章节:


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

  1. The read function should write its information into the page. For proper use, the function should start writing at an offset of off in page and write at most count bytes, but because most read functions are quite simple and only return a small amount of information, these two parameters are usually ignored (it breaks pagers like more and less, but cat still works).
在读函数中,应该把data数据写入到 page中。正确的用法是,函数应该考虑page中的offset偏移量,写入多少count字节。但是,因为在多数函数中仅仅返回很少的一点信息,这两个变量 off 和 count常常被忽视。我们可以使用 more less cat 读我们写入的数据。


  1. If the off and count parameters are properly used, eof should be used to signal that the end of the file has been reached by writing 1 to the memory location eof points to.
假如off和 count变量被使用到,变量eof应该被设置为1,


  1. The parameter start doesn’t seem to be used anywhere in the kernel. The data parameter can be used to create a single call back function for several files
  2. The read_func function must return the number of bytes written into the page.
参数start似乎并没有在内核中使用到。参数data可以被用来建立一个简单的回调函数

在read_func函数实现中,我们仅仅会使用 data 和 page 这两个参数,其他的较少使用到。

函数没有考虑到off偏移,所以当我们第一次写入“nihao”,再第二次写入“hello”的时候,hello就会完全覆盖“nihao”,所以read_func函数没有考虑到偏移


write_func
  1. int write_func (struct file* file, const char__user* buffer, unsigned long count, void* data);
  1. The write function should read countbytes at maximum from the buffer. Note that the buffer doesn’t live in the kernel’s memory space, so it should first be copied to kernel space with copy_from_user. The file parameter is usually ignored. 
写函数,应该从buffer缓存中读取最大的数据量。注意:缓存不存在内核空间内存中,因此,它首先应该通过 copy_from_user从用户空间复制。 而参数file常常被忽视,
将buffer中的数据写入到 data中,count参数定义了在 buff 中有多少数据要被写入
========================================================================

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

  1. //kernel module: procfs_exam.c
  2. //#include <linux/config.h>
  3. #include <linux/init.h>
  4. #include <linux/kernel.h>
  5. #include <linux/module.h>
  6. #include <linux/proc_fs.h>
  7. #include <linux/sched.h>
  8. #include <linux/types.h>
  9. #include <asm/uaccess.h>

  10. #define STR_MAX_SIZE 255
  11. static int int_var;
  12. static char string_var[256];
  13. static char big_buffer[65536];
  14. static int big_buffer_len = 0;
  15. static struct proc_dir_entry * myprocroot;
  16. static int first_write_flag = 1;

  17. int int_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
  18. {
  19.     count = sprintf(page, "%d", *(int *)data); //格式化打印
  20.     return count;
  21. }

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

  26.     while (count)
  27.     {
  28.         if (get_user(c, buffer)) //§?? 从用户空间读取数据
  29.          return -EFAULT;

  30.         len++;
  31.         buffer++;
  32.         count--;

  33.         if (c == 10 || c == 0) //10 字符 **,0 字符 空
  34.             break;
  35.         val = c - '0';
  36.         if (val > 9)
  37.             return -EINVAL;
  38.         sum *= 10;
  39.         sum += val;
  40.     }
  41.     *temp = sum;
  42.     return len;
  43. }

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

  49. int string_write_proc(struct file *file, const char __user *buffer, unsigned long count, void *data)
  50. {
  51.     if (count > STR_MAX_SIZE)
  52.     {
  53.         count = 255;
  54.     }
  55.     copy_from_user(data, buffer, count);
  56.     return count;
  57. }

  58. int bigfile_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
  59. {
  60.     if (off > big_buffer_len)
  61.     {
  62.         * eof = 1;
  63.         return 0;
  64.     }

  65.     if (count > PAGE_SIZE)
  66.     {
  67.         count = PAGE_SIZE;
  68.     }

  69.     if (big_buffer_len - off < count)
  70.     {
  71.         count = big_buffer_len - off;
  72.     }

  73.     memcpy(page, data, count);
  74.     *start = page;
  75.     return count;
  76. }

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

  80.     if (first_write_flag)
  81.     {
  82.         big_buffer_len = 0;
  83.         first_write_flag = 0;
  84.     }

  85.     if (65536 - big_buffer_len < count)
  86.     {
  87.         count = 65536 - big_buffer_len;
  88.         first_write_flag = 1;
  89.     }

  90.     copy_from_user(p + big_buffer_len, buffer, count);
  91.     big_buffer_len += count;
  92.     return count;
  93. }
  94. static int __init procfs_exam_init(void)
  95. {
  96.     #ifdef CONFIG_PROC_FS
  97.     struct proc_dir_entry * entry;
  98.     myprocroot = proc_mkdir("myproctest", NULL);
  99.     entry = create_proc_entry("aint", 0666, myprocroot);
  100.     if (entry)
  101.     {
  102.         entry->data = &int_var;
  103.         entry->read_proc = &int_read_proc;
  104.         entry->write_proc = &int_write_proc;
  105.     }

  106.     entry = create_proc_entry("astring", 0666, myprocroot);
  107.     if (entry)
  108.     {
  109.         entry->data = &string_var;
  110.         entry->read_proc = &string_read_proc;
  111.         entry->write_proc = &string_write_proc;
  112.     }

  113.     entry = create_proc_entry("bigprocfile", 0666, myprocroot);
  114.     if (entry)
  115.     {
  116.         entry->data = &big_buffer;
  117.         entry->read_proc = &bigfile_read_proc;
  118.         entry->write_proc = &bigfile_write_proc;
  119.     }
  120.     #else
  121.         printk("This module requires the kernel to support procfs,\n");
  122.     #endif

  123.     printk("exam init\n");
  124.     return 0;
  125. }

  126. static void __exit procfs_exam_exit(void)
  127. {
  128.     #ifdef CONFIG_PROC_FS
  129.     remove_proc_entry("aint", myprocroot);
  130.     remove_proc_entry("astring", myprocroot);
  131.     remove_proc_entry("bigprocfile", myprocroot);
  132.     remove_proc_entry("myproctest", NULL);
  133.     printk("exam exit\n");
  134.     #endif
  135. }

  136. module_init(procfs_exam_init);
  137. module_exit(procfs_exam_exit);
  138. MODULE_LICENSE("GPL");

  1. ywx@ywx:~/desktop/module/proc/proc_exam$ sudo insmod ./exam.ko
  2. ywx@ywx:~/desktop/module/proc/proc_exam$ echo 123456 > /proc/myproctest/aint
  3. ywx@ywx:~/desktop/module/proc/proc_exam$ cat /proc/myproctest/aint
  4. 123456ywx@ywx:~/desktop/module/proc/proc_exam$ echo "yuweixian" > /proc/myproctest/astring 
  5. ywx@ywx:~/desktop/module/proc/proc_exam$ cat /proc/myproctest/astring
  6. yuweixian
注意:这里的程序,echo 会覆盖前一次输入的数据
  1. ywx@ywx:~/desktop/module/proc/proc_exam$ sudo rmmod exam
  2. ywx@ywx:~/desktop/module/proc/proc_exam$ dmesg | tail -5
  3. [12474.351356] exam exit
  4. [12496.784603] exam init
  5. [12524.519173] exam exit
  6. [12534.649329] exam init
  7. [12617.528998] exam exit
  8. ywx@ywx:~/desktop/module/proc/proc_exam$







阅读(1904) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~