忘记密码   免费注册 查看新帖 | 论坛精华区

ChinaUnix.net

  平台 论坛 博客 认证专区 大话IT HPC论坛 徽章 文库 沙龙 自测 下载 频道自动化运维 虚拟化 储存备份 C/C++ PHP MySQL 嵌入式 Linux系统
最近访问板块 发新帖
楼主: superwujc

[文件系统] 创建proc项,write函数调用copy_from_user读取换行符的疑问 [复制链接]

论坛徽章:
0
发表于 2017-03-30 13:18 |显示全部楼层
回复 10# superwujc

。。。请看5楼。啊 自己实现。
不确定使用空间大小的安全做法就是使用 环形链表。






论坛徽章:
11
摩羯座
日期:2013-09-29 17:39:09白羊座
日期:2014-11-13 09:38:14技术图书徽章
日期:2014-01-17 15:07:36狮子座
日期:2013-12-25 14:01:52技术图书徽章
日期:2013-12-17 11:33:22技术图书徽章
日期:2013-12-03 10:27:57天秤座
日期:2013-11-08 15:47:19申猴
日期:2013-10-29 13:16:32未羊
日期:2013-10-12 22:28:56辰龙
日期:2013-10-09 14:39:5515-16赛季CBA联赛之山东
日期:2016-07-25 10:23:00
发表于 2017-03-30 13:25 |显示全部楼层
回复 11# nuclearxin

刚才搞错了,其实任何情况下,read都会执行2次的,最后一次读取遇到EOF,返回0
  1. echo -ne "a b c \n d e \n f \n gh \n wxyz" > /proc/hello
  2. [root@super memory]# cat /proc/hello
  3. wxyz[root@super memory]# dmesg
  4. [87130.808871] buf size: 1613
  5. [87130.808875] write
  6. [87130.808876] count = 7
  7. [87130.808877] strlen(msg) = 16
  8. [87130.808881] buf size: 1613
  9. [87130.808882] write
  10. [87130.808883] count = 6
  11. [87130.808883] strlen(msg) = 16
  12. [87130.808887] buf size: 1613
  13. [87130.808888] write
  14. [87130.808889] count = 4
  15. [87130.808889] strlen(msg) = 16
  16. [87130.808894] buf size: 1613
  17. [87130.808894] write
  18. [87130.808895] count = 5
  19. [87130.808896] strlen(msg) = 16
  20. [87130.808901] buf size: 1613
  21. [87130.808901] write
  22. [87130.808902] count = 5
  23. [87130.808903] strlen(msg) = 16
  24. [87134.014814] read
  25. [87134.014819] count = 5
  26. [87134.014820] strlen(msg) = 16
  27. [87134.014840] read
  28. [87134.014841] count = 0
  29. [87134.014842] strlen(msg) = 16
复制代码

write会把user buf中最后一个'\n'之后的内容实际写入,覆盖掉'\n'之前的内容
所以read会返回最后一个'\n'之后的内容


另外,ring buf可有样例供参考?多谢

论坛徽章:
11
摩羯座
日期:2013-09-29 17:39:09白羊座
日期:2014-11-13 09:38:14技术图书徽章
日期:2014-01-17 15:07:36狮子座
日期:2013-12-25 14:01:52技术图书徽章
日期:2013-12-17 11:33:22技术图书徽章
日期:2013-12-03 10:27:57天秤座
日期:2013-11-08 15:47:19申猴
日期:2013-10-29 13:16:32未羊
日期:2013-10-12 22:28:56辰龙
日期:2013-10-09 14:39:5515-16赛季CBA联赛之山东
日期:2016-07-25 10:23:00
发表于 2017-03-30 13:49 |显示全部楼层
本帖最后由 superwujc 于 2017-03-30 13:51 编辑

回复 11# nuclearxin

哈喽,proc的文件内容操作函数是固定的,read和write的原型也是内核定义好的,换言之,写死的
  1. const struct file_operations *proc_fops;
复制代码
  1. ssize_t (*read) (struct file *file, char __user *buf, size_t count, loff_t *offset);
  2. ssize_t (*write) (struct file *file, const char __user *buf, size_t count, loff_t *offset);
复制代码

read从file中读取count字节到buf中,并更新offset
write将buf中的count字节写入到file中,并更新offset
buffer都在用户空间

问下环形缓冲区在这怎么用?

论坛徽章:
0
发表于 2017-03-30 14:09 来自手机 |显示全部楼层
你想复杂了。不会修改任何 内核机制啊。修改你的module code。一会我写个。

论坛徽章:
0
发表于 2017-03-30 14:09 来自手机 |显示全部楼层
你想复杂了。不会修改任何 内核机制啊。修改你的module code。一会我写个。

论坛徽章:
0
发表于 2017-03-30 14:10 来自手机 |显示全部楼层
你想复杂了。不会修改任何 内核机制啊。修改你的module code。一会我写个。

论坛徽章:
11
摩羯座
日期:2013-09-29 17:39:09白羊座
日期:2014-11-13 09:38:14技术图书徽章
日期:2014-01-17 15:07:36狮子座
日期:2013-12-25 14:01:52技术图书徽章
日期:2013-12-17 11:33:22技术图书徽章
日期:2013-12-03 10:27:57天秤座
日期:2013-11-08 15:47:19申猴
日期:2013-10-29 13:16:32未羊
日期:2013-10-12 22:28:56辰龙
日期:2013-10-09 14:39:5515-16赛季CBA联赛之山东
日期:2016-07-25 10:23:00
发表于 2017-03-30 14:33 |显示全部楼层
回复 16# nuclearxin


给力大神,有劳有劳

论坛徽章:
0
发表于 2017-03-31 14:08 |显示全部楼层
本帖最后由 nuclearxin 于 2017-03-31 14:23 编辑
  1. 有点问题
复制代码

论坛徽章:
0
发表于 2017-03-31 14:09 |显示全部楼层
本帖最后由 nuclearxin 于 2017-03-31 14:31 编辑
  1. linux-mkov:~/jerry # cat hh.c
  2. #include <linux/module.h>
  3. #include <linux/mm.h>
  4. #include <linux/gfp.h>
  5. #include <linux/kernel.h>
  6. #include <linux/proc_fs.h>
  7. #include <asm/uaccess.h>
  8. #include <linux/slab.h>
  9. #include <linux/string.h>



  10. struct cir_list {
  11.   unsigned int num ;
  12.   struct list_head * cir_entry ;
  13.   struct list_head * write;
  14.   struct list_head * read;
  15. };

  16. struct cir_node {
  17.   struct list_head list;
  18.   int w_off_set ;
  19.   int r_off_set ;
  20.   char * buff ;
  21.   int ok ;
  22. };

  23. struct cir_list * jerry;


  24. int add_node (struct cir_list *c, struct cir_node * n)
  25. {
  26.   if(c == NULL) return 0;
  27.   if(n == NULL) return 0;


  28.   if(c->cir_entry == NULL){
  29.     c->cir_entry = &n->list;
  30.     c->write = &n->list;
  31.     c->read = &n->list;
  32.     printk("create the first node\n");
  33.     return 1;
  34.   }else {
  35.     printk("add the new node to the list\n");
  36.     list_add(&n->list,c->cir_entry);
  37.     c->num +=1;
  38.     printk("the num of c %d \n", c->num);
  39.     return 1;
  40.   }

  41. }

  42. struct cir_list * gen_cir(int n){

  43.   struct cir_list * hello_list;

  44.   hello_list = kmalloc(sizeof(struct cir_list),GFP_KERNEL);

  45.   if(hello_list == NULL){
  46.     return NULL;
  47.   }
  48.   //init the list
  49.   hello_list->cir_entry = NULL;
  50.   hello_list->write = NULL;
  51.   hello_list->num = 0;
  52.   hello_list->read = NULL;

  53.   struct cir_node * hello_node;
  54.   int i;
  55.   
  56.   printk("start to generate nodes  in total %d \n",n);

  57.   for(i=0;i<n;i++){
  58.     printk("start to generate %d \n",i);
  59.     hello_node = kmalloc(sizeof(struct cir_node),GFP_KERNEL);
  60.     if(hello_node == NULL) {
  61.       printk("not enough mem\n");
  62.      //TO DO #free all the node already allocated;
  63.       return NULL;
  64.     }
  65.     //init the node
  66.     hello_node->list.next = &hello_node->list;
  67.     hello_node->list.prev = &hello_node->list;
  68.     hello_node->w_off_set = 0;
  69.     hello_node->r_off_set = 0;
  70.     hello_node->buff = get_zeroed_page(GFP_KERNEL);
  71.     hello_node->ok = 1;
  72.     printk("start to generate %d  add_node func\n",i);
  73.     add_node(hello_list,hello_node);
  74.   }

  75.   return hello_list;

  76. }


  77. void clean_list_node(struct cir_list * c)
  78. {
  79.   struct cir_node * n;
  80.   struct list_head * l;
  81.   printk("start to free\n");

  82.   list_for_each(l,c->cir_entry) {
  83.     printk("in for each loop free\n");
  84.     n = list_entry(l, struct cir_node, list);
  85.     if(n==NULL) return;
  86.     free_page(n->buff);
  87.     printk("in for each loop free free_page\n");
  88.     kfree(n);
  89.     printk("in for each loop free node\n");
  90.   }

  91.   printk("out for each loop free list\n");

  92.   //free the head
  93.   printk("free the head \n");
  94.   n = list_entry(c->cir_entry, struct cir_node, list);
  95.   free_page(n->buff);
  96.   printk("head free_page\n");
  97.   kfree(n);
  98.   printk("head node\n");
  99.   kfree(c);
  100.   printk("free the list descriptor\n");
  101. }


  102. void write_end(char * buff ,size_t count ,struct cir_list * l )
  103. {

  104.   printk("----------------------------------start write--------------------------------\n" );

  105.   unsigned int done=0;
  106.   unsigned int left_sp_node;
  107.   struct cir_node * t_node;
  108.   t_node = list_entry(l->write,struct cir_node,list);
  109.   left_sp_node = 4096 - t_node->w_off_set;
  110.   printk("the left space : %d , woffset : %d\n",left_sp_node,t_node->w_off_set );
  111.   
  112.   while(count > left_sp_node){
  113.   
  114.       printk("----------------------------------loops--------------------------------\n" );
  115.       printk(" value lengh %d is bigger than left space %d\n",count,left_sp_node);
  116.       copy_from_user(t_node->buff + t_node->w_off_set,buff+done,left_sp_node);
  117.       printk(" count %d is decrease space\n",count,left_sp_node);
  118.       count -= left_sp_node;   
  119.       t_node->w_off_set += left_sp_node;
  120.       done += left_sp_node;
  121.       t_node = list_entry(t_node->list.next,struct cir_node,list);
  122.       t_node->r_off_set = 0;
  123.       t_node->w_off_set = 0;
  124.       left_sp_node = 4096 - t_node->w_off_set;
  125.       printk("----------------------------------loope--------------------------------\n" );
  126.    
  127.   }
  128.   
  129.   printk(" value length %d is small than left space %d\n",count,left_sp_node);
  130.   printk(" --start to append value %d  at offset %d---\n",count,t_node->w_off_set );
  131.   copy_from_user(t_node->buff + t_node->w_off_set,buff+done,count);
  132.   t_node->w_off_set += count;
  133.   done += count;
  134.   printk(" finshed append %d , all done is %d in this time\n",count,done);
  135.   l->write = &t_node->list;
  136.   printk("----------------------------------end--------------------------------\n" );
  137.   return 1;
  138.   
  139. }

  140. int read_to_write (struct cir_list * l,char * buff,size_t count)
  141. {
  142.   
  143.   struct cir_node * t_node;
  144.   int o_left;

  145.   t_node = list_entry(l->read,struct cir_node,list);
  146.   
  147.   if(l->read != l->write){
  148.     printk("cross read\n");

  149.     o_left = 4096 - t_node->r_off_set;
  150.     printk("cross read this node have left %d , the request count is %d \n",o_left,count);

  151.     printk("cross area read  woffset : %d , roffset : %d \n",t_node->w_off_set,t_node->r_off_set);
  152.     if(count <= o_left){
  153.       printk("cross read count is <= o_left \n");
  154.       copy_to_user(buff,t_node->buff + t_node->r_off_set,count);
  155.       printk("cross area read  copy to user %d \n",count);
  156.       t_node->r_off_set += count;
  157.       return count;
  158.     }else{
  159.       copy_to_user(buff ,t_node->buff + t_node->r_off_set,o_left);
  160.       t_node->r_off_set = 4096;
  161.       t_node = list_entry(t_node->list.next,struct cir_node,list);
  162.       l->read  = &t_node->list;
  163.       return o_left;
  164.     }

  165.   } else {

  166.     printk("same area read\n");
  167.     o_left = t_node->w_off_set - t_node->r_off_set;
  168.     printk("same area read  woffset : %d , roffset : %d \n",t_node->w_off_set,t_node->r_off_set);
  169.     if(o_left==0) return 0;

  170.     if(count <= o_left){
  171.       copy_to_user(buff,t_node->buff + t_node->r_off_set,count);
  172.       t_node->r_off_set += count;
  173.       return count;
  174.     }else{
  175.       copy_to_user(buff ,t_node->buff + t_node->r_off_set,o_left);
  176.       t_node->r_off_set += o_left;
  177.       return o_left;
  178.     }
  179.   
  180.   }
  181.   

  182. }
  183. int read_proc(struct file *filp,char *buf,size_t count,loff_t *offp)
  184. {
  185.   printk("read\n");
  186.   int real_count;
  187.   real_count = read_to_write(jerry,buf,count);
  188.   return real_count;
  189. }

  190. int write_proc(struct file *filp,const char *buf,size_t count,loff_t *offp)
  191. {
  192.         printk("write\n");
  193.         write_end(buf,count,jerry);           
  194.         return count;
  195. }

  196. struct file_operations proc_fops = {
  197.         read: read_proc,
  198.         write: write_proc
  199. };


  200. void create_new_proc_entry()
  201. {
  202.         proc_create("hello",0,NULL,&proc_fops);
  203. }
  204. int proc_init (void) {
  205.         
  206.         jerry = gen_cir(4);
  207.         create_new_proc_entry();
  208.         return 0;
  209. }

  210. void proc_cleanup(void) {
  211.         remove_proc_entry("hello",NULL);
  212.         clean_list_node(jerry);
  213. }

  214. MODULE_LICENSE("GPL");
  215. module_init(proc_init);
  216. module_exit(proc_cleanup);
复制代码

论坛徽章:
0
发表于 2017-03-31 14:15 |显示全部楼层
我申请了4个page大小的空间作为 buff。你自己随意分配吧。

也是新手。。学习玩了
您需要登录后才可以回帖 登录 | 注册

本版积分规则

SACC2017购票8.8折优惠进行时

2017中国系统架构师大会(SACC2017)将于10月19-21日在北京新云南皇冠假日酒店震撼来袭。今年,大会以“云智未来”为主题,云集国内外顶级专家,围绕云计算、人工智能、大数据、移动互联网、产业应用等热点领域展开技术探讨与交流。本届大会共设置2大主会场,18个技术专场;邀请来自互联网、金融、制造业、电商等多个领域,100余位技术专家及行业领袖来分享他们的经验;并将吸引4000+人次的系统运维、架构师及IT决策人士参会,为他们提供最具价值的交流平台。
----------------------------------------
优惠时间:2017年8月2日前

活动链接>>
  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号 北京市公安局海淀分局网监中心备案编号:11010802020122
广播电视节目制作经营许可证(京) 字第1234号 中国互联网协会会员  联系我们:
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP