linux 塊設備驅動(二)——塊設備數據結構


本文來源於:

1. http://www.cnblogs.com/dyllove98/archive/2013/07/01/3165567.html

塊設備相關的數據結構以及接口:

      塊設備接口則相對復雜,讀寫API沒有直接到塊設備層,而是直接到文件系統層,然后再由文件系統層發起讀寫請求。

一: block_device:  block_device結構代表了內核中的一個塊設備。它可以表示整個磁盤或一個特定的分區。當這個結構代表一個分區時,它的bd_contains成員指向包含這個分區的設備,bd_part成員指向設備的分區結構。當這個結構代表一個塊設備時,bd_disk成員指向設備的gendisk結構。

struct block_device {  
    dev_t           bd_dev;  
    struct inode *  bd_inode;   /*分區結點*/  
    int         bd_openers;  
    struct semaphore    bd_sem; /*打開/關閉鎖*/  
    struct semaphore    bd_mount_sem;   /* 加載互斥鎖*/  
    struct list_head    bd_inodes;  
    void *      bd_holder;  
    int         bd_holders;  
    struct block_device *   bd_contains;  
    unsigned        bd_block_size;//分區塊大小  
    struct hd_struct *  bd_part;  
    unsigned        bd_part_count;//打開次數  
    int         bd_invalidated;  
    struct gendisk *    bd_disk;  
    struct list_head    bd_list;  
    struct backing_dev_info *bd_inode_backing_dev_info;  
    unsigned long   bd_private;  
};  
 
 
二:gendisk是一個單獨的磁盤驅動器的內核表示。內核還使用gendisk來表示分區。
struct gendisk {  
    int major;          //主設備號  
    int first_minor;     
    int minors;         //最大的次設備號數量,如果設備不能分區,該值為1                                   
    char disk_name[32]; //主設備名  
    struct hd_struct **part;    //分區信息,有minors個  
    struct block_device_operations *fops;//設備操作  
    struct request_queue *queue;    //設備管理I/O請求  
    void *private_data;  
    sector_t capacity;  
    int flags;  
    char devfs_name[64];  
    int number;  
    struct device *driverfs_dev;  
    struct kobject kobj;  
    struct timer_rand_state *random;  
    int policy;  
    atomic_t sync_io;     
    unsigned long stamp, stamp_idle;  
    int in_flight;  
#ifdef  CONFIG_SMP  
    struct disk_stats *dkstats;  
#else  
    struct disk_stats dkstats;  
#endif  
};  
gendisk結構的操作函數包括以下幾個:
struct gendisk *alloc_disk(int minors);     //分配磁盤  
void add_disk(struct gendisk *disk);        //增加磁盤信息  
void unlink_gendisk(struct gendisk *disk)   //刪除磁盤信息  
void delete_partition(struct gendisk *disk, int part);  //刪除分區  
void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len, int flags);//添加分區  
 
 
三: block_device_operations結構是塊設備對應的操作接口,是連接抽象的塊設備操作與具體塊設備操作之間的樞紐。
 
struct block_device_operations {  
    int (*open) (struct inode *, struct file *);  
    int (*release) (struct inode *, struct file *);  
    int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long);  
    long (*unlocked_ioctl) (struct file *, unsigned, unsigned long);  
    long (*compat_ioctl) (struct file *, unsigned, unsigned long);  
    int (*direct_access) (struct block_device *, sector_t, unsigned long *);  
    int (*media_changed) (struct gendisk *);  
    int (*revalidate_disk) (struct gendisk *);  
    int (*getgeo)(struct block_device *, struct hd_geometry *);  
    struct module *owner;  
};  
block_device_operations並不能完全提供文件操作全部的API,實際上只提供了open、release等函數,其他的文件操作依賴於def_blk_fops:
const struct file_operations def_blk_fops = {  
    .open   = blkdev_open,  
    .release    = blkdev_close,  
    .llseek = block_llseek,  
    .read       = do_sync_read,  
    .write  = do_sync_write,  
    .aio_read   = generic_file_aio_read,  
    .aio_write= generic_file_aio_write_nolock,  
    .mmap   = generic_file_mmap,  
    .fsync  = block_fsync,  
    .unlocked_ioctl = block_ioctl,  
#ifdef CONFIG_COMPAT  
    .compat_ioctl   = compat_blkdev_ioctl,  
#endif  
    .splice_read        = generic_file_splice_read,  
    .splice_write   = generic_file_splice_write,  
}; 

 

四: 系統對塊設備進行讀寫操作時,通過塊設備通用的讀寫操作函數將一個請求保存在該設備的操作請求隊列(request queue)中,然后調用這個塊設備的底層處理函數,對請求隊列中的操作請求進行逐一執行。request_queue結構描述了塊設備的請求隊列,該結構定義如下:

struct request_queue  
{  
    struct list_head    queue_head;  
    struct request      *last_merge;  
    elevator_t      elevator;  
    /*請求隊列列表*/  
    struct request_list     rq;  
    request_fn_proc     *request_fn;  
    merge_request_fn    *back_merge_fn;  
    merge_request_fn    *front_merge_fn;  
    merge_requests_fn   *merge_requests_fn;  
    make_request_fn     *make_request_fn;  
    prep_rq_fn          *prep_rq_fn;  
    unplug_fn           *unplug_fn;  
    merge_bvec_fn       *merge_bvec_fn;  
    activity_fn         *activity_fn;  
    /*自動卸載狀態*/  
    struct timer_list   unplug_timer;  
    int         unplug_thresh;    
    unsigned long       unplug_delay;   /*自動卸載延時*/  
    struct work_struct  unplug_work;  
    struct backing_dev_info backing_dev_info;  
    void                *queuedata;  
    void                *activity_data;  
    unsigned long       bounce_pfn;  
    int             bounce_gfp;  
    unsigned long       queue_flags;//各種隊列標志  
    /*保護隊列結構,避免重入*/  
    spinlock_t          *queue_lock;  
    /* 請求的核心結構*/  
    struct kobject kobj;  
    /*請求的配置*/  
    unsigned long       nr_requests;    /* 請求的最大數*/  
    unsigned int        nr_congestion_on;  
    unsigned int        nr_congestion_off;  
    unsigned short      max_sectors;  
    unsigned short      max_phys_segments;  
    unsigned short      max_hw_segments;  
    unsigned short      hardsect_size;  
    unsigned int        max_segment_size;  
    unsigned long       seg_boundary_mask;  
    unsigned int        dma_alignment;  
    struct blk_queue_tag    *queue_tags;  
    atomic_t        refcnt;  
    unsigned int        in_flight;  
    /*sg 參數配置*/  
    unsigned int        sg_timeout;  
    unsigned int        sg_reserved_size;  
};  
請求隊列相關的處理函數包括:
//創建隊列時提供了一個自旋鎖。  
request_queue_t *blk_init_queue(request_fn_proc *rfn, spinlock_t *lock);  
//獲得隊列中第一個未完成的請求。  
struct request *elv_next_request(request_queue_t *q);  
void end_request(struct request *req, int uptodate);//請求完成  
void blk_stop_queue(request_queue_t *queue); //停止請求  
void blk_start_queue(request_queue_t *queue); //開始請求  
void blk_cleanup_queue(request_queue_t *);//清除請求隊列 

 

五:向內核注冊和注銷一個塊設備可使用如下函數:

int register_blkdev(unsigned int major, const char *name);  
int unregister_blkdev(unsigned int major, const char *name); 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM