日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux块设备驱动简述(Linux驱动开发篇)

發(fā)布時間:2023/12/31 linux 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux块设备驱动简述(Linux驱动开发篇) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、塊設備

  • 塊設備驅動是Linux 三大驅動類型之一。
  • 塊設備驅動要遠比字符設備驅動復雜得多,不同類型的存儲設備又對應不同的驅動子系統(tǒng)。
  • 塊設備是針對存儲設備的,比如 SD 卡、EMMC、NAND Flash、Nor Flash、SPI Flash、機械硬盤、固態(tài)硬盤等。

塊設備和字符設備的區(qū)別?

  • 塊設備以塊(是VFS基本數(shù)據(jù)傳輸單位)為單位進行讀寫,字符設備以字節(jié)的形式進行讀寫,
  • 塊設備在結構上是可以進行隨機訪問的,對于這些設備的讀寫都是按塊進行的塊設備使用緩沖區(qū)來暫時存放數(shù)據(jù),等到條件成熟以后在一次性將緩沖區(qū)中的數(shù)據(jù)寫入塊設備中。(這樣就減少了對塊設備的擦除次數(shù),提高了塊設備壽命。)
  • 字符設備是順序的數(shù)據(jù)流設備,字符設備是按照字節(jié)進行讀寫訪問的。字符設備不需要緩沖區(qū),對于字符設備的訪問都是實時的,而且也不需要按照固定的塊大小進行訪問
  • 總結一下:
    字符設備:實時、按照字節(jié)訪問,無緩沖。
    塊設備:帶有緩沖區(qū),按照塊大小進行訪問。(一種是隨機訪問。一種是按順序訪問)

塊設備的類別

  • 針對不同的存儲設備實現(xiàn)了不同的I/O調度算法。
  • 塊設備結構的不同其 I/O算法也會不同,比如對于EMMC、SD卡、NAND Flash這類沒有任何機械設備的存儲設備就可以任意讀寫任何的扇區(qū)(塊設備物理存儲單元)。
  • 但是對于機械硬盤這樣帶有磁頭的設備,讀取不同的盤面或者磁道里面的數(shù)據(jù),磁頭都需要進行移動,因此對于機械硬盤而言,將那些雜亂的訪問按照一定的順序進行排列可以有效提高磁盤性能。
  • ===這個后面的框架你會發(fā)現(xiàn)是有所不同的。

二、塊設備驅動框架簡述

  • 在了解具體的塊設備驅動框架的大概,我們現(xiàn)需要了解一下其中的結構體和一些函數(shù)
/* @ 定義在include/linux/fs.h文件中 @ block_device 結構體 @ linux 內核使用 block_device 表示塊設備 */struct block_device { dev_t bd_dev; /* not a kdev_t - it's a search key */ int bd_openers; struct inode *bd_inode; /* will die */ struct super_block *bd_super; struct mutex bd_mutex; /* open/close mutex */ struct list_head bd_inodes; void * bd_claiming; void * bd_holder; int bd_holders; bool bd_write_holder; #ifdef CONFIG_SYSFS struct list_head bd_holder_disks; #endif struct block_device *bd_contains; unsigned bd_block_size; struct hd_struct *bd_part; /*number of times partitions within this device have been opened.*/unsigned bd_part_count; int bd_invalidated; struct gendisk *bd_disk; //比如一個硬盤或者分區(qū),如果是硬盤的話 bd_disk就指向通用磁盤結構 gendiskstruct request_queue *bd_queue; struct list_head bd_list;unsigned long bd_private; /* The counter of freeze processes */ int bd_fsfreeze_count; /* Mutex for freeze */ struct mutex bd_fsfreeze_mutex; }; /* @ 向內核注冊新的塊設備、申請設備號 @ major:主設備號。 @ name:塊設備名字。 @ 返回值:如果參數(shù) major 在 1~255 之間的話表示自定義主設備號,那么返回 0 表示注冊成功,如果返回負值的話表示注冊失敗。如果 major 為 0 的話表示由系統(tǒng)自動分配主設備號,那么返回值就是系統(tǒng)分配的主設備號(1~255),如果返回負值那就表示注冊失敗 */ int register_blkdev(unsigned int major, const char *name) /* @ 如果不使用某個塊設備了,那么就需要注銷掉 @ major:要注銷的塊設備主設備號 @ name:要注銷的塊設備名字。 @ 返回值:無 */ void unregister_blkdev(unsigned int major, const char *name)/* @ 定義在 include/linux/genhd.h中 @ gendisk 結構體 @ linux內核使用gendisk來描述一個磁盤設備 */ struct gendisk { /* major, first_minor and minors are input parameters only, * don't use directly. Use disk_devt() and disk_max_parts(). */ int major; /* major number of driver */ int first_minor; /*磁盤的第一個次設備號*/int minors; /*磁盤的次設備號數(shù)量,也就是磁盤的分區(qū)數(shù)量,這些分區(qū)的主設備號一樣,次設備號不同*/char disk_name[DISK_NAME_LEN]; /* name of major driver */ char *(*devnode)(struct gendisk *gd, umode_t *mode); unsigned int events; /* supported events */ unsigned int async_events; /* async events, subset of all */ /* Array of pointers to partitions indexed by partno. * Protected with matching bdev lock but stat and other * non-critical accesses use RCU. Always access through * helpers. */ struct disk_part_tbl __rcu *part_tbl; /*此數(shù)組每一項都對應一個分區(qū)信息*/struct hd_struct part0; const struct block_device_operations *fops; /*字符設備操作集 file_operations一樣*/struct request_queue *queue; /*,queue為磁盤對應的請求隊列,所以針對該磁盤設備的請求都放到此隊列中,驅動程序需要處理此隊列中的所有請求*/void *private_data; int flags; struct device *driverfs_dev; // FIXME: remove struct kobject *slave_dir; struct timer_rand_state *random; atomic_t sync_io; /* RAID */ struct disk_events *ev; #ifdef CONFIG_BLK_DEV_INTEGRITY struct blk_integrity *integrity; #endif int node_id; } /*************************************帶有機械磁頭的磁盤 @ 使用gendisk之前要先申請 @ minors:次設備號數(shù)量,也就是gendisk對應的分區(qū)數(shù)量。 @ 返回值:成功:返回申請到的 gendisk,失敗:NULL。 */ struct gendisk *alloc_disk(int minors) /* @ 使用 add_disk 函數(shù)將申請到的gendisk添加到內核中 @ disk:要添加到內核的 gendisk。 @ 返回值:無。 */ void add_disk(struct gendisk *disk) /* @ 在初始化 gendisk 的時候也需要設置其容量 @ disk:要設置容量的 gendisk。 @ size:磁盤容量大小,注意這里是扇區(qū)數(shù)量。塊設備中最小的可尋址單元是扇區(qū),一個扇區(qū)一般是 512字節(jié)比如一個 2MB 的磁盤,其扇區(qū)數(shù)量就是(2*1024*1024)/512=4096。 @ 返回值:無。 */ void set_capacity(struct gendisk *disk, sector_t size) /* @ 內核會通過 get_disk 和 put_disk 這兩個函數(shù)來調整 gendisk 的引用計數(shù) @ get_disk是增加 gendisk的引用計數(shù) @ put_disk是減少gendisk的引用計數(shù) */ truct kobject *get_disk(struct gendisk *disk) void put_disk(struct gendisk *disk) /* @ 刪除gendisk的話可以使用函數(shù)del_gendisk @ gp:要刪除的gendisk。 @ 返回值:無。 */ void del_gendisk(struct gendisk *gp) /* @ 定義在include/linux/blkdev.h中 @ block_device_operations 結構體 @ 和字符設備的file _operations一樣,塊設備也有操作集 */struct block_device_operations { int (*open) (struct block_device *, fmode_t); void (*release) (struct gendisk *, fmode_t); int (*rw_page)(struct block_device *, sector_t, struct page *, int rw); /*讀寫指定頁*/int (*ioctl) (struct block_device *, fmode_t, unsigned, unsigned long); /*32-32塊設備的IO控制*/int (*compat_ioctl) (struct block_device *, fmode_t, unsigned, unsigned long); /*64-32塊設備IO控制*/long (*direct_access)(struct block_device *, sector_t, void **, unsigned long *pfn, long size); unsigned int (*check_events) (struct gendisk *disk, unsigned int clearing); /* ->media_changed() is DEPRECATED, use ->check_events() instead */int (*media_changed) (struct gendisk *); void (*unlock_native_capacity) (struct gendisk *); int (*revalidate_disk) (struct gendisk *); int (*getgeo)(struct block_device *, struct hd_geometry *); /*磁頭、柱面、扇區(qū)*//* this callback is with swap_lock and sometimes page table lock held */ void (*swap_slot_free_notify) (struct block_device *, unsigned long); struct module *owner; /*表示此結構屬于哪個模塊*/};
  • 我們上面的介紹的fops操作集里面不像字符設備一樣里面有read和write函數(shù),但是我們呢,是肯定要進行讀寫操作的。

  • 要想了解整個流程,首先就要引入塊設備驅動中非常重要的三個角色。
    request_queue、
    request
    bio

  • 內核將對塊設備的讀寫都發(fā)送到請求隊列 request_queue 中,request_queue 中是大量的request(請求結構體),而 request 又包含了 bio,bio 保存了讀寫相關數(shù)據(jù)。比如從塊設備的哪個地址開始讀取、讀取的數(shù)據(jù)長度,讀取到哪里,如果是寫的話還包括要寫入的數(shù)據(jù)等。

  • 下面我們繼續(xù)了解一下其中的結構體和一些函數(shù)目的就是可以了解requestqueue和quest。

/* @ 上面談到過block_device 里面含有requet_queue. @ 因為在編寫塊設備驅動的時候,每個磁盤(gendisk)都要分配一個 request_queue */ /*============================================================機械磁頭硬盤 @ 這個一般用于像機械硬盤這樣的存儲設備,需要 I/O 調度器來優(yōu)化數(shù)據(jù)讀寫過程 @ 申請并初始化一個 request_queue @ rfn:請求處理函數(shù)指針,每個 request_queue 都要有一個請求處理函數(shù), @ lock:自旋鎖指針,需要驅動編寫人員定義一個自旋鎖,然后傳遞進來。請求隊列會使用這個自旋鎖。 @ 返回值:如果為NULL的話表示失敗,成功的話就返回申請到的request_queue 地址。 */ request_queue *blk_init_queue(request_fn_proc *rfn, spinlock_t *lock) /* @ 請求處理函數(shù)需要驅動編寫人員自行實現(xiàn) @ 與上面依賴 @ q:請求隊列 */ void (request_fn_proc) (struct request_queue *q) /*我們只傳入了request+_queue*/ /*===========================================================EMMC、SD卡非機械設備 @ 但是對于 EMMC、SD 卡這樣的非機械設備,可以進行完全隨機訪問,所以就不需要復雜的 I/O 調度器了(分配請求隊列+綁定制造請求函數(shù)) @ gfp_mask: 內存分配掩碼 @ 返回值:申請到的無 I/O調度的request_queue。 */ struct request_queue *blk_alloc_queue(gfp_t gfp_mask) /* @ 上面blk_alloc_queue函數(shù)申請到的請求隊列綁定一個“制造請求”函數(shù) @ q:需要綁定的請求隊列,也就是 blk_alloc_queue申請到的請求隊列。 @ mfn:需要綁定的“制造”請求函數(shù) @ 返回值:無 */ void blk_queue_make_request(struct request_queue *q, make_request_fn *mfn) /* @ 與上面依賴 @ “制造請求”函數(shù)需要驅動編寫人員實現(xiàn) @ 返回值:無。 */ void (make_request_fn) (struct request_queue *q, struct bio *bio) /* @ 當卸載塊設備驅動的時候我們還需要刪除掉前面申請到的 request_queue @ q:需要刪除的請求隊列 @ 返回值:無。 */ void blk_cleanup_queue(struct request_queue *q) /* @ 請求隊列(request_queue)里面包含的就是一系列的請求(request) */ /* @ 從request_queue中依次獲取每個request @ q:指定request_queue。 @ 返回值:request_queue 中下一個要處理的請求(request),如果沒有要處理的請求就返回NULL @ */ request *blk_peek_request(struct request_queue *q) /* @ 獲取到下一個要處理的請求以后就要開始處理這個請求 @ req:要開始處理的請求 @ 返回值:無。 */ void blk_start_request(struct request *req) /* @ 此函數(shù)功能等是上面的兩個函數(shù)的合體==一步到位處理請求 @ q:指定request_queue。 */ struct request *blk_fetch_request(struct request_queue *q) { struct request *rq; rq = blk_peek_request(q); if (rq) blk_start_request(rq); return rq; }
  • 每個request里面里面會有多個bio,bio保存著最終要讀寫的數(shù)據(jù)、地址等信息上層應用程序對于塊設備的讀寫會被構造成一個或多個bio結構,bio結構描述了要讀寫的起始扇區(qū)、要讀寫的扇區(qū)數(shù)量、是讀取還是寫入、頁偏移、數(shù)據(jù)長度等等信息。上層會將 bio提交給I/O調度器, I/O 調度器會將這些bio構造成request結構,而一個物理存儲設備對應一個 request_queue,request_queue里面順序存放著一系列的 request。新產生的 bio可能被合并到 request_queue里現(xiàn)有的 request 中,也可能產生新的 request,然后插入到 request_queue 中合適的位置,這一切都是由I/O 調度器來完成的

  • 下面我們繼續(xù)了解一下其中的結構體和一些函數(shù)目的就是可以了解quest中的bio。

/* @ 定義在 include/linux/blk_types.h中 @ bio 結構體 */struct bio { struct bio *bi_next; /* 請求隊列的下一個 bio */ struct block_device *bi_bdev; /* 指向塊設備 */ unsigned long bi_flags; /* bio 狀態(tài)等信息 */ unsigned long bi_rw; /* I/O 操作,讀或寫 */ struct bvec_iter bi_iter; /* I/O 操作,讀或寫===== */ unsigned int bi_phys_segments; unsigned int bi_seg_front_size; unsigned int bi_seg_back_size; atomic_t bi_remaining; bio_end_io_t *bi_end_io; void *bi_private; #ifdef CONFIG_BLK_CGROUP /* * Optional ioc and css associated with this bio. Put on bio * release. Read comment on top of bio_associate_current(). */ struct io_context *bi_ioc; struct cgroup_subsys_state *bi_css; #endif union { #if defined(CONFIG_BLK_DEV_INTEGRITY) struct bio_integrity_payload *bi_integrity; #endif }; unsigned short bi_vcnt; /* bio_vec 列表中元素數(shù)量 */ unsigned short bi_max_vecs; /* bio_vec 列表長度 */ atomic_t bi_cnt; /* pin count */ struct bio_vec *bi_io_vec; /* bio_vec 列表 */ struct bio_set *bi_pool; struct bio_vec bi_inline_vecs[0]; }; /* @ 屬于bio中 @ 定義在 include/linux/blk_types.h中 @ bio 結構體 */struct bvec_iter { sector_t bi_sector; /* I/O 請求的設備起始扇區(qū)(512 字節(jié)) */ unsigned int bi_size; /* 剩余的 I/O 數(shù)量 */ unsigned int bi_idx; /* blv_vec 中當前索引 */ unsigned int bi_bvec_done; /* 當前 bvec 中已經處理完成的字節(jié)數(shù) */ }; /* @ 屬于bio中 @ 定義在 include/linux/blk_types.h中 @ bio 結構體 */struct bio_vec { struct page *bv_page; /* 頁 */ unsigned int bv_len; /* 長度 */ unsigned int bv_offset; /* 偏移 */ };
  • 上面的bio和bio_vec和bvec_iter的關系
  • 我們對于物理存儲設備的操作不外乎就是將 RAM 中的數(shù)據(jù)寫入到物理存儲設備中,或者、將物理設備中的數(shù)據(jù)讀取到 RAM 中去處理。數(shù)據(jù)傳輸三個要求:數(shù)據(jù)源、數(shù)據(jù)長度以及數(shù)據(jù)目的地,也就是你要從物理存儲設備的哪個地址開始讀取、讀取到 RAM 中的哪個地址處、讀取的數(shù)據(jù)長度是多少。
    bi_iter這個結構體成員變量就用于描述物理存儲設備地址信息,比如要操作的扇區(qū)地址
    bi_io_vec指向 bio_vec數(shù)組首地址,bio_vec數(shù)組就是RAM信息,比如頁地址、頁偏移以及長度

三、簡單實例

  • 接下來我們使用開發(fā)板上的 RAM 模擬一段塊設備,也就是ramdisk,然后編寫塊設備驅動
  • 我們上面也提到過我們在上面請求隊列的時候分為機械硬盤比如SD卡非機械硬盤這兩種不同的
  • 一般 blk_alloc_queue 和blk_queue_make_request 是搭配在一起使用的,用于那么非機械的存儲設備、無需 I/O 調度器,比如 EMMC、SD 卡等。blk_init_queue 函數(shù)會給請求隊列分配一個 I/O調度器,用于機械存儲設備,比如機械硬盤等。

1、傳統(tǒng)的使用請求隊列的時候,也就是針對機械硬盤的時候如何編寫驅動

#include <linux/types.h> #include <linux/kernel.h> #include <linux/delay.h> #include <linux/ide.h> #include <linux/init.h> #include <linux/module.h> #include <linux/errno.h> #include <linux/gpio.h> #include <linux/cdev.h> #include <linux/device.h> #include <linux/of_gpio.h> #include <linux/semaphore.h> #include <linux/timer.h> #include <linux/i2c.h> #include <linux/genhd.h> #include <linux/blkdev.h> #include <linux/hdreg.h>#include <asm/mach/map.h> #include <asm/uaccess.h> #include <asm/io.h>#define RAMDISK_SIZE (2 * 1024 * 1024) /* 容量大小為2MB */ #define RAMDISK_NAME "ramdisk" /* 名字 */ #define RADMISK_MINOR 3 /* 表示有三個磁盤分區(qū)!不是次設備號為3! *//* ramdisk設備結構體 */ struct ramdisk_dev{int major; /* 主設備號 */unsigned char *ramdiskbuf; /* ramdisk內存空間,用于模擬塊設備 */spinlock_t lock; /* 自旋鎖 */struct gendisk *gendisk; /* gendisk */struct request_queue *queue;/* 請求隊列 */};struct ramdisk_dev ramdisk; /* ramdisk設備 *//** @description : 打開塊設備* @param - dev : 塊設備* @param - mode : 打開模式* @return : 0 成功;其他 失敗*/ int ramdisk_open(struct block_device *dev, fmode_t mode) {printk("ramdisk open\r\n");return 0; }/** @description : 釋放塊設備* @param - disk : gendisk* @param - mode : 模式* @return : 0 成功;其他 失敗*/ void ramdisk_release(struct gendisk *disk, fmode_t mode) {printk("ramdisk release\r\n"); }/** @description : 獲取磁盤信息* @param - dev : 塊設備* @param - geo : 模式* @return : 0 成功;其他 失敗*/ int ramdisk_getgeo(struct block_device *dev, struct hd_geometry *geo) {/* 這是相對于機械硬盤的概念 */geo->heads = 2; /* 磁頭 */geo->cylinders = 32; /* 柱面 */geo->sectors = RAMDISK_SIZE / (2 * 32 *512); /* 一個磁道上的扇區(qū)數(shù)量 */return 0; }/* * 塊設備操作函數(shù) */ static struct block_device_operations ramdisk_fops = {.owner = THIS_MODULE,.open = ramdisk_open,.release = ramdisk_release,.getgeo = ramdisk_getgeo, };/** @description : 處理傳輸過程* @param-req : 請求* @return : 無*/ static void ramdisk_transfer(struct request *req) { unsigned long start = blk_rq_pos(req) << 9; /* blk_rq_pos獲取到的是扇區(qū)地址,左移9位轉換為字節(jié)地址 */unsigned long len = blk_rq_cur_bytes(req); /* 大小 *//* bio中的數(shù)據(jù)緩沖區(qū)* 讀:從磁盤讀取到的數(shù)據(jù)存放到buffer中* 寫:buffer保存這要寫入磁盤的數(shù)據(jù)*/void *buffer = bio_data(req->bio); if(rq_data_dir(req) == READ) /* 讀數(shù)據(jù) */ memcpy(buffer, ramdisk.ramdiskbuf + start, len);else if(rq_data_dir(req) == WRITE) /* 寫數(shù)據(jù) */memcpy(ramdisk.ramdiskbuf + start, buffer, len);}/** @description : 請求處理函數(shù)* @param-q : 請求隊列* @return : 無*/ void ramdisk_request_fn(struct request_queue *q) {int err = 0;struct request *req;/* 循環(huán)處理請求隊列中的每個請求 */req = blk_fetch_request(q);while(req != NULL) {/* 針對請求做具體的傳輸處理 */ramdisk_transfer(req);/* 判斷是否為最后一個請求,如果不是的話就獲取下一個請求* 循環(huán)處理完請求隊列中的所有請求。*/if (!__blk_end_request_cur(req, err))req = blk_fetch_request(q);} }/** @description : 驅動出口函數(shù)* @param : 無* @return : 無*/ static int __init ramdisk_init(void) {int ret = 0;printk("ramdisk init\r\n");/* 1、申請用于ramdisk內存 */ramdisk.ramdiskbuf = kzalloc(RAMDISK_SIZE, GFP_KERNEL);if(ramdisk.ramdiskbuf == NULL) {ret = -EINVAL;goto ram_fail;}/* 2、初始化自旋鎖 */spin_lock_init(&ramdisk.lock);/* 3、注冊塊設備 */ramdisk.major = register_blkdev(0, RAMDISK_NAME); /* 由系統(tǒng)自動分配主設備號 */if(ramdisk.major < 0) {goto register_blkdev_fail;} printk("ramdisk major = %d\r\n", ramdisk.major);/* 4、分配并初始化gendisk */ramdisk.gendisk = alloc_disk(RADMISK_MINOR);if(!ramdisk.gendisk) {ret = -EINVAL;goto gendisk_alloc_fail;}/* 5、分配并初始化請求隊列 */ramdisk.queue = blk_init_queue(ramdisk_request_fn, &ramdisk.lock);if(!ramdisk.queue) {ret = EINVAL;goto blk_init_fail;}/* 6、添加(注冊)disk */ramdisk.gendisk->major = ramdisk.major; /* 主設備號 */ramdisk.gendisk->first_minor = 0; /* 第一個次設備號(起始次設備號) */ramdisk.gendisk->fops = &ramdisk_fops; /* 操作函數(shù) */ramdisk.gendisk->private_data = &ramdisk; /* 私有數(shù)據(jù) */ramdisk.gendisk->queue = ramdisk.queue; /* 請求隊列 */sprintf(ramdisk.gendisk->disk_name, RAMDISK_NAME); /* 名字 */set_capacity(ramdisk.gendisk, RAMDISK_SIZE/512); /* 設備容量(單位為扇區(qū)) */add_disk(ramdisk.gendisk);return 0;blk_init_fail:put_disk(ramdisk.gendisk);//del_gendisk(ramdisk.gendisk); gendisk_alloc_fail:unregister_blkdev(ramdisk.major, RAMDISK_NAME); register_blkdev_fail:kfree(ramdisk.ramdiskbuf); /* 釋放內存 */ ram_fail:return ret; }/** @description : 驅動出口函數(shù)* @param : 無* @return : 無*/ static void __exit ramdisk_exit(void) {printk("ramdisk exit\r\n");/* 釋放gendisk */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("zuozhongkai");
  • 當我們把上面細心閱讀后,會發(fā)現(xiàn)塊設備驅動框架還是有些字符設備的影子的,只是在具體實現(xiàn)上要復雜一下。

2、對于EMMC、SD、ramdisk這樣沒有機械結構的存儲設備,我們可以直接訪問任意一個扇區(qū),因此可以不需要 I/O 調度器,也就不需要請求隊列了

  • 這里主要貼出區(qū)別的地方
/* @ 驅動函數(shù)入口 */static int __init ramdisk_init(void) { .... /* 5、分配請求隊列 */ ramdisk.queue = blk_alloc_queue(GFP_KERNEL); if(!ramdisk.queue){ ret = -EINVAL; goto blk_allo_fail; } /* 6、設置“制造請求”函數(shù) */ blk_queue_make_request(ramdisk.queue, ramdisk_make_request_fn);/* 7、添加(注冊)disk */ ramdisk.gendisk->major = ramdisk.major; /* 主設備號 */ ramdisk.gendisk->first_minor = 0; /* 起始次設備號 */ ramdisk.gendisk->fops = &ramdisk_fops; /* 操作函數(shù) */ ramdisk.gendisk->private_data = &ramdisk; /* 私有數(shù)據(jù) */ ramdisk.gendisk->queue = ramdisk.queue; /* 請求隊列 */ sprintf(ramdisk.gendisk->disk_name, RAMDISK_NAME); /* 名字 */ set_capacity(ramdisk.gendisk, RAMDISK_SIZE/512); /* 設備容量*/ add_disk(ramdisk.gendisk); .... return ret; } /* * @description : “制造請求”函數(shù) * @param-q : 請求隊列 * @return : 無 */ void ramdisk_make_request_fn(struct request_queue *q, 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 中的每個段 */ bio_for_each_segment(bvec, bio, iter){ char *ptr = page_address(bvec.bv_page) + bvec.bv_offset; len = bvec.bv_len; if(bio_data_dir(bio) == READ) /* 讀數(shù)據(jù) */ memcpy(ptr, ramdisk.ramdiskbuf + offset, len); else if(bio_data_dir(bio) == WRITE) /* 寫數(shù)據(jù) */ memcpy(ramdisk.ramdiskbuf + offset, ptr, len); offset += len; } set_bit(BIO_UPTODATE, &bio->bi_flags); bio_endio(bio, 0); }
  • (分配請求隊列+綁定制造請求函數(shù)) 這部分代替了原有的初始化請求隊列

整體例子代碼

#include <linux/types.h> #include <linux/kernel.h> #include <linux/delay.h> #include <linux/ide.h> #include <linux/init.h> #include <linux/module.h> #include <linux/errno.h> #include <linux/gpio.h> #include <linux/cdev.h> #include <linux/device.h> #include <linux/of_gpio.h> #include <linux/semaphore.h> #include <linux/timer.h> #include <linux/i2c.h> #include <linux/genhd.h> #include <linux/blkdev.h> #include <linux/hdreg.h>#include <asm/mach/map.h> #include <asm/uaccess.h> #include <asm/io.h>#define RAMDISK_SIZE (2 * 1024 * 1024) /* 容量大小為2MB */ #define RAMDISK_NAME "ramdisk" /* 名字 */ #define RADMISK_MINOR 3 /* 表示有三個磁盤分區(qū)!不是次設備號為3! *//* ramdisk設備結構體 */ struct ramdisk_dev{int major; /* 主設備號 */unsigned char *ramdiskbuf; /* ramdisk內存空間,用于模擬塊設備 */spinlock_t lock; /* 自旋鎖 */struct gendisk *gendisk; /* gendisk */struct request_queue *queue;/* 請求隊列 */};struct ramdisk_dev ramdisk; /* ramdisk設備 *//** @description : 打開塊設備* @param - dev : 塊設備* @param - mode : 打開模式* @return : 0 成功;其他 失敗*/ int ramdisk_open(struct block_device *dev, fmode_t mode) {printk("ramdisk open\r\n");return 0; }/** @description : 釋放塊設備* @param - disk : gendisk* @param - mode : 模式* @return : 0 成功;其他 失敗*/ void ramdisk_release(struct gendisk *disk, fmode_t mode) {printk("ramdisk release\r\n"); }/** @description : 獲取磁盤信息* @param - dev : 塊設備* @param - geo : 模式* @return : 0 成功;其他 失敗*/ int ramdisk_getgeo(struct block_device *dev, struct hd_geometry *geo) {/* 這是相對于機械硬盤的概念 */geo->heads = 2; /* 磁頭 */geo->cylinders = 32; /* 柱面 */geo->sectors = RAMDISK_SIZE / (2 * 32 *512); /* 一個磁道上的扇區(qū)數(shù)量 */return 0; }/* * 塊設備操作函數(shù) */ static struct block_device_operations ramdisk_fops = {.owner = THIS_MODULE,.open = ramdisk_open,.release = ramdisk_release,.getgeo = ramdisk_getgeo, };/** @description : “制造請求”函數(shù)* @param-q : 請求隊列* @return : 無*/ void ramdisk_make_request_fn(struct request_queue *q, 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中的每個段 */bio_for_each_segment(bvec, bio, iter){char *ptr = page_address(bvec.bv_page) + bvec.bv_offset;len = bvec.bv_len;if(bio_data_dir(bio) == READ) /* 讀數(shù)據(jù) */memcpy(ptr, ramdisk.ramdiskbuf + offset, len);else if(bio_data_dir(bio) == WRITE) /* 寫數(shù)據(jù) */memcpy(ramdisk.ramdiskbuf + offset, ptr, len);offset += len;}set_bit(BIO_UPTODATE, &bio->bi_flags);bio_endio(bio, 0); }/** @description : 驅動出口函數(shù)* @param : 無* @return : 無*/ static int __init ramdisk_init(void) {int ret = 0;printk("ramdisk init\r\n");/* 1、申請用于ramdisk內存 */ramdisk.ramdiskbuf = kzalloc(RAMDISK_SIZE, GFP_KERNEL);if(ramdisk.ramdiskbuf == NULL) {ret = -EINVAL;goto ram_fail;}/* 2、初始化自旋鎖 */spin_lock_init(&ramdisk.lock);/* 3、注冊塊設備 */ramdisk.major = register_blkdev(0, RAMDISK_NAME); /* 由系統(tǒng)自動分配主設備號 */if(ramdisk.major < 0) {goto register_blkdev_fail;} printk("ramdisk major = %d\r\n", ramdisk.major);/* 4、分配并初始化gendisk */ramdisk.gendisk = alloc_disk(RADMISK_MINOR);if(!ramdisk.gendisk) {ret = -EINVAL;goto gendisk_alloc_fail;}/* 5、分配請求隊列 */ramdisk.queue = blk_alloc_queue(GFP_KERNEL);if(!ramdisk.queue){ret = -EINVAL;goto blk_allo_fail;}/* 6、設置“制造請求”函數(shù) */blk_queue_make_request(ramdisk.queue, ramdisk_make_request_fn);/* 7、添加(注冊)disk */ramdisk.gendisk->major = ramdisk.major; /* 主設備號 */ramdisk.gendisk->first_minor = 0; /* 第一個次設備號(起始次設備號) */ramdisk.gendisk->fops = &ramdisk_fops; /* 操作函數(shù) */ramdisk.gendisk->private_data = &ramdisk; /* 私有數(shù)據(jù) */ramdisk.gendisk->queue = ramdisk.queue; /* 請求隊列 */sprintf(ramdisk.gendisk->disk_name, RAMDISK_NAME); /* 名字 */set_capacity(ramdisk.gendisk, RAMDISK_SIZE/512); /* 設備容量(單位為扇區(qū)) */add_disk(ramdisk.gendisk);return 0;blk_allo_fail:put_disk(ramdisk.gendisk);//del_gendisk(ramdisk.gendisk); gendisk_alloc_fail:unregister_blkdev(ramdisk.major, RAMDISK_NAME); register_blkdev_fail:kfree(ramdisk.ramdiskbuf); /* 釋放內存 */ ram_fail:return ret; }/** @description : 驅動出口函數(shù)* @param : 無* @return : 無*/ static void __exit ramdisk_exit(void) {printk("ramdisk exit\r\n");/* 釋放gendisk */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("zuozhongkai");

總結

以上是生活随笔為你收集整理的linux块设备驱动简述(Linux驱动开发篇)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

水蜜桃亚洲一二三四在线 | 欧美日韩综合在线 | 成年免费在线视频 | 99在线精品视频在线观看 | 久草在线在线精品观看 | 中文字幕在线视频一区 | 中文字幕久久精品 | 色综合天天视频在线观看 | 久久婷婷色 | 黄色三级免费片 | 97夜夜澡人人爽人人免费 | 欧美性猛片, | 在线播放国产一区二区三区 | 色丁香综合 | 成人中文字幕在线观看 | 黄色毛片电影 | 婷婷av综合 | 在线中文字幕一区二区 | 日韩 精品 一区 国产 麻豆 | 蜜桃久久久 | 97人人澡人人爽人人模亚洲 | 久久久伊人网 | 国产成人一区二区三区久久精品 | 精品一区 精品二区 | 精品亚洲va在线va天堂资源站 | 天天插天天干 | 久草免费在线 | 久久艹综合 | 99久久日韩精品免费热麻豆美女 | 亚洲欧美日韩精品久久奇米一区 | 日韩免费av网址 | 成 人 黄 色 片 在线播放 | 操一草 | 成人免费视频网 | 天天射天天舔天天干 | 亚州精品在线视频 | 免费看av在线 | 精品国产_亚洲人成在线 | 综合在线色 | 91在线网站 | www.五月天婷婷.com | 久久人人艹 | 久久久久久蜜桃一区二区 | 国产精品福利在线 | 久久久电影网站 | 91桃色免费视频 | 四虎永久免费在线观看 | 黄色a一级片 | 国产电影一区二区三区四区 | 国产美女无遮挡永久免费 | 天天操网 | 亚州免费视频 | 日韩成人免费在线电影 | 日本性生活免费看 | av资源免费看 | 日韩欧美高清 | 欧美一级视频免费 | 国产精品成久久久久三级 | 欧美日韩1区 | 久久超碰在线 | 免费看亚洲毛片 | 婷婷久久久久 | 久久深夜福利免费观看 | 久久97久久97精品免视看 | 毛片视频网址 | aaa日本高清在线播放免费观看 | 激情五月婷婷激情 | 日韩av网页 | 日韩a级黄色片 | 久久久香蕉视频 | 国产最顶级的黄色片在线免费观看 | 日本午夜在线观看 | 亚洲精品国偷自产在线91正片 | 国产日产精品一区二区三区四区的观看方式 | 婷婷综合久久 | 99夜色| 黄色小网站在线观看 | 337p西西人体大胆瓣开下部 | 一区二区精品在线视频 | 天天干夜夜操视频 | www.亚洲黄色 | 日韩av一卡二卡三卡 | 久久影视网| 亚洲国产字幕 | 人九九精品 | 欧美日韩亚洲第一 | 亚洲欧美日韩精品久久奇米一区 | 91成人破解版 | 国产毛片久久 | 免费观看国产精品视频 | 亚洲欧美精品一区 | 亚洲午夜激情网 | 久久国产精品一区二区三区 | 婷婷六月综合亚洲 | 涩涩网站在线播放 | 色在线最新 | 久久久久伊人 | 成年人免费av | 久久久久免费精品国产小说色大师 | 日本最新高清不卡中文字幕 | av手机版 | 丁香导航 | 国产精品美女在线 | 中文字幕在线免费97 | 日韩免费视频播放 | 国产精品2020 | 国产在线观看中文字幕 | 亚洲在线网址 | 国产专区在线看 | 精品久久久久久亚洲综合网站 | 欧美精品国产精品 | 天天插天天爱 | 国产在线 一区二区三区 | 91av视频在线观看免费 | 亚洲精品午夜久久久久久久 | 自拍超碰在线 | 久久99精品国产99久久6尤 | 成人午夜免费剧场 | 五月激情天| 国产亚洲成人网 | 在线观看av网站 | 日日草夜夜操 | 99电影456麻豆 | 精品福利视频在线观看 | 日韩免费在线观看 | www.色五月.com | 亚洲欧美日韩精品一区二区 | 视频1区2区| 91黄色小视频 | 欧美一级黄色片 | 五月婷婷综合在线观看 | 欧美高清成人 | 国产美女网 | 99热精品在线| 黄色一级在线免费观看 | 精品综合久久 | 91在线视频在线观看 | 久久夜色精品亚洲噜噜国4 午夜视频在线观看欧美 | 夜夜夜草 | 亚洲精品久久激情国产片 | 色偷偷88欧美精品久久久 | 欧美一级片在线观看视频 | 天天天干 | 久久只有精品 | 亚洲精品看片 | 欧美一区日韩一区 | 精品视频在线播放 | 色视频网站在线观看一=区 a视频免费在线观看 | 97超碰成人在线 | 国产精品嫩草69影院 | 九色精品免费永久在线 | 又湿又紧又大又爽a视频国产 | 国产大尺度视频 | 欧美精品在线观看免费 | 国产精品一区二区免费视频 | 国产精品久久久久9999 | 久草视频中文在线 | 亚洲日本在线视频观看 | 国产精品一区二区av麻豆 | 人人草在线观看 | 色网站免费在线看 | 亚洲精品视频在线观看视频 | 久久久久久久久久久黄色 | 亚洲国产精品va在线 | 亚洲精品免费视频 | 国产美腿白丝袜足在线av | 亚洲人成网站精品片在线观看 | 国产午夜三级一区二区三 | 国产盗摄精品一区二区 | 91色综合 | 久久精品视频免费观看 | 在线观看黄色 | 国产在线播放一区二区三区 | 一区二区精品视频 | 日韩久久久久久久久久 | 美腿丝袜av | 手机在线欧美 | 黄色的视频网站 | 中文视频一区二区 | 国产91免费在线观看 | 久久人人爽人人爽人人片 | 亚洲一区二区三区毛片 | 欧美一级免费高清 | 欧洲精品视频一区 | 亚洲jizzjizz日本少妇 | 日韩中文字幕亚洲一区二区va在线 | 亚洲涩涩一区 | 欧美日韩国产免费视频 | 特级xxxxx欧美 | 伊人热 | 91九色蝌蚪视频网站 | 欧美激情一区不卡 | 久久a久久 | 日韩高清精品免费观看 | 日本动漫做毛片一区二区 | 免费观看www7722午夜电影 | 国产护士hd高朝护士1 | 亚洲黄色av网址 | 亚洲精品国产高清 | 国产污视频在线观看 | 五月天亚洲婷婷 | 日韩在线观看电影 | 日韩一区二区三区免费电影 | a午夜电影| 日日干日日色 | 99热在线精品观看 | 成人网在线免费视频 | 欧美精品一区二区免费 | 亚洲无吗av | 国产精品区二区三区日本 | 精品1区二区 | 亚洲欧洲成人精品av97 | av在线网站大全 | 日韩在线视频播放 | 美女视频黄是免费的 | 91毛片在线 | 免费在线成人 | 91精品国产自产91精品 | 免费视频xnxx com | 国产成人一区在线 | 亚洲成a人片在线观看网站口工 | 国产精品18久久久久久久久久久久 | 色播五月激情五月 | 天堂av高清 | 国产一区二区在线播放 | 黄网站app在线观看免费视频 | 亚洲乱码在线观看 | av官网在线 | 伊人成人激情 | 亚洲精品视频在线观看网站 | 自拍超碰在线 | 国产精品9999久久久久仙踪林 | 黄色成年片 | 欧美疯狂性受xxxxx另类 | 国产精品久久久网站 | 久久久五月天 | 91九色视频国产 | 成人黄色在线视频 | 国产在线观看h | 手机在线看永久av片免费 | 国产中文字幕在线 | 国产精品国产三级国产aⅴ无密码 | 91综合久久一区二区 | 天堂av在线免费观看 | 久久久福利影院 | 亚洲精品乱码久久久久v最新版 | 中文字幕中文 | 99热这里有| 精品国产一区二 | 91在线视频播放 | 精品国产欧美一区二区三区不卡 | 精品国产一区二区三区噜噜噜 | 夜色在线资源 | 久久精品国产免费观看 | 国产黄免费 | 亚洲在线视频免费 | 成人av一二三区 | 人人网av| 人人要人人澡人人爽人人dvd | 亚洲免费国产视频 | 久久er99热精品一区二区三区 | 韩国一区二区三区在线观看 | www日| 久久久久久久久久久影院 | 天天鲁一鲁摸一摸爽一爽 | 国产精品日韩 | 天天躁天天躁天天躁婷 | 国产成人av免费在线观看 | 日本黄色免费在线观看 | 日韩高清免费在线 | 97视频亚洲| 免费看片网址 | 狠狠躁夜夜躁人人爽超碰97香蕉 | 国产一级片免费播放 | 黄色小说18| 亚洲国产影院av久久久久 | 五月天综合 | 久久99精品国产91久久来源 | 香蕉视频在线视频 | 婷婷综合五月天 | 欧美日韩xxxxx | 成人黄色小说视频 | 欧美怡红院| 午夜视频一区二区 | 99久久久国产免费 | 日本中文字幕网址 | 精品福利网 | 国产精品免费久久久久久久久久中文 | 一区二区三区日韩在线观看 | 一区二区三区中文字幕在线观看 | 91精品国产乱码 | 成人羞羞免费 | 欧美激情第八页 | 国产精品一区二区在线免费观看 | 在线亚洲成人 | 久草在线在线视频 | 日韩精品一区二区三区高清免费 | 国产成人三级一区二区在线观看一 | a黄色影院 | 麻豆视频在线观看 | 日韩在线视 | 日韩网站在线看片你懂的 | 日韩av中文在线观看 | 国产美女在线精品免费观看 | 五月天综合网 | 99久久99久久精品 | 亚洲黄色三级 | 日本精品久久久一区二区三区 | 2019中文最近的2019中文在线 | 伊人干综合| 在线看片中文字幕 | 天天操天天色天天 | 91成人网在线观看 | 国产69精品久久99不卡的观看体验 | 久久精品韩国 | 日日狠狠 | www.夜色.com | 欧美做受69 | 最近中文字幕在线中文高清版 | 国产毛片久久 | 亚洲不卡av一区二区三区 | 黄色最新网址 | www.一区二区三区 | 日本黄网站 | 中文在线a√在线 | 四虎影视av| a级片久久久 | 国产大陆亚洲精品国产 | 亚洲午夜精品久久久 | 国产麻豆剧传媒免费观看 | 国产高清在线一区 | 在线免费色视频 | 久久高清 | 欧美日韩三区二区 | 我爱av激情网 | 在线亚洲激情 | 欧美一区二区三区免费观看 | 国产精品资源在线 | 午夜视频导航 | 开心激情五月婷婷 | av三区在线 | 亚洲一区二区三区四区精品 | 91黄色影视 | 蜜臀av一区| 成人精品视频久久久久 | 日韩在线短视频 | 中文字幕在线观看不卡 | 黄色软件视频大全免费下载 | 久久精品999 | 91成年人视频 | 亚洲精品观看 | 韩日电影在线观看 | 狠狠88综合久久久久综合网 | 182午夜在线观看 | av观看免费在线 | 亚洲不卡av一区二区三区 | 色吊丝在线永久观看最新版本 | 91女子私密保健养生少妇 | 日韩精品在线视频 | 九九热在线观看视频 | 中文字幕一区二区三区久久 | 久久艹在线 | 97视频中文字幕 | 欧美日韩视频在线观看一区二区 | 久久精品一区八戒影视 | 五月婷婷中文 | 国产一级免费视频 | 亚洲成免费 | 婷婷av在线 | 少妇超碰在线 | 亚洲欧美精品在线 | 欧美性生活久久 | 日韩在线视频免费播放 | 国产精品久久中文字幕 | 麻豆成人精品 | 免费视频你懂的 | 一区二区不卡视频在线观看 | 欧美精品一区二区蜜臀亚洲 | 91色九色 | 91精品国产综合久久婷婷香蕉 | 久久成人高清视频 | 久久国产精品色婷婷 | 亚洲春色综合另类校园电影 | 黄色三级久久 | 日韩在线电影一区二区 | 久久久不卡影院 | 免费h在线观看 | 免费在线成人av | 精品国产成人av在线免 | 国产日韩在线播放 | 成人99免费视频 | 日韩欧美成人网 | 久久久久久久久黄色 | 中文字幕免费观看 | 久久国产精品久久w女人spa | 久久久久国产免费免费 | 国产成人一区二 | 91精品国产高清自在线观看 | 一区中文字幕电影 | 天天操夜夜做 | 欧美成年网站 | 免费日韩电影 | 欧美成人猛片 | 国产午夜精品久久久久久久久久 | 国产精品久久一区二区无卡 | 免费男女网站 | 国产香蕉97碰碰久久人人 | 亚洲 欧美日韩 国产 中文 | 久久av免费| 日韩精品不卡在线观看 | 国产资源中文字幕 | 91在线精品一区二区 | 999电影免费在线观看 | 探花视频免费在线观看 | 国产高清黄色 | 少妇搡bbbb搡bbb搡69 | 精品久久久久久久久久 | 九九免费观看全部免费视频 | 久久调教视频 | 国产91成人在在线播放 | 亚洲国产成人高清精品 | 国产99久久精品一区二区300 | 天天综合视频在线观看 | 国产一区在线免费观看视频 | 亚洲蜜桃在线 | 国产成人亚洲在线观看 | 国产午夜视频在线观看 | 久久人人97超碰国产公开结果 | 一区二区三区免费在线观看视频 | 在线黄色国产 | 日韩欧美精品在线观看 | 国产精品av一区二区 | 亚洲精品视频偷拍 | 一区二区三区在线免费播放 | 亚洲国产精品推荐 | 国产在线看一区 | 亚洲砖区区免费 | 九九视频在线观看视频6 | 在线日本看片免费人成视久网 | 欧美精品久久99 | 99在线精品观看 | 久草99| 999成人网 | 欧美91精品国产自产 | 成人资源在线播放 | 97精品国产97久久久久久免费 | 正在播放国产精品 | 亚洲春色综合另类校园电影 | 九九色视频 | 日韩欧美高清在线 | 天天天干天天射天天天操 | 免费av网址在线观看 | 综合网欧美 | 成人高清av在线 | 亚洲精品女人久久久 | 麻豆精品视频在线观看免费 | 亚洲国产网站 | 97香蕉久久国产在线观看 | 日韩精品中文字幕av | 黄色午夜| 亚洲 欧洲 国产 精品 | 久久久午夜剧场 | 久久久精品午夜 | 国内精品一区二区 | 免费成人在线观看视频 | 黄色官网在线观看 | 成年人免费在线观看 | 中文字幕第 | 成人网色 | 91视频在线 | 91高清视频 | 久久99久久99精品中文字幕 | 一区二区三区精品在线视频 | 青青草国产精品视频 | 国产免费观看高清完整版 | 久久综合久久综合这里只有精品 | 久久99精品国产一区二区三区 | 天天看天天干 | 东方av免费在线观看 | 欧美日韩后 | 特级黄色视频毛片 | www日| 久久久91精品国产一区二区精品 | 欧美性生交大片免网 | 亚洲免费国产视频 | 久久免费视频2 | 91精品一区二区三区久久久久久 | 水蜜桃亚洲一二三四在线 | 国产色资源 | 夜夜婷婷 | 国产91精品在线观看 | 国产自在线观看 | 狠狠网站 | 天天拍天天操 | 日韩三级在线 | 久草在线视频在线 | 在线中文字母电影观看 | 亚洲一级二级三级 | 18av在线视频 | 波多在线视频 | 国产精品久久片 | 欧美视频日韩 | a色视频 | 久久视频网址 | 美女国内精品自产拍在线播放 | 久久久人人人 | av中文字幕亚洲 | 国产h在线观看 | 国产91全国探花系列在线播放 | av国产网站| 一区二区三区不卡在线 | 美女网站视频久久 | 国产免费a | 中文在线字幕观看电影 | 久久久久久久久久久久久国产精品 | 天天操比 | 精品伦理一区二区三区 | 久久免费av电影 | 亚洲欧美日韩国产 | 顶级欧美色妇4khd | 在线精品视频免费播放 | 日韩免费视频在线观看 | 欧美一级性生活视频 | 国产精品资源 | 色天天综合久久久久综合片 | 免费黄色a级毛片 | 麻豆视频在线免费看 | a级片久久 | 国产精品 国产精品 | 色综合a| 日韩专区在线播放 | 91香蕉久久 | 人人草天天草 | 国产国语在线 | 五月天激情开心 | 高潮久久久久久 | 91丨九色丨国产女 | 亚洲91精品在线观看 | 国产护士在线 | 色综合天天做天天爱 | 国产一卡久久电影永久 | 久久久久久久久爱 | 欧美性做爰猛烈叫床潮 | www.91国产| 久久不卡日韩美女 | 亚洲国产成人高清精品 | 国产在线p | 99久国产 | 激情婷婷av | 国产精品久久久久久久久久久免费看 | 黄色av成人在线观看 | 久久精品播放 | 蜜桃av久久久亚洲精品 | 插综合网 | 国产精品久久久久久久久费观看 | 在线观看精品一区 | 美女久久久久 | 日韩在线不卡视频 | 国产精品第一 | 开心色婷婷 | 国产精品日韩久久久久 | 特级毛片在线 | 激情五月综合网 | 日韩免费在线观看视频 | 成人免费观看av | 五月天激情综合 | 亚洲好视频 | 久久久黄视频 | 久色 网 | 国产综合久久 | 色综合久久久久久中文网 | 久久精品综合 | 国产午夜精品一区二区三区 | 91香蕉视频在线下载 | 欧美性粗大hdvideo | 久久天天躁狠狠躁夜夜不卡公司 | 亚洲第一av在线 | 色av网站| 欧美色伊人 | 亚洲成人黄色在线 | 久久噜噜少妇网站 | 亚洲综合在线一区二区三区 | 成人网大片 | 日韩免费不卡视频 | 五月婷久久 | 一区二区三区免费在线观看视频 | 亚洲精品日韩在线观看 | 深夜免费福利视频 | 99超碰在线观看 | 97**国产露脸精品国产 | 91夜夜夜| 人人澡人人爱 | 亚洲片在线观看 | 国产免费视频一区二区裸体 | 91在线精品播放 | 99热99热 | 91亚洲精品久久久蜜桃网站 | 字幕网在线观看 | 精品在线观看一区二区三区 | 日韩欧美在线视频一区二区三区 | 在线观看日本高清mv视频 | 91福利试看 | 久久经典国产 | 婷婷av电影| 国产伦理一区二区 | 99在线热播精品免费 | 国产二区视频在线观看 | 亚洲激情在线播放 | 日日日日| 日韩一区二区三区在线看 | 69xxxx欧美| 国产亚洲高清视频 | www久久99 | 视频91在线 | 欧美日韩高清国产 | 国产手机精品视频 | 精品国产欧美 | 手机av电影在线 | 欧美极品少妇xxxx | 深爱五月激情网 | 深夜国产在线 | 色干干 | 国产成人精品一二三区 | 一区二区三区在线影院 | 欧美精品一区在线发布 | av免费成人 | www黄色软件 | 日韩网站在线 | 久久精品欧美一区二区三区麻豆 | 91成人久久| 国产永久网站 | av资源在线看| 激情婷婷亚洲 | 96精品视频 | 免费看wwwwwwwwwww的视频 久久久久久99精品 91中文字幕视频 | 国产精品一级视频 | 国产亚洲精品久久19p | 美女视频黄频大全免费 | 色婷婷成人 | 一区二区不卡 | 精品1区二区 | 91秒拍国产福利一区 | 国产专区在线视频 | 在线不卡a| 97国产情侣爱久久免费观看 | 日本久久免费电影 | 丁香婷婷激情五月 | 91精品成人 | 中文字幕乱码日本亚洲一区二区 | 综合激情网 | 超级碰碰碰碰 | 91污在线| 天天草av | 黄av免费在线观看 | 五月天堂网| 亚洲美女精品视频 | 亚洲精品午夜久久久久久久久久久 | 91麻豆免费看| 国产欧美精品一区二区三区四区 | 九九99视频 | 伊人春色电影网 | 在线免费av播放 | 成年人视频在线观看免费 | 国产色婷婷精品综合在线手机播放 | 成人国产网址 | 五月婷婷黄色网 | 97人人艹| 国产又粗又猛又黄视频 | 一级片视频在线 | 国产视频在 | 一区二区三区四区五区六区 | 99爱精品在线 | 97精品国产97久久久久久久久久久久 | 91精品电影 | 精品不卡视频 | 中文字幕制服丝袜av久久 | 日韩中文在线观看 | 久久成人精品电影 | 亚洲1级片 | 亚洲精品理论片 | 中文不卡视频在线 | 精品国产视频一区 | 超碰在线免费97 | 久久九九久久精品 | www.久久免费视频 | 久久久色| 日韩成人中文字幕 | 久久视频99 | 伊人五月天综合 | 五月开心激情网 | 91在线日本 | 综合久久久久久久久 | 色视频在线免费观看 | 中文字幕亚洲综合久久五月天色无吗'' | 欧美人体xx | 夜夜躁狠狠躁日日躁 | 久久手机在线视频 | 久久黄色小说视频 | 999久久国精品免费观看网站 | 亚洲电影院 | 91热爆视频| 成人免费在线观看av | 中文亚洲欧美日韩 | 波多野结衣精品视频 | 涩涩网站在线播放 | 精品人人爽 | 亚洲aⅴ乱码精品成人区 | 欧美在线久久 | www.888.av| 国产日本在线播放 | 久草视频在线看 | 麻豆精品在线 | 日韩在线一区二区免费 | 97看片吧| 国产精品久久久久久久久久久久午夜 | 久久久精品网站 | 亚洲精品18p | 欧美在线日韩在线 | 国产精品18久久久久白浆 | 久久视频免费观看 | 久久综合色天天久久综合图片 | 综合久久影院 | 欧美污污视频 | 天天操夜操| 日韩精品一区二区免费 | 亚洲91中文字幕无线码三区 | 久久99网站 | 久青草影院 | 999色视频 | 成人精品在线 | 亚洲最新av在线 | 99免费观看视频 | 欧美日韩一区二区在线观看 | 国产久草在线 | 欧美在线你懂的 | 最近中文字幕高清字幕在线视频 | 97福利视频 | 2019久久精品 | 超碰在线免费97 | 欧美日韩在线免费视频 | 天天玩夜夜操 | 欧美精品在线视频 | 人人草人人草 | 91看片黄色| 午夜性生活片 | 亚洲特级片 | 在线不卡视频 | 人人狠狠综合久久亚洲婷 | 毛片无卡免费无播放器 | 欧美日韩一区久久 | 亚洲精品综合一二三区在线观看 | 视频三区在线 | 日韩高清在线一区二区三区 | www.国产毛片 | 人人爽人人爽人人爽 | 夜夜看av | 日韩中文字幕电影 | 亚洲色图美腿丝袜 | 久久性生活片 | 日本中文字幕在线播放 | 麻豆影视在线观看 | 天天操天天操天天操 | 色资源中文字幕 | 五月天综合婷婷 | 久久99偷拍视频 | 欧美另类网站 | 欧美成人xxxxx | 国产成人一区二 | 日韩理论片在线观看 | 超级碰视频 | 在线视频 一区二区 | 国产精品久久久久久久久久久久午夜 | 国产成人久久av977小说 | 精品视频免费观看 | 免费在线观看一区二区三区 | 91精品国产一区二区在线观看 | 97成人在线| 国产亚洲精品免费 | 五月天婷亚洲天综合网精品偷 | 日精品在线观看 | 午夜av片 | 99免费在线观看视频 | 91在线免费观看网站 | 中文字幕一区二区三区在线播放 | 欧美日韩性视频 | 国产精品久久视频 | 日韩免费电影 | 日韩精品视频免费看 | 在线小视频你懂的 | 人人躁 | 国产精品白浆视频 | 天天av资源 | 日韩精品中文字幕av | 成人亚洲精品久久久久 | 国产精品久久久久久久久久久久午夜 | 亚洲精品理论 | 操操日| 国产精品免费久久久久 | 又色又爽的网站 | 黄色av电影 | 免费在线观看一区 | 日韩在线观看一区二区三区 | 人人草人人草 | 国产一区二区三区在线免费观看 | 玖玖综合网 | 久久免费大片 | 亚洲无吗视频在线 | 国产 在线 高清 精品 | 97免费在线观看 | 91女人18片女毛片60分钟 | 日韩免费在线观看视频 | 五月综合激情婷婷 | 免费久久精品视频 | 久久人人爽爽 | 国产精品久久99精品毛片三a | 麻豆视频免费在线播放 | 岛国一区在线 | 91网站免费观看 | 国产免费观看久久 | 91福利社在线观看 | 成人午夜黄色影院 | 国产视频中文字幕在线观看 | 日韩中文字幕在线 | 色狠狠综合天天综合综合 | 人人看人人| 九九视频免费在线观看 | 成人久久 | 97精品超碰一区二区三区 | 天天综合久久 | 又黄又网站 | 超级碰碰碰视频 | 亚洲视频免费在线观看 | 亚洲 欧美 国产 va在线影院 | 能在线看的av | 一区 二区电影免费在线观看 | 日韩一区二区三区免费电影 | 四虎影视av | 色资源网在线观看 | 天天操网址 | 久久欧美精品 | 国产精品黄色 | 日韩av不卡在线 | 久久久www| 亚洲 欧美 精品 | 国产录像在线观看 | 日韩视频一区二区三区 | 一级特黄aaa大片在线观看 | 亚洲电影黄色 | 亚洲精品高清在线 | 欧美日韩国产精品爽爽 | 日韩三级久久 | 欧美精品一区二区在线播放 | 久久国产精品影片 | 狠狠躁日日躁夜夜躁av | 人人插人人干 | 久久在线影院 | 国产小视频免费在线网址 | 欧美va天堂在线电影 | 天天操狠狠操 | 免费亚洲成人 | 日本一区二区三区视频在线播放 | 午夜色站 | 国产精品一区二区你懂的 | 亚洲国内精品 | 久久精品视频国产 | 亚洲精品影视在线观看 | 日韩电影精品 | 久久久久久综合 | 国语自产偷拍精品视频偷 | 一区二区三区免费在线观看视频 | 国产九色91| 国产精品免费在线播放 | 九九热国产| 97在线观看视频 | 成人久久18免费网站麻豆 | 免费的黄色av | 波多野结衣亚洲一区二区 | 日本中文字幕网址 | 天天操天天操天天操天天操天天操天天操 | 欧美极品xxx | 91亚洲精品在线 | 四虎永久国产精品 | 国产专区在线播放 | 4hu视频| 91免费视频国产 | 91毛片在线 | 人人插人人舔 | 国产精品久久久久久久免费观看 | 国产99久久精品一区二区永久免费 | 婷婷在线观看视频 | 99热在线观看 | 韩国在线视频一区 | av3级在线 | 国产精品久久久久久久久久久杏吧 | 国产成人三级在线 | 美女黄视频免费 | 91在线精品秘密一区二区 | 久久一区国产 | 亚洲乱码久久 | 日韩理论在线观看 | 麻豆视频在线观看免费 | 亚洲永久国产精品 | 97精品国产97久久久久久粉红 | 国产一区在线看 | 国产婷婷 | 久久96国产精品久久99软件 | 日本黄色大片儿 | 日韩免费观看一区二区三区 | 91久久一区二区 | 午夜久久影视 | 精品国内自产拍在线观看视频 | 99精品一区二区三区 | 久久久久久看片 | 日韩av电影免费观看 | 成人av电影在线观看 | 2020天天干夜夜爽 | 亚洲精品一区二区三区四区高清 | 伊人宗合网 | 国产一区在线观看免费 | 成人在线观看网址 | 国产黄色精品在线观看 | 久久97久久97精品免视看 | 超碰人人乐 | 福利在线看片 | 久久99精品热在线观看 | 亚洲精品裸体 | 色婷婷丁香 | 亚洲在线视频播放 | 可以免费观看的av片 | 成人一级免费电影 | 337p欧美 | 99免在线观看免费视频高清 | 国偷自产中文字幕亚洲手机在线 | 亚洲精品乱码久久久久久蜜桃不爽 | 天天操人人要 | 国产又粗又猛又色又黄视频 | 成人在线黄色 | 国产亚洲精品久久久久5区 成人h电影在线观看 | 探花国产在线 | 在线观看视频你懂 | 日日夜夜天天久久 | 在线免费观看的av网站 | 黄色三级在线看 | 一级α片免费看 | 日韩av中文在线观看 | 亚洲在线综合 | 青青河边草免费观看完整版高清 | 免费久久久| 91女子私密保健养生少妇 | 在线播放第一页 | 中文字幕一区二区在线播放 | 成年人在线观看 | 99精品国产视频 | 国产一区二区在线播放 | 九九亚洲视频 | 国产小视频免费观看 | 日韩国产精品一区 | 欧美在线一级片 | 黄色大片日本免费大片 | 亚洲欧洲xxxx | 日韩在线| 国产精品美女久久久久久久久久久 | 日韩精品一区二区在线 | 亚洲国产精品日韩 | 日本女人逼 | 久久精品国亚洲 | av激情五月 | 日韩一区二区免费播放 | 一区 二区 精品 | 91在线在线观看 | 亚洲国产精品电影 | 国模视频一区二区 | 91成人短视频在线观看 | 91看片在线免费观看 | 天堂av免费观看 | 99久久激情视频 | 日韩午夜高清 | 在线激情小视频 | 日韩精品中文字幕在线不卡尤物 | 久久国产精品99久久久久久进口 | 毛片随便看 | 蜜臀久久99精品久久久酒店新书 | 午夜视频一区二区 | 欧美天堂久久 | 一级特黄aaa大片在线观看 | 97超碰超碰久久福利超碰 | 色多多视频在线 | 天天射天天射天天 | a色视频 | 久久看毛片 | 久草视频99 | 91探花系列在线播放 | 久久久午夜剧场 | 亚洲电影黄色 | 色开心| 国产精品18久久久久久首页狼 | 96精品高清视频在线观看软件特色 | 日本久久影视 |