免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1885 | 回复: 4
打印 上一主题 下一主题

[内核模块] 编写内核模块,获取磁盘的disk_stats信息 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-05-19 16:35 |只看该作者 |倒序浏览

我正在写一个内核模块,基于linux 2.6.32。这个模块的功能是获取所有磁盘的disk_stats,最后展示的结果与文件/sys/block/sda/stat的内容相似。

想问一下,对于block device,有没有类似于for_each_netdev的宏/函数,因为一台机器可能有多个磁盘,我需要遍历这些磁盘。或者,有没有什么方法可以根据块设备的名字(比如sda)获取到相应的数据结构。一块磁盘的disk_stats,存放在struct hd_struct,如何获取到这个hd_struct?

我看了linux2.6.32/block/genhd.c,/sys/block/sda/stat的内容是由genhd.c的diskstats_show函数产生的,不过这个函数被调用的时候,第二个参数应该是什么?如何获取到这个参数?

对于block device,linux 2.4有一个全局变量gendisk_head,但是linux2.6好像找不到了。

求大牛帮忙,感激不尽。

论坛徽章:
9
辰龙
日期:2014-08-18 20:38:42未羊
日期:2014-09-04 08:50:45丑牛
日期:2014-09-06 00:12:55寅虎
日期:2014-12-22 20:50:56摩羯座
日期:2015-01-14 22:28:15巳蛇
日期:2015-01-23 20:39:272015年辞旧岁徽章
日期:2015-03-03 16:54:1515-16赛季CBA联赛之青岛
日期:2016-03-13 23:37:1915-16赛季CBA联赛之深圳
日期:2016-03-29 18:52:38
2 [报告]
发表于 2014-05-19 22:18 |只看该作者
回复 1# motorn

你要的东西就在genhd.c这个文件里。
  1. /*
  2. * aggregate disk stat collector.  Uses the same stats that the sysfs
  3. * entries do, above, but makes them available through one seq_file.
  4. * Watching a few disks may be efficient through sysfs, but watching
  5. * all of them will be more efficient through this interface.
  6. *
  7. * The output looks suspiciously like /proc/partitions with a bunch of
  8. * extra fields.
  9. */

  10. /* iterator */
  11. static void *diskstats_start(struct seq_file *part, loff_t *pos)
  12. {
  13.         loff_t k = *pos;
  14.         struct list_head *p;

  15.         mutex_lock(&block_subsys_lock);
  16.         list_for_each(p, &block_subsys.list)
  17.                 if (!k--)
  18.                         return list_entry(p, struct gendisk, kobj.entry);
  19.         return NULL;
  20. }

  21. static void *diskstats_next(struct seq_file *part, void *v, loff_t *pos)
  22. {
  23.         struct list_head *p = ((struct gendisk *)v)->kobj.entry.next;
  24.         ++*pos;
  25.         return p==&block_subsys.list ? NULL :
  26.                 list_entry(p, struct gendisk, kobj.entry);
  27. }

  28. static void diskstats_stop(struct seq_file *part, void *v)
  29. {
  30.         mutex_unlock(&block_subsys_lock);
  31. }
复制代码
你太不认真的。你怎么只看diskstats_show,不看和他一套的函数呢。

如果对seq_operations不熟,自己去baidu.com!!

论坛徽章:
0
3 [报告]
发表于 2014-05-19 23:07 |只看该作者
本帖最后由 motorn 于 2014-05-19 23:11 编辑

回复 2# Tinnal


    你好,你提到的diskstats_{start, next, stop},在linux 2.6.25及以前的版本中存在,之后就不存在了,看这里。不过我在linux 2.6.32中找到了类似的一组函数:disk_seqf_{start, next, stop},看这里,这组函数从linux 2.6.31开始出现。

    但是有一个问题:对于linux 2.6.25,diskstats_start的实现中用到了一个变量block_subsys,它在drivers/block/genhd.c中定义的,在这里,可以看到,它是static的,即文件内可见。所以,你写个内核模块装载到内核之后,你是看不到这个变量的。所以也就没法把这几个函数“依葫芦画瓢”地再实现一遍。(为什么要再实现一遍?因为genhd.c里这几个函数是static的,而你要在你的模块里获得类似的功能)

    同样的,对于linux 2.6.32,disk_seqf_start的实现中用到了一个变量block_class,它也是在block/genhd.c中定义的,看这里,可以看到,它虽不是static的,但是它在定义之后并没有EXPORT_SYMBOL。linux内核在2.4之后,凡是没有EXPORT_SYMBOL的全局变量,不管它是不是static的,它都只是文件可见,不是真正的全局(即整个模块可见)。所以,我们遇到了同样的问题。

论坛徽章:
0
4 [报告]
发表于 2014-05-19 23:08 |只看该作者
回复 2# Tinnal
  1. #ifdef CONFIG_PROC_FS
  2. /* iterator */
  3. static void *disk_seqf_start(struct seq_file *seqf, loff_t *pos)
  4. {
  5.         loff_t skip = *pos;
  6.         struct class_dev_iter *iter;
  7.         struct device *dev;

  8.         iter = kmalloc(sizeof(*iter), GFP_KERNEL);
  9.         if (!iter)
  10.                 return ERR_PTR(-ENOMEM);

  11.         seqf->private = iter;
  12.         class_dev_iter_init(iter, &block_class, NULL, &disk_type);
  13.         do {
  14.                 dev = class_dev_iter_next(iter);
  15.                 if (!dev)
  16.                         return NULL;
  17.         } while (skip--);

  18.         return dev_to_disk(dev);
  19. }

  20. static void *disk_seqf_next(struct seq_file *seqf, void *v, loff_t *pos)
  21. {
  22.         struct device *dev;

  23.         (*pos)++;
  24.         dev = class_dev_iter_next(seqf->private);
  25.         if (dev)
  26.                 return dev_to_disk(dev);

  27.         return NULL;
  28. }

  29. static void disk_seqf_stop(struct seq_file *seqf, void *v)
  30. {
  31.         struct class_dev_iter *iter = seqf->private;

  32.         /* stop is called even after start failed :-( */
  33.         if (iter) {
  34.                 class_dev_iter_exit(iter);
  35.                 kfree(iter);
  36.         }
  37. }
复制代码

论坛徽章:
9
辰龙
日期:2014-08-18 20:38:42未羊
日期:2014-09-04 08:50:45丑牛
日期:2014-09-06 00:12:55寅虎
日期:2014-12-22 20:50:56摩羯座
日期:2015-01-14 22:28:15巳蛇
日期:2015-01-23 20:39:272015年辞旧岁徽章
日期:2015-03-03 16:54:1515-16赛季CBA联赛之青岛
日期:2016-03-13 23:37:1915-16赛季CBA联赛之深圳
日期:2016-03-29 18:52:38
5 [报告]
发表于 2014-05-20 20:23 |只看该作者
回复 4# motorn

这个函数是你想要的。
  1. void class_dev_iter_init(struct class_dev_iter *iter, struct class *class,
  2.                          struct device *start, const struct device_type *type)
  3. {
  4.         struct klist_node *start_knode = NULL;

  5.         if (start)
  6.                 start_knode = &start->knode_class;
  7.         klist_iter_init_node(&class->p->class_devices, &iter->ki, start_knode);
  8.         iter->type = type;
  9. }
  10. EXPORT_SYMBOL_GPL(class_dev_iter_init);
复制代码
这也是你要的。
  1. void class_dev_iter_init(struct class_dev_iter *iter, struct class *class,
  2.                          struct device *start, const struct device_type *type)
  3. {
  4.         struct klist_node *start_knode = NULL;

  5.         if (start)
  6.                 start_knode = &start->knode_class;
  7.         klist_iter_init_node(&class->p->class_devices, &iter->ki, start_knode);
  8.         iter->type = type;
  9. }
  10. EXPORT_SYMBOL_GPL(class_dev_iter_init);
复制代码
至于其他,你自己写呀,大哥。
  1. struct class block_class = {
  2.         .name                = "block",
  3. };
复制代码
这个这么简单的的定义你也非得要用别人的? 这些函数都只是让你参考,也不是让你直接去用,而且也没必要去抄。这几个函数代码量又不大,你抄来干嘛。
你要真纠结,就把他们EXPORT_SYMBOL_GPL。{:2_174:}

   
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP