007 device driver

First, the introduction of the block device drivers (Lesson 18 / first)

Summarize the character device driver:

1, introducing a character device driver


When the application calls the open, drv_open function driver is called.

2, the simplest driver wording

1. Determine the major number: You can set itself, but also allows the kernel distribution.
2. The configuration of the drive in "open, read, write" function, etc., and then into "file_operation" in structure.
3. register_chrdev character registration apparatus, the configuration of the "file_operation" characters into the device structure in the core of the primary device number for the next target to the array. "register_chrdev (major number, the name of the master device, file_operation structure)."
4. entry functions: call this "register_chrdev" function, loading a kernel module, will automatically call this entry point.
The export function: Call "unregister_chrdev"

3, we wrote a lot of the key driver for example a driver

1. query: driver provides a read function that returns a pin direct state, the application will continue to read, whether before and after the two pin status has been changed. CPU occupancy rate will be high.
2. interrupt (wake-up): The application to enter the read function driver when using the read function. In the driver program, if there is no data on sleep, if an interrupt occurs will be awakened, then copy_to_user copy the data to the user space.
3. poll mechanism: just set alarm clock, if time is up or an interrupt occurs returns
4. Asynchronous Notification: The above are three kinds of applications to read, asynchronous notification is the driver sends a signal to the application.
Disadvantage of the above four cases is that this drive only you know how to use. Drivers must be written in general understand the kernel code, the integration into your own code. For key is input subsystem, it is for the LCD Framebuffer.

Block device driver

1, the hard disk:



Cylinder: the same as the runway of a ring, such as: 0 Runway
sectors: a continuous track on a small part of the area, a track can be divided into several sectors.
In fact, disk read and write very fast, slow reader is positioned above the mechanical structure of the apparatus.
Suppose now read and write heads of different sectors on the

execution of the above is: "R0" -> "W " -> "R1", the operation jumps twice.
Optimization about: "R0" -> "R1 " -> "W", so that this operation would only need to jump once.
Solution: First in the queue but not executed, optimized execution (reorder) later. On a hard disk can be prevented from jumping reduce the overall read and write efficiency.

2、Flash


Assumptions write sector 0 and sector 1
Flash erased first and then write.

  1. To read entire buffer.
  2. Modify the buffer in the sector 0.
  3. Erase the entire Flash.
  4. The buffer modified programmed into the piece.
    Solution: First in the queue is not performed, perform optimization (consolidation) after.

    Therefore, provided that the block device can not read and write functions like character device. But the first read into the queue is not performed; after performing the optimization.

Second, a block device driver framework (Lesson 18 / II)


Read and write ordinary file "1.txt" are converted paired block device to read and write, to read and write which sector. Conversion paired sectors read from the file read and write, the intermediate will involve "File System."
Application to read and write an ordinary file, the operation will eventually be converted to hardware, the "block device drivers," to operate the hardware.
How do we know that "ll_rw_block" (lowlevel bottom) can see "LINUX kernel source code Scenario Analysis."

From now on "ll_rw_block" function begins analysis


File this function under "fs" directory in the kernel source directory, there are a wide variety of file systems this "fs" directory (Organization format files - the concept of pure software), under "fs" There directory many common document, "ll_rw_blokc" this function (buffer.c) is a universal file under the "fs" directory.
Parameter 1: indicates a read or write; Parameter 2: 3 and nr parameter "buffer_head" structure array entries; Parameter 3: Data transfer three elements (source, destination, length) into an array "buffer_head" structure.


Enter (submit_bh) function

construct bio, submitted Bio

---------------------------------------- -------------

enter (submit_bio) function


-------------------------------- ---------------------


----------------------------- ------------------------



Well, this is where the function is set it? Search


this (blk_queue_make_request) function is invoked Where is it? Search



to see this default function (__make_request) What do something?






Analytical Framework:

Third, the write driver block device driver with an analog memory disk (Lesson 18 / third)

How to write a block device drivers?

1. The idea of object-oriented assigned a "gendisk" structure: Use alloc_disk function
2. Set "gendisk" structure.
2.1 assignment / setting a queue: Use blk_init_queue (providing read and write)
2.2 Set "gendisk" other information. Providing attributes: such capacity
3. Register "gendisk" structure: function using add_disk

Take a look at how other people do, refer to (drivers / block / xd.c) and (drivers / block / z2ram.c).
From "xd.c" start entry function
1. Register block device


2. Initialize queue

3. queue


4. add_disk

1th、

To write a device driver block
allocated disk structural

assignment / setting queue


set other attributes disk




registration

processing request
allocation / queue set "blk_init_queue" function, the parameter is a function for processing requests in the queue of

the outlet function

test 1th:
1 the loading driving:

after loading the driver immediately called "do_ramblock_request" queue request handler, but never returned to here, because of the reques without any treatment.

2th, unable to return to deal with the problem

Look (xd.c), take a look at how to do

mimic what

test 2th:
loading drive

because nothing is done, it will not recognize the partition table
check equipment


3th, improve memory, analog disk

1. Allocate memory to simulate a disk


2. The three elements of data transmission, data transmission block device three elements defined in the "request" structure

block device operation is performed in units of sectors, even when writing a byte is read first a sector, after modifying this sector that was in bytes, and then burned into the entire sector.

3. The direction of write

tests 3th:
No test solution mkdosfs tool:
. A download source, decompressed, compiled

mkdosfs 2. Compile the copied to usr / sbin directory file system


3. Use board after nfs articulated to copy from the board mount directory / usr / sbin next.

Starting test:
1. Driver loading

or prompt the unrecognized partition table, because all allocated memory is cleared up.

2. Format: The mkdosfs / dev / ramblock

3. Mount: mount / dev / ramblock / tmp / =====> tmp the disks to the directory, the operation / tmp / directory operation is equivalent to We memory virtual disk

4. read-write file: cd / tmp, in which file or edit a file copy


5. jump to the root directory, then unmount

6. the memory used to cover the entire virtual disk image / mnt / ramblock. bin


7. Check ramblock.bin in first_fs directory on your PC
"-o Loop" represents the loopback device can be a regular file as a block device file to mount.

4th, the write queue request handler printed

With memory to simulate a disk, ignoring the complex operational hardware, where the use of "memcpy" to achieve hardware operations.
Add print statements to see the execution of a read or write operation

test 4th:
1. load the driver

to read when driving a load
2. Format

3. Mount

......

4. copy a file (cp / etc / inittab / tmp)

can be seen immediately written into and did not write, but read. Will read and write operations to the block in a queue inside the device, and is not performed immediately.

I waited a while to write into

Sometimes on Windows can copy files to the U disk found in the "progress bar" has been completed, it is to click on the bottom right corner when unloading U disk, you are prompted to say the device is busy, U disk lights are flashing mad. This is the background actually still writing.

Then copy a file (cp /etc/init.d/rcS / tmp)

found or did not write
the implementation of sync (sync) can write into it immediately, sync is a system call.

Again copy files, they also can not write immediately, when executing "umount" the (unmounted), immediately began to write.

5th, partition


Will prompt you did not know "cylinders" number. Now many disks have no (head, cylinder) this structure, but for compatibility with these "fdisk" old tool, you need to pretend that they have a number of "heads", the number of "cylinders." This information is obtained from the geometric attributes "block_device_operation" structure ".getgeo" function.

Search ".getgeo" to see how other people are using the

follow what others wording

Cylinder head capacity = * * 512 * sector
head: indicates how many faces. It is assumed that there are two faces.
Cylinder: indicates how many rings. It is assumed that there are 32 rings.
Sector: Indicates a loop in the number of sectors.
A sector is 512 bytes.

Test 5th:
1. reload the driver

2. Check the device

minor number "0" represents the entire disk, 1M memory
3. partition

to partition the space of 1M

"n" to add a new partition

set up the first of several partitions, set partition size

view the partition table

this time to see a new partition is created out below to add a partition

input "w" will really write the partition table, this disk is called the partition table in the first sector of the

viewing device

can each format, may be mounted separately

5th partitioning program

/*
 * 参考:drivers\block\xd.c
 *        drivers\block\z2ram.c
 */
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/timer.h>
#include <linux/genhd.h>
#include <linux/hdreg.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/wait.h>
#include <linux/blkdev.h>
#include <linux/blkpg.h>
#include <linux/delay.h>
#include <linux/io.h>

#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/dma.h>

#define RAMBLOCK_SIZE (1204*1024)    //应该是1024*1024,只是内存大小不同

static int major;
static struct gendisk* ramblock_disk;
static request_queue_t* ramblock_queue;
static DEFINE_SPINLOCK(ramblock_lock);
static unsigned char* ramblock_buffer;

static int ramblock_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
    /* 容量 =   磁头 * 柱面 * 扇区 * 512 */
    geo->heads = 2;
    geo->sectors = 32;
    geo->cylinders = RAMBLOCK_SIZE/2/32/512;
    return 0;
}

static struct block_device_operations ramblock_fops = {
    .owner    = THIS_MODULE,
    .getgeo = ramblock_getgeo,
};

static void do_ramblock_request (request_queue_t * q)
{
    struct request *req;
    //static unsigned int w_cnt = 0, r_cnt = 0;
    while ((req = elv_next_request(q)) != NULL) {
        /* 要开始提交的第几个扇区 */
        unsigned long offset = req->sector * 512;
        /* 长度 */
        unsigned long len  = req->current_nr_sectors * 512;

        if (rq_data_dir(req) == READ)
        {//memcpy(dest,src,len)
            memcpy(req->buffer, ramblock_buffer + offset, len);
            //printk("read %d\n", ++r_cnt);
        }
        else
        {
            memcpy(ramblock_buffer + offset, req->buffer, len);
            //printk("write %d\n", ++w_cnt);
        }
        end_request(req, 1);    /* wrap up, 0 = fail, 1 = success */
        }
}

static int ram_block_init(void)
{
    /* 1. 分配一个disk结构 */
    /* 分配的次设备号个数,16表示组多能创建15个分区,其中次设备号为0表示整个磁盘。 */
    /* 如果不想分区,写为1就可以了 */
    ramblock_disk = alloc_disk(16);
    /* 2. 设置 */
    /* 2.1 分配/设置队列 */
    ramblock_queue = blk_init_queue(do_ramblock_request, &ramblock_lock);
    ramblock_disk->queue = ramblock_queue;
    /* 2.2 设置其它属性:比如容量 */
    major = register_blkdev(0, "ramblock");
    ramblock_disk->major = major;
    ramblock_disk->first_minor = 0;
    sprintf(ramblock_disk->disk_name, "ramblock");
    ramblock_disk->fops = &ramblock_fops;

    set_capacity(ramblock_disk, RAMBLOCK_SIZE/512);
    /* 4.硬件相关操作 */
    ramblock_buffer = kzalloc(RAMBLOCK_SIZE, GFP_KERNEL);
    /* 3.注册 */
    add_disk(ramblock_disk);
    return 0;
}

static void ram_block_exit(void)
{
    put_disk(ramblock_disk);
    blk_cleanup_queue(ramblock_queue);
    unregister_blkdev(major, "ramblock");
    del_gendisk(ramblock_disk);
    kfree(ramblock_buffer);
}

module_init(ram_block_init);
module_exit(ram_block_exit);

MODULE_LICENSE("GPL");

Personal summary:

    格式化、读写文件等都是由"文件系统"这一层将文件的读写转换成对扇区的读写。调用"ll_rw_block"会把读写放到你的队列中去。会调用你的"队列请求函数"来处理。只要写好"队列请求函数"即可。
    一旦使用读写文件等操作就会被文件系统拆分成对不同扇区的一个一个读写请求然后加入队列,在队列会调用电梯调度算法,最终就会调用"do_request"函数,在函数里面从队列里取出一个请求以实现对硬件的读写操作。

<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">

Guess you like

Origin www.cnblogs.com/luosir520/p/11457409.html