m0_64633712 2023-03-04 10:00 采纳率: 72.2%
浏览 40
已结题

最近在编写块设备驱动,使用制造请求队列函数时,set_bit()和bio_endio()函数报错,请问这是什么原因?

最近在编写块设备驱动,使用制造请求队列函数时,set_bit()和bio_endio()函数报错,请问这是什么原因?

set_bit(BIO_UPTODATE, &bio->bi_flags);
    bio_endio(bio, 0);

总体代码如下:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/string.h>
#include <linux/irq.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/interrupt.h>
#include <linux/input.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/input/mt.h>
#include <linux/input/touchscreen.h>
#include <linux/blkdev.h>
#include <linux/hdreg.h>

/*参考例程*/

/*定义磁盘大小,内存模式*/
#define RAMDISK_SIZE        (2  *   1024    *   1024)   /*大小2MB*/
#define RAMDISK_NAME    "ramdisk"                 /*名字*/
#define RAMDISK_MINOR   3                                   /*表示3个分区*/


/*ramdisk设备结构体*/
struct ramdisk_dev
{
    int major;              /*主设备号*/
    unsigned    char    *ramdiskbuf;        /*ramdisk的内存空间,模拟磁盘的空间*/
    struct  gendisk *gendisk;
    struct  request_queue   *queue;
    spinlock_t  lock;       /*自旋锁*/
};

struct  ramdisk_dev ramdisk;
#if 0
/*具体的数据处理过程*/
static  void    ramdisk_transfer(struct request *req)
{
    /*数据传输三要素:源,目的,长度。
    *内存地址,块设备地址,长度
    */
   unsigned long    start   =   blk_rq_pos(req) <<  9;      /*blk_rq_pos获取到要操作的块设备扇区地址,左移9位,地址字节*/
   unsigned long    len =   blk_rq_cur_bytes(req);          /*数据长度*/

    /*获取bio里面的缓冲区:
    *如果是读:从磁盘里面读取到的数据保存在缓冲区里面
    *如果是写:此缓冲区保存着要写入到磁盘里面的数据
    */
   void *buffer =   bio_data(req->bio);

    if(rq_data_dir(req) ==   READ)               /*读操作*/
        memcpy(buffer,  ramdisk.ramdiskbuf  +   start,  len);
    else                                                                    /*写操作*/
        memcpy(ramdisk.ramdiskbuf  +   start,  buffer, len);

}
#endif
/*制造请求函数*/
static  void    ramdisk_make_request(struct request_queue   *queue, struct  bio *bio)
{
    int offset;
    struct  bio_vec bvec;
    struct  bvec_iter   iter;
    unsigned    long    len =   0;

    offset  =   bio->bi_iter.bi_sector   <<  9;      /*要操作的磁盘起始扇区偏移,改为字节地址*/

    /*循环处理每个段*/
    bio_for_each_segment(bvec,  bio,    iter)   {
    /*获取bio里面的缓冲区:
    *如果是读:从磁盘里面读取到的数据保存在缓冲区里面
    *如果是写:此缓冲区保存着要写入到磁盘里面的数据
    */
        char    *ptr    =   page_address(bvec.bv_page)  +   bvec.bv_offset;
        len =   bvec.bv_len;        /*长度*/

        if(bio_data_dir(bio) ==   READ)               /*读操作*/
            memcpy(ptr,  ramdisk.ramdiskbuf  +   offset,  len);
        else                                                                    /*写操作*/
            memcpy(ramdisk.ramdiskbuf  +   offset,  ptr, len);

        offset  +=  len;
    }

    set_bit(BIO_UPTODATE,   &bio->bi_flags);
    bio_endio(bio,  0);
}


static  int ramdisk_open(struct block_device    *bdev,  fmode_t mode)
{
    printk("ramdisk_open\r\n");
    return  0;
}

static  void    ramdisk_release(struct  gendisk *disk,  fmode_t mode)
{
    printk("ramdisk_release\r\n");
}

static  int    ramdisk_getgeo(struct   block_device   *dev,  struct  hd_geometry    *geo)
{
    printk("ramdisk_getgeo\r\n");
    /*硬盘信息*/
    geo->heads  =   2;      /*磁头*/
    geo->cylinders  =   32;         /*柱面,磁道*/
    geo->sectors    =   RAMDISK_SIZE/(2  *   32  *   512);   /*一个磁道里面的扇区数量*/
    
    return  0;
}

/*块设备操作集*/
static  const   struct  block_device_operations ramdisk_fops    =   
{
    .owner          =   THIS_MODULE,
    .open             = ramdisk_open,
    .release        =   ramdisk_release,
    .getgeo         =   ramdisk_getgeo,
};

/* 驱动入口函数 */
static int __init ramdisk_init(void)
{
    int ret =   0;
    printk("ramdisk_init\r\n");

    /*1.先申请内存*/
    ramdisk.ramdiskbuf  =   kzalloc(RAMDISK_SIZE,   GFP_KERNEL);
    if(ramdisk.ramdiskbuf   ==  NULL){
            ret =   -EINVAL;
            goto    ramalloc_fail;
    }
    /*2.注册块设备*/
    ramdisk.major   =   register_blkdev(0,RAMDISK_NAME);
    if(ramdisk.major    <   0)  {
        ret =   -EINVAL;
        goto    ramdisk_register_blkdev_fail;
    }
    printk("ramdisk major   =   %d\r\n",    ramdisk.major);

    /*3.申请gendisk*/
    ramdisk.gendisk =   alloc_disk(RAMDISK_MINOR);
    if(!ramdisk.gendisk){
        ret =   -EINVAL;
        goto    gendisk_alloc_fail;
    }

/*4.初始化自旋锁*/
spin_lock_init(&ramdisk.lock);

/*5.申请请求队列*/
ramdisk.queue   =   blk_alloc_queue(GFP_KERNEL);
if(!ramdisk.queue){
    ret =   -EINVAL;
    goto    blk_queue_fail;
}

/*绑定"制造请求"函数*/
blk_queue_make_request(ramdisk.queue,   ramdisk_make_request);

/*6.初始化gendisk*/
ramdisk.gendisk->major  =   ramdisk.major;      /*主设备号*/
ramdisk.gendisk->first_minor    =   0;
ramdisk.gendisk->fops   =   &ramdisk_fops;
ramdisk.gendisk->private_data   =   &ramdisk;
ramdisk.gendisk->queue  =   ramdisk.queue;
sprintf(ramdisk.gendisk->disk_name, RAMDISK_NAME);
set_capacity(ramdisk.gendisk,  RAMDISK_SIZE/512);      /*设置gendisk容量,单位扇区*/

add_disk(ramdisk.gendisk);

return  0;

blk_queue_fail:
    put_disk(ramdisk.gendisk);
gendisk_alloc_fail:
    unregister_blkdev(ramdisk.major,    RAMDISK_NAME);
ramdisk_register_blkdev_fail:
    kfree(ramdisk.ramdiskbuf);
ramalloc_fail:
    return ret;
}

/* 驱动出口函数 */
static void __exit ramdisk_exit(void)
{
    printk("ramdisk     exit\r\n");
    del_gendisk(ramdisk.gendisk);
    put_disk(ramdisk.gendisk);

    blk_cleanup_queue(ramdisk.queue);

    unregister_blkdev(ramdisk.major,    RAMDISK_NAME);
    kfree(ramdisk.ramdiskbuf);
}

module_init(ramdisk_init);
module_exit(ramdisk_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("ty");

具体报错如下:

make -C /home/user/linux/rv/kernel M=/home/user/linux/study/ramdisk_makerequest ARCH=arm CROSS_COMPILE=/home/user/linux/rv/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/arm-linux-gnueabihf- modules 
make[1]: 进入目录“/home/user/linux/rv/kernel”
  CC [M]  /home/user/linux/study/ramdisk_makerequest/ramdisk.o
In file included from ./include/linux/bitops.h:19,
                 from ./include/linux/kernel.h:11,
                 from ./include/linux/list.h:9,
                 from ./include/linux/module.h:9,
                 from /home/user/linux/study/ramdisk_makerequest/ramdisk.c:1:
/home/user/linux/study/ramdisk_makerequest/ramdisk.c: In function 'ramdisk_make_request':
/home/user/linux/study/ramdisk_makerequest/ramdisk.c:98:13: error: 'BIO_UPTODATE' undeclared (first use in this function); did you mean 'IS_PRIVATE'?
     set_bit(BIO_UPTODATE,   &bio->bi_flags);
             ^~~~~~~~~~~~
./arch/arm/include/asm/bitops.h:183:42: note: in definition of macro 'ATOMIC_BITOP'
 #define ATOMIC_BITOP(name,nr,p)  _##name(nr,p)
                                          ^~
/home/user/linux/study/ramdisk_makerequest/ramdisk.c:98:5: note: in expansion of macro 'set_bit'
     set_bit(BIO_UPTODATE,   &bio->bi_flags);
     ^~~~~~~
/home/user/linux/study/ramdisk_makerequest/ramdisk.c:98:13: note: each undeclared identifier is reported only once for each function it appears in
     set_bit(BIO_UPTODATE,   &bio->bi_flags);
             ^~~~~~~~~~~~
./arch/arm/include/asm/bitops.h:183:42: note: in definition of macro 'ATOMIC_BITOP'
 #define ATOMIC_BITOP(name,nr,p)  _##name(nr,p)
                                          ^~
/home/user/linux/study/ramdisk_makerequest/ramdisk.c:98:5: note: in expansion of macro 'set_bit'
     set_bit(BIO_UPTODATE,   &bio->bi_flags);
     ^~~~~~~
/home/user/linux/study/ramdisk_makerequest/ramdisk.c:98:29: error: passing argument 2 of '_set_bit' from incompatible pointer type [-Werror=incompatible-pointer-types]
     set_bit(BIO_UPTODATE,   &bio->bi_flags);
                             ^~~~~~~~~~~~~~
./arch/arm/include/asm/bitops.h:183:45: note: in definition of macro 'ATOMIC_BITOP'
 #define ATOMIC_BITOP(name,nr,p)  _##name(nr,p)
                                             ^
/home/user/linux/study/ramdisk_makerequest/ramdisk.c:98:5: note: in expansion of macro 'set_bit'
     set_bit(BIO_UPTODATE,   &bio->bi_flags);
     ^~~~~~~
./arch/arm/include/asm/bitops.h:153:55: note: expected 'volatile long unsigned int *' but argument is of type 'short unsigned int *'
 extern void _set_bit(int nr, volatile unsigned long * p);
                              ~~~~~~~~~~~~~~~~~~~~~~~~~^
/home/user/linux/study/ramdisk_makerequest/ramdisk.c:99:5: error: too many arguments to function 'bio_endio'
     bio_endio(bio,  0);
     ^~~~~~~~~
In file included from ./include/linux/blkdev.h:21,
                 from /home/user/linux/study/ramdisk_makerequest/ramdisk.c:26:
./include/linux/bio.h:448:13: note: declared here
 extern void bio_endio(struct bio *);
             ^~~~~~~~~
/home/user/linux/study/ramdisk_makerequest/ramdisk.c: In function 'ramdisk_init':
/home/user/linux/study/ramdisk_makerequest/ramdisk.c:172:41: error: passing argument 2 of 'blk_queue_make_request' from incompatible pointer type [-Werror=incompatible-pointer-types]
 blk_queue_make_request(ramdisk.queue,   ramdisk_make_request);
                                         ^~~~~~~~~~~~~~~~~~~~
In file included from /home/user/linux/study/ramdisk_makerequest/ramdisk.c:26:
./include/linux/blkdev.h:1206:60: note: expected 'blk_qc_t (*)(struct request_queue *, struct bio *)' {aka 'unsigned int (*)(struct request_queue *, struct bio *)'} but argument is of type 'void (*)(struct request_queue *, struct bio *)'
 extern void blk_queue_make_request(struct request_queue *, make_request_fn *);
                                                            ^~~~~~~~~~~~~~~~~
cc1: some warnings being treated as errors
scripts/Makefile.build:339: recipe for target '/home/user/linux/study/ramdisk_makerequest/ramdisk.o' failed
make[2]: *** [/home/user/linux/study/ramdisk_makerequest/ramdisk.o] Error 1
Makefile:1641: recipe for target '_module_/home/user/linux/study/ramdisk_makerequest' failed
make[1]: *** [_module_/home/user/linux/study/ramdisk_makerequest] Error 2
make[1]: 离开目录“/home/user/linux/rv/kernel”
Makefile:12: recipe for target 'all' failed
make: *** [all] Error 2

  • 写回答

2条回答 默认 最新

  • 「已注销」 2023-03-04 10:08
    关注

    “Devil组”引证GPT后的撰写:

    • et_bit()和bio_endio()函数报错可能是由于缺少头文件或函数定义不正确引起的。这两个函数都是属于Linux内核中的函数,set_bit()用于设置某个二进制位为1,bio_endio()用于结束块I/O操作。因此,需要在代码中包含正确的头文件并确保函数调用的正确性。
    • 在代码中,缺少的头文件是<linux/bitmap.h>,它包含set_bit()函数的定义。需要添加该头文件,以便编译器正确解析set_bit()函数。您可以在代码中添加以下行:
    #include <linux/bitmap.h>
    
    
    • 在bio_endio()函数的情况下,它需要两个参数:第一个是指向结束I/O操作的struct bio结构的指针,第二个是表示I/O操作的错误代码。因此,要确保传递正确的参数。在代码中,第二个参数应该是0,表示I/O操作成功完成。如果I/O操作发生错误,应该传递相应的错误代码。以下是正确的bio_endio()函数调用示例:
    
    bio_endio(bio, 0);
    
    

    请注意,还需要在代码中定义ramdisk_make_request()函数,该函数将用于处理I/O请求。在您的代码中,该函数似乎已经定义,但是被注释掉了。因此,要取消注释该函数,并确保它与其他函数一起正确工作。

    最后,为了更好地了解错误的原因,请在编译时启用调试信息,以便编译器可以输出更详细的错误信息。用以下命令进行编译:

    • make CONFIG_DEBUG_INFO=y
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 5月1日
  • 已采纳回答 4月23日
  • 创建了问题 3月4日

悬赏问题

  • ¥15 Matlab问题解答有两个问题
  • ¥50 Oracle Kubernetes服务器集群主节点无法访问,工作节点可以访问
  • ¥15 LCD12864中文显示
  • ¥15 在使用CH341SER.EXE时不小心把所有驱动文件删除了怎么解决
  • ¥15 gsoap生成onvif框架
  • ¥15 有关sql server business intellige安装,包括SSDT、SSMS。
  • ¥15 stm32的can接口不能收发数据
  • ¥15 目标检测算法移植到arm开发板
  • ¥15 利用JD51设计温度报警系统
  • ¥15 快手联盟怎么快速的跑出建立模型