免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: OstrichFly
打印 上一主题 下一主题

[原创] 写一个块设备驱动 [复制链接]

论坛徽章:
0
191 [报告]
发表于 2011-04-01 21:47 |只看该作者
楼主能做成一个pdf不?实在是上网没时间。只能下载了看。

论坛徽章:
0
192 [报告]
发表于 2011-04-07 23:20 |只看该作者
看完了两遍...今天自己动手就悲剧了...

毕竟是时间过去一段时间了  块设备部分也有了变化,自己查了查,

然后编译通过了  但是加载就悲剧····还是第一章····这不是打击我积极性么····

楼主能给看看不....
  1. #include <linux/init.h>
  2. #include <linux/module.h>
  3. #include <linux/blkdev.h>

  4. MODULE_LICENSE("Dual BSD/GPL");

  5. #define MY_BLKDEV_DEVICEMAJOR COMPAQ_SMART2_MAJOR
  6. #define MY_BLKDEV_DISKNAME "mydisk"
  7. #define MY_BLKDEV_SIZE (16*1024*1024)

  8. static struct request_queue *my_blkdev_queue;
  9. static struct gendisk *my_blkdev_disk;
  10. unsigned char my_blkdev_data[MY_BLKDEV_SIZE];

  11. static void my_blkdev_do_request(struct request_queue *q);

  12. struct block_device_operations my_blkdev_fops ={ .owner = THIS_MODULE,};

  13. static int __init my_blkdev_init(void )
  14. {
  15.    
  16.     int ret;
  17.     printk(KERN_ALERT MY_BLKDEV_DISKNAME"init!");
  18.     my_blkdev_queue = blk_init_queue(my_blkdev_do_request,NULL);
  19.     if(!my_blkdev_queue){
  20.         ret = -ENOMEM;
  21.         goto err_init_queue;
  22.     }
  23.     my_blkdev_disk = alloc_disk(1);
  24.     if(!my_blkdev_disk){
  25.         ret = -ENOMEM;
  26.         goto err_alloc_disk;
  27.     }
  28.     strcpy(my_blkdev_disk->disk_name,MY_BLKDEV_DISKNAME);
  29.     my_blkdev_disk->major = MY_BLKDEV_DEVICEMAJOR;
  30.     my_blkdev_disk->fops = & my_blkdev_fops;
  31.     my_blkdev_disk->queue = my_blkdev_queue;
  32.     set_capacity(my_blkdev_disk,MY_BLKDEV_SIZE>>9);
  33.     add_disk(my_blkdev_disk);
  34.     return 0;

  35. err_alloc_disk:
  36.     blk_cleanup_queue(my_blkdev_queue);

  37. err_init_queue:
  38.     return ret;

  39. }

  40. static void my_blkdev_exit(void)
  41. {

  42.         printk(KERN_ALERT"exit modules blk!");
  43.     del_gendisk(my_blkdev_disk);
  44.     blk_cleanup_queue(my_blkdev_queue);
  45. }

  46. static void my_blkdev_do_request(struct request_queue *q)
  47. {
  48.     struct request *req;
  49.     while((req=blk_fetch_request(q))!=NULL){
  50.         if((blk_rq_pos(req)+blk_rq_sectors(req))<<9 >MY_BLKDEV_SIZE){
  51.             printk(KERN_ERR MY_BLKDEV_DISKNAME"bad request :block =%llu,count=%u\n",(u64) blk_rq_pos(req),blk_rq_sectors( req));
  52.             __blk_end_request_all(req,-EIO);
  53.             continue;
  54.         }
  55.         switch( rq_data_dir(req)){
  56.             case READ:
  57.                 printk(KERN_ALERT "read\n");
  58.                 memcpy(req->buffer,my_blkdev_data+(blk_rq_pos(req)<<9),blk_rq_sectors(req)<<9);
  59.                 __blk_end_request_all(req,1);
  60.                 break;
  61.             case WRITE:
  62.                 printk(KERN_ALERT "write\n");
  63.                 memcpy(my_blkdev_data+(blk_rq_pos(req)<<9),req->buffer,blk_rq_sectors(req)<<9);
  64.                 __blk_end_request_all(req,1);                break;
  65.             default:
  66.                 printk(KERN_ALERT "this should not happen");
  67.                 break;
  68.         }
  69.     }
  70. }
  71. module_init(my_blkdev_init);
  72. module_exit(my_blkdev_exit);

复制代码

论坛徽章:
0
193 [报告]
发表于 2011-04-07 23:24 |只看该作者
环境:ubuntu 10.04tls
内核 :2.6.36.2
gcc:4.4.3

论坛徽章:
0
194 [报告]
发表于 2011-04-08 20:39 |只看该作者
lz,我拿你第一章的代码在我电脑上编译,出现以下错误:
make -C /lib/modules/2.6.37.2+/build SUBDIRS=/data/home/likuo/blockdrive/simp_blkdev/simp_blkdev_step01 modules
make[1]: Entering directory `/usr/src/linux-2.6.37.2'
  CC [M]  /data/home/likuo/blockdrive/simp_blkdev/simp_blkdev_step01/simp_blkdev.o
/data/home/likuo/blockdrive/simp_blkdev/simp_blkdev_step01/simp_blkdev.c: In function 'simp_blkdev_do_request':
/data/home/likuo/blockdrive/simp_blkdev/simp_blkdev_step01/simp_blkdev.c:43: error: implicit declaration of function 'elv_next_request'
/data/home/likuo/blockdrive/simp_blkdev/simp_blkdev_step01/simp_blkdev.c:43: warning: assignment makes pointer from integer without a cast
/data/home/likuo/blockdrive/simp_blkdev/simp_blkdev_step01/simp_blkdev.c:44: error: 'struct request' has no member named 'sector'
/data/home/likuo/blockdrive/simp_blkdev/simp_blkdev_step01/simp_blkdev.c:44: error: 'struct request' has no member named 'current_nr_sectors'
/data/home/likuo/blockdrive/simp_blkdev/simp_blkdev_step01/simp_blkdev.c:48: error: 'struct request' has no member named 'sector'
/data/home/likuo/blockdrive/simp_blkdev/simp_blkdev_step01/simp_blkdev.c:49: error: 'struct request' has no member named 'current_nr_sectors'
/data/home/likuo/blockdrive/simp_blkdev/simp_blkdev_step01/simp_blkdev.c:50: error: implicit declaration of function 'end_request'
/data/home/likuo/blockdrive/simp_blkdev/simp_blkdev_step01/simp_blkdev.c:57: error: 'struct request' has no member named 'sector'
/data/home/likuo/blockdrive/simp_blkdev/simp_blkdev_step01/simp_blkdev.c:58: error: 'struct request' has no member named 'current_nr_sectors'
/data/home/likuo/blockdrive/simp_blkdev/simp_blkdev_step01/simp_blkdev.c:62: error: 'struct request' has no member named 'sector'
/data/home/likuo/blockdrive/simp_blkdev/simp_blkdev_step01/simp_blkdev.c:63: error: 'struct request' has no member named 'current_nr_sectors'
make[2]: *** [/data/home/likuo/blockdrive/simp_blkdev/simp_blkdev_step01/simp_blkdev.o] Error 1
make[1]: *** [_module_/data/home/likuo/blockdrive/simp_blkdev/simp_blkdev_step01] Error 2
make[1]: Leaving directory `/usr/src/linux-2.6.37.2'
make: *** [default] Error 2

我的内核是Linux-2.6.37.2
我于是在内核里找相应结构,发现struct request里没有sector和current_nr_sectors成员,也没发现elv_next_reques和end_request函数;
是不是它们改名字了,还是在哪地方弄错了;
我是菜鸟,上网上也没找到答案,请lz帮帮忙,谢谢

论坛徽章:
0
195 [报告]
发表于 2011-04-11 21:22 |只看该作者
回复 194# lilikoo


    改名字了   


具体看linux/include/blkdev.h

sectors    ------------- >   blk_rq_pos

nr_sectros   --------------- > blk_rq_sectors

__elv_next_request              -------------------->       blk_peek_request

论坛徽章:
0
196 [报告]
发表于 2011-04-13 19:29 |只看该作者
谢谢blinkkey,我改了一些地方:
sectors调用blk_rq_pos得到
current_nr_sectors调用blk_rq_sectors得到
elv_next_request换成blk_peek_request
end_request换成blk_end_request_cur
终于编译成功了,太高兴了;
于是我insmod simp_blkdev.ko;
悲剧了,机器宕了,自动重启

论坛徽章:
0
197 [报告]
发表于 2011-04-27 14:58 |只看该作者
我也碰到楼上的问题,哪位大牛解释一下原因啊,谢谢。。。

论坛徽章:
0
198 [报告]
发表于 2011-05-20 09:24 |只看该作者
一加载模块就死机,什么原因?哪位给分析下,谢谢了。

  1. #include <linux/init.h>
  2. #include <linux/module.h>
  3. #include <linux/blkdev.h>

  4. #define KERNEL_SECTOR_SIZE        512

  5. static int sbull_major = 0;
  6. static struct request_queue *request;
  7. static struct gendisk *gd;

  8. static int nsectors = (16*1024*1024) >> 9;
  9. static int hardsect_size = 512;

  10. unsigned char sbull_data[16*1024*1024];

  11. static struct block_device_operations sbull_fops = {
  12.         .owner        =        THIS_MODULE,
  13. };

  14. static void sbull_request(struct request_queue *q)
  15. {
  16.         int err;
  17.         struct request *req;
  18.         unsigned int sector, current_nr_sectors;
  19.        
  20.         req = blk_peek_request(q);
  21.         sector = blk_rq_pos(req);
  22.         current_nr_sectors = blk_rq_sectors(req);

  23.         switch (rq_data_dir(req)) {

  24.         case READ:
  25.                 memcpy(req->buffer, sbull_data + (sector << 9), current_nr_sectors << 9);
  26.                 blk_end_request_cur(req, err);
  27.                 break;

  28.         case WRITE:
  29.                 memcpy(sbull_data + (sector << 9), req->buffer, current_nr_sectors << 9);
  30.                 blk_end_request_cur(req, err);
  31.                 break;

  32.         default:
  33.                 break;
  34.         }
  35. }

  36. static int __init sbull_init(void)
  37. {
  38.         int ret;
  39.         sbull_major = register_blkdev(sbull_major, "sbull");
  40.         if (sbull_major <= 0) {               
  41.                 printk(KERN_WARNING "sbull: unable to get major number\n");                                                                                                      
  42.                 return -EBUSY;
  43.         }

  44.         /* I/O scheduler passes ordered requests to device driver through struct request_queue */
  45.         request = blk_init_queue(sbull_request, NULL);
  46.         if (!request) {
  47.                 ret = -ENOMEM;
  48.                 printk (KERN_NOTICE "blk_init_queue failure\n");
  49.                 goto err_init_queue;
  50.         }       

  51.         gd = alloc_disk(1);
  52.         if (!gd) {
  53.                 ret = -ENOMEM;
  54.                 printk (KERN_NOTICE "alloc_disk failure\n");
  55.                 goto err_alloc_disk;
  56.         }
  57.        
  58.         strcpy(gd->disk_name, "sbull");
  59.         gd->major = sbull_major;
  60.         gd->first_minor = 0;
  61.         gd->fops = &sbull_fops;
  62.         gd->queue = request;
  63.         set_capacity(gd, nsectors*(hardsect_size/KERNEL_SECTOR_SIZE));
  64.         add_disk(gd);
  65.        
  66.         return 0;

  67. err_alloc_disk:
  68.         blk_cleanup_queue(request);
  69. err_init_queue:
  70.         return ret;
  71. }

  72. static void __exit sbull_exit(void)
  73. {
  74.         del_gendisk(gd);
  75.         put_disk(gd);
  76.         blk_cleanup_queue(request);
  77. }

  78. module_init(sbull_init);
  79. module_exit(sbull_exit);
复制代码

论坛徽章:
0
199 [报告]
发表于 2011-08-02 18:44 |只看该作者
本帖最后由 c04n05 于 2011-08-04 10:45 编辑

看到了第3章了。觉得非常不错。
感谢LZ分享

我在fedora 9下面碰到了和193楼类似的问题。。悲剧。
BTW:给大家分享一个基树的资料http://www.360doc.com/content/09/1017/08/313373_7396041.shtml

论坛徽章:
0
200 [报告]
发表于 2011-08-03 14:13 |只看该作者
把blk_end_request_cur 换成__blk_end_request_cur
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP