【问题标题】:Pseudo Block Driver: I have generated the device file for block driver using mknod伪块驱动程序:我已经使用 mknod 生成了块驱动程序的设备文件
【发布时间】:2015-12-23 05:49:26
【问题描述】:

我已经使用 mknod 为块驱动程序生成了设备文件。现在如何通过我生成的设备文件读取/写入/传输任何请求或文件?

【问题讨论】:

    标签: linux block linux-device-driver


    【解决方案1】:

    浏览这个示例块驱动程序

    sbd.c
    
    /*
     * A sample, extra-simple block driver. Updated for kernel 2.6.31.
     *
     * (C) 2003 Eklektix, Inc.
     * (C) 2010 Pat Patterson <pat at superpat dot com>
     * Redistributable under the terms of the GNU GPL.
     */
    
    #include <linux/module.h>
    #include <linux/moduleparam.h>
    #include <linux/init.h>
    
    #include <linux/kernel.h> /* printk() */
    #include <linux/fs.h>     /* everything... */
    #include <linux/errno.h>  /* error codes */
    #include <linux/types.h>  /* size_t */
    #include <linux/vmalloc.h>
    #include <linux/genhd.h>
    #include <linux/blkdev.h>
    #include <linux/hdreg.h>
    
    MODULE_LICENSE("Dual BSD/GPL");
    static char *Version = "1.4";
    
    static int major_num = 0;
    module_param(major_num, int, 0);
    static int logical_block_size = 512;
    module_param(logical_block_size, int, 0);
    static int nsectors = 1024; /* How big the drive is */
    module_param(nsectors, int, 0);
    
    /*
     * We can tweak our hardware sector size, but the kernel talks to us
     * in terms of small sectors, always.
     */
    #define KERNEL_SECTOR_SIZE 512
    
    /*
     * Our request queue.
     */
    static struct request_queue *Queue;
    
    /*
     * The internal representation of our device.
     */
    static struct sbd_device {
        unsigned long size;
        spinlock_t lock;
        u8 *data;
        struct gendisk *gd;
    } Device;
    
    /*
     * Handle an I/O request.
     */
    static void sbd_transfer(struct sbd_device *dev, sector_t sector,
            unsigned long nsect, char *buffer, int write) {
        unsigned long offset = sector * logical_block_size;
        unsigned long nbytes = nsect * logical_block_size;
    
        if ((offset + nbytes) > dev->size) {
            printk (KERN_NOTICE "sbd: Beyond-end write (%ld %ld)\n", offset, nbytes);
            return;
        }
        if (write)
            memcpy(dev->data + offset, buffer, nbytes);
        else
            memcpy(buffer, dev->data + offset, nbytes);
    }
    
    static void sbd_request(struct request_queue *q) {
        struct request *req;
    
        req = blk_fetch_request(q);
        while (req != NULL) {
            // blk_fs_request() was removed in 2.6.36 - many thanks to
            // Christian Paro for the heads up and fix...
            //if (!blk_fs_request(req)) {
            if (req == NULL || (req->cmd_type != REQ_TYPE_FS)) {
                printk (KERN_NOTICE "Skip non-CMD request\n");
                __blk_end_request_all(req, -EIO);
                continue;
            }
            sbd_transfer(&Device, blk_rq_pos(req), blk_rq_cur_sectors(req),
                    req->buffer, rq_data_dir(req));
            if ( ! __blk_end_request_cur(req, 0) ) {
                req = blk_fetch_request(q);
            }
        }
    }
    
    /*
     * The HDIO_GETGEO ioctl is handled in blkdev_ioctl(), which
     * calls this. We need to implement getgeo, since we can't
     * use tools such as fdisk to partition the drive otherwise.
     */
    int sbd_getgeo(struct block_device * block_device, struct hd_geometry * geo) {
        long size;
    
        /* We have no real geometry, of course, so make something up. */
        size = Device.size * (logical_block_size / KERNEL_SECTOR_SIZE);
        geo->cylinders = (size & ~0x3f) >> 6;
        geo->heads = 4;
        geo->sectors = 16;
        geo->start = 0;
        return 0;
    }
    
    /*
     * The device operations structure.
     */
    static struct block_device_operations sbd_ops = {
            .owner  = THIS_MODULE,
            .getgeo = sbd_getgeo
    };
    
    static int __init sbd_init(void) {
        /*
         * Set up our internal device.
         */
        Device.size = nsectors * logical_block_size;
        spin_lock_init(&Device.lock);
        Device.data = vmalloc(Device.size);
        if (Device.data == NULL)
            return -ENOMEM;
        /*
         * Get a request queue.
         */
        Queue = blk_init_queue(sbd_request, &Device.lock);
        if (Queue == NULL)
            goto out;
        blk_queue_logical_block_size(Queue, logical_block_size);
        /*
         * Get registered.
         */
        major_num = register_blkdev(major_num, "sbd");
        if (major_num < 0) {
            printk(KERN_WARNING "sbd: unable to get major number\n");
            goto out;
        }
        /*
         * And the gendisk structure.
         */
        Device.gd = alloc_disk(16);
        if (!Device.gd)
            goto out_unregister;
        Device.gd->major = major_num;
        Device.gd->first_minor = 0;
        Device.gd->fops = &sbd_ops;
        Device.gd->private_data = &Device;
        strcpy(Device.gd->disk_name, "sbd0");
        set_capacity(Device.gd, nsectors);
        Device.gd->queue = Queue;
        add_disk(Device.gd);
    
        return 0;
    
    out_unregister:
        unregister_blkdev(major_num, "sbd");
    out:
        vfree(Device.data);
        return -ENOMEM;
    }
    
    static void __exit sbd_exit(void)
    {
        del_gendisk(Device.gd);
        put_disk(Device.gd);
        unregister_blkdev(major_num, "sbd");
        blk_cleanup_queue(Queue);
        vfree(Device.data);
    }
    
    module_init(sbd_init);
    module_exit(sbd_exit);
    

    对于伪块设备也可以参考this
    参考http://free-electrons.com/doc/block_drivers.pdf

    【讨论】:

    • 是的,在那个 pdf 文件中,我没有了解那些用于读取、写入的 API?它们是什么?
    • 读取和写入实际虚拟(伪)设备的设备
    • 然后我不知道如何使用它们,意味着我有一个包含 Makefile 和简单代码 Hello world.c 的文件夹和一个包含有关该块驱动程序的所有结构的文件 pblk.c。现在步骤 1.make,步骤 2.insmod .ko,步骤 3.dmesg,我从我的 pblk.c 中看到的消息。现在我该如何使用这个设备文件。设备文件隐式生成在我的 /dev 文件夹中。
    • 您可以制作示例驱动程序以使用写入 API 在此驱动程序上写入,然后在同一程序中您可以使用读取 API 读取您之前编写的任何内容。所以当你阅读时应该打印在屏幕上
    • 您可以理解文件中写入了一些内容,并且从中读取了一些内容
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-29
    • 2013-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多