在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內(nèi)不再提示

i.MX6ULL驅(qū)動開發(fā)2—新字符設備開發(fā)模板

碼農(nóng)愛學習 ? 來源:碼農(nóng)愛學習 ? 作者:碼農(nóng)愛學習 ? 2022-03-17 09:11 ? 次閱讀

上篇文章介紹了字符設備的開發(fā)模板,但那是一種舊版本的驅(qū)動開發(fā)模式,設備驅(qū)動需要手動分配設備號再使用 register_chrdev進行注冊,加載成功以后還需要手動使用mknod命令創(chuàng)建設備節(jié)點,比較麻煩

目前Linux內(nèi)核推薦的新字符設備驅(qū)動API函數(shù),使得驅(qū)動的使用更加自動化,本篇就來一起研究下。

1 舊字符設備驅(qū)動的弊端

使用register_chrdev函數(shù)注冊字符設備,需要指定一個設備號,這就造成:

需要事先確定好哪些主設備號沒有使用

會將一個主設備號下的所有次設備號都使用掉,比如主設備號為200,那么 0~1048575(2^20-1)這個區(qū)間的次設備號就全部都被占用了

回顧上一篇的操作,先是加載驅(qū)動:

pYYBAGIyAAmAFyp0AAB4iFrzgsc420.png

加載完,還有手動使用mknod指令來手動創(chuàng)建該設備節(jié)點,并且指定驅(qū)動程序中寫死的設備號:

pYYBAGIyAA-AX6J5AAAy_IcL8LE995.png

本篇,就要使用一種新的字符驅(qū)動編寫方式,實現(xiàn)設備號的自動分配,省去mknod指令操作

2 新字符設備驅(qū)動原理

2.1 分配和釋放設備號

使用設備號的時候向Linux內(nèi)核申請,需要幾個就申請幾個,由Linux內(nèi)核分配設備可以使用的設備號。

使用如下函數(shù)來申請設備號(該函數(shù)在上篇提到過):

/*
* dev:保存申請到的設備號
* baseminor:次設備號起始地址,一般baseminor為0 (次設備號以baseminor為起始地址地址開始遞)
* count:要申請的設備號數(shù)量
* name:設備名字
*/
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name) 

如果給定了設備的主設備號和次設備號就使用如下所示函數(shù)來注冊設備號即可:

/*
* from:要申請的起始設備號
* count:要申請的設備號數(shù)量
* name:設備名字
*/
int register_chrdev_region(dev_t from, unsigned count, const char *name) 

注銷字符設備之后要釋放設備號,不管是通過alloc_chrdev_region函數(shù)的動態(tài)分配還是register_chrdev_region函數(shù)手動指定的設備號,統(tǒng)一使用(和上篇使用的一樣)的釋放函數(shù):

/*
* from:要釋放的設備號
* count:表示從from開始,要釋放的設備號數(shù)量
*/
void unregister_chrdev_region(dev_t from, unsigned count) 

新字符設備驅(qū)動下,設備號分配示例代碼如下:

int major;      /*主設備號*/ 
int minor;      /*次設備號*/ 
dev_t devid;    /*設備號*/ 

/*定義了主設備號*/
if (major)       
{
   devid = MKDEV(major, 0);    /*大部分驅(qū)動次設備號都選擇0*/ 
   register_chrdev_region(devid, 1, "test"); 
} 
/*沒有定義設備號*/ 
else 
{                         
   alloc_chrdev_region(&devid, 0, 1, "test");  /*申請設備號*/ 
   major = MAJOR(devid);       /*獲取分配號的主設備號*/ 
   minor = MINOR(devid);       /*獲取分配號的次設備號*/ 
}

2.2 字符設備注冊

2.2.1 cdev字符設備結構

在Linux中使用cdev結構體表示一個字符設備,其定義在include/linux/cdev.h文件中:

struct cdev { 
    struct kobject               kobj; 
    struct module                *owner; 
    const struct file_operations *ops;  /*文件操作函數(shù)集合*/
    struct list_head             list; 
    dev_t                        dev;   /*設備號*/              
    unsigned int                 count; 
};

2.2.2 cdev_init 函數(shù)

定義好cdev變量以后就要使用cdev_init函數(shù)對其進行初始化:

/*
* cdev:要初始化的cdev結構體變量
* fops:字符設備文件操作函數(shù)集合
*/
void cdev_init(struct cdev *cdev, const struct file_operations *fops) 

該函數(shù)的使用示例如下:

/*要初始化的cdev結構體*/
struct cdev testcdev; 

/* 設備操作函數(shù) */ 
static struct file_operations test_fops = { 
   .owner = THIS_MODULE, 
   /* 其他具體的初始項 */ 
}; 

testcdev.owner = THIS_MODULE;

/* 初始化cdev*/ 
cdev_init(&testcdev, &test_fops); 

2.2.3 cdev_add函數(shù)

該函數(shù)用于向Linux系統(tǒng)添加字符設備,即cdev結構體變量:

/*
* cdev:要初始化的cdev結構體變量
* dev:字符設備所使用的設備號
* count:要添加的設備數(shù)量
*/
int cdev_add(struct cdev *p, dev_t dev, unsigned count) 

2.2.4 cdev_del函數(shù)

卸載驅(qū)動的時候要使用cdev_del函數(shù)從Linux內(nèi)核中刪除字符設備:

/*
* p:要刪除的字符設備
*/
void cdev_del(struct cdev *p)

2.3 自動創(chuàng)建設備節(jié)點

上篇的Linux驅(qū)動實驗中,在使用modprobe加載驅(qū)動程序以后還需要使用“mknod”命令手動創(chuàng)建設備節(jié)點,比較麻煩,這里就來研究一下如何實現(xiàn)自動創(chuàng)建設備節(jié)點。

2.3.1 mdev機制

在Linux下通過udev來實現(xiàn)設備文件的自動創(chuàng)建與刪除。使用busybox構建根文件系統(tǒng)的時候,busybox會創(chuàng)建一個udev的簡化版本mdev

所以,在嵌入式開發(fā)中使用mdev來實現(xiàn)設備節(jié)點文件的自動創(chuàng)建與刪除。Linux系統(tǒng)中的熱插拔事件也由mdev 管理,在/etc/init.d/rcS 文件中如下語句:

echo /sbin/mdev > /proc/sys/kernel/hotplug 

2.3.2 創(chuàng)建和刪除類

自動創(chuàng)建設備節(jié)點的工作是在驅(qū)動程序的入口函數(shù)中完成的,一般在cdev_add函數(shù)后面添 加自動創(chuàng)建設備節(jié)點相關代碼。

首先要創(chuàng)建一個class類,其實是個結構體,定義在include/linux/device.h里面。class_create是類創(chuàng)建函數(shù)(宏定義):

#define class_create(owner, name) \ 
({ \ 
    static struct lock_class_key __key; \ 
    __class_create(owner, name, &__key); \ 
}) 

struct class *__class_create(struct module *owner, 
                             const char *name, 
                             struct lock_class_key *key) 

卸載驅(qū)動程序的時候需要使用函數(shù)為class_destroy刪除掉類

/*
* cls:要刪除的類
*/
void class_destroy(struct class *cls); 

2.3.3 創(chuàng)建設備

創(chuàng)建好類以后還不能實現(xiàn)自動創(chuàng)建設備節(jié)點,還需要在這個類下創(chuàng)建一個設備。使用device_create函數(shù)創(chuàng)建設備:

/*
* class:設備要創(chuàng)建哪個類下面
* parent:父設備, 一般為 NULL
* devt:設備號
* drvdata:設備可能會使用的一些數(shù)據(jù),一般為 NULL
* fmt:設備名字
*/
struct device *device_create(struct clas *class,  
                             struct device *parent,  
                             dev_t devt,  
                             void *drvdata,  
                             const char *fmt, ...) 

參數(shù)最后的...表示這在是一個可變參數(shù)的函數(shù)。

2.4 設置文件私有數(shù)據(jù)

每個硬件設備都有一些屬性, 比如主設備號(dev_t),類(class)、設備(device)、開關狀態(tài)(state)等等,在編寫驅(qū)動的時候你可以將這些屬性全部寫成變量的形式:

 dev_t         devid;     /*設備號*/ 
struct cdev   cdev;      /*cdev*/ 
struct class  *class;    /*類*/ 
struct device *device;   /*設備*/ 
int           major;     /*主設備號*/ 
int           minor;     /*次設備號*/ 

可以將所有屬性信封裝到結構體中, 并在編寫驅(qū)動open函數(shù)的時候?qū)⑵渥鳛樗接袛?shù)據(jù)添加到設備文件中:

/*設備結構體*/ 
struct test_dev{ 
    dev_t         devid;     /*設備號*/ 
    struct cdev   cdev;      /*cdev*/ 
    struct class  *class;    /*類*/ 
    struct device *device;   /*設備*/ 
    int           major;     /*主設備號*/ 
    int           minor;     /*次設備號*/ 
}; 

struct test_dev testdev; 

/*open函數(shù)*/ 
static int test_open(struct inode *inode, struct file *filp) 
{ 
    filp->private_data = &testdev; /*設置私有數(shù)據(jù)*/ 
    return 0; 
} 

3 驅(qū)動程序編寫

在上篇的基礎上進行修改,因為只是更換的驅(qū)動程序的編寫方式,與應用程序無關,因此只修改驅(qū)動程序即可。

3.1 添加一些定義

因為上篇文章的代碼中使用的是chrdevbase這個名稱,為了減少修改量,這里僅把結構體類型定義為帶有new標志的newchr_dev,變量名仍使用chrdevbase這個名稱。

#define CHRDEVBASE_CNT			1		/* 設備號個數(shù) */
#define CHRDEVBASE_NAME	 "chrdevbase"	/* 名字 */

/*newchr設備結構體 */
struct newchr_dev{
	dev_t         devid;	/* 設備號   */
	struct cdev   cdev;		/* cdev     */
	struct class  *class;	/* 類       */
	struct device *device;	/* 設備     */
	int           major;	/* 主設備號 */
	int           minor;	/* 次設備號 */
};

struct newchr_dev chrdevbase; /* 自定義字符設備 */

3.2 修改open函數(shù)

在上篇程序的基礎上增加了一條“設置私有數(shù)據(jù)”

static int chrdevbase_open(struct inode *inode, struct file *filp)
{
	printk("chrdevbase open!\r\n");
    filp->private_data = &chrdevbase; /* 設置私有數(shù)據(jù) */
	return 0;
}

3.3 修改init函數(shù)

這個修改比較大,因為要在init函數(shù)中使用設備號的自動分配

static int __init chrdevbase_init(void)
{
    /* 注冊字符設備驅(qū)動 */
	/* 1、創(chuàng)建設備號 */
	if (chrdevbase.major) /* 定義了設備號 */
    {
		chrdevbase.devid = MKDEV(chrdevbase.major, 0);
		register_chrdev_region(chrdevbase.devid, CHRDEVBASE_CNT, CHRDEVBASE_NAME);
	} 
    else /* 沒有定義設備號 */
    {
		alloc_chrdev_region(&chrdevbase.devid, 0, CHRDEVBASE_CNT, CHRDEVBASE_NAME);	/* 申請設備號 */
		chrdevbase.major = MAJOR(chrdevbase.devid);	/* 獲取分配號的主設備號 */
		chrdevbase.minor = MINOR(chrdevbase.devid);	/* 獲取分配號的次設備號 */
	}
	printk("chrdevbase major=%d,minor=%d\r\n",chrdevbase.major, chrdevbase.minor);	
	
	/* 2、初始化cdev */
	chrdevbase.cdev.owner = THIS_MODULE;
	cdev_init(&chrdevbase.cdev, &chrdevbase_fops);
	
	/* 3、添加一個cdev */
	cdev_add(&chrdevbase.cdev, chrdevbase.devid, CHRDEVBASE_CNT);

	/* 4、創(chuàng)建類 */
	chrdevbase.class = class_create(THIS_MODULE, CHRDEVBASE_NAME);
	if (IS_ERR(chrdevbase.class)) 
    {
		return PTR_ERR(chrdevbase.class);
	}

	/* 5、創(chuàng)建設備 */
	chrdevbase.device = device_create(chrdevbase.class, NULL, chrdevbase.devid, NULL, CHRDEVBASE_NAME);
	if (IS_ERR(chrdevbase.device)) 
    {
		return PTR_ERR(chrdevbase.device);
	}
    
	printk("chrdevbase init done!\r\n");
	return 0;
}

3.4 修改exit函數(shù)

因為init修改較大,對應的exit也要進行大的修改:

static void __exit chrdevbase_exit(void)
{
    /* 注銷字符設備驅(qū)動 */
	cdev_del(&chrdevbase.cdev);/*  刪除cdev */
	unregister_chrdev_region(chrdevbase.devid, CHRDEVBASE_CNT); /* 注銷設備號 */

	device_destroy(chrdevbase.class, chrdevbase.devid);
	class_destroy(chrdevbase.class);
    
    printk("chrdevbase exit done!\r\n");
}

至此,修改完畢,其它的與之前的一樣。

3.5 新舊驅(qū)動方式對比

通過一張圖來對比新舊兩種驅(qū)動編寫方式的區(qū)別

舊方式編寫驅(qū)動的流程

pYYBAGIyAdOAKvkdAACBY8npGD4752.png

新方式編寫驅(qū)動的流程

pYYBAGIyAdiAMiETAAEM8HQykVI076.png

可以看出主要區(qū)別在驅(qū)動的加載和卸載。

4 編譯驅(qū)動

和上次編譯驅(qū)動的方式一樣,使用makefile,因為驅(qū)動的c文件名由chrdevbase.c改為了newchrdevbase.c,因此makefile文件中也要把名字改掉。

編譯完之后,將編譯出的ko文件先復制到ubuntu虛擬機的tftpboot目錄中,為后面的測序做準備。

pYYBAGIyAeCARtBwAACum9V3bvM294.png

復制后,看一下tftpboot目錄:

poYBAGIyAeWAcC6OAABRgY3MQbY132.png

5 程序測試

5.1 文件發(fā)送到板子

和上篇一樣,使用tftp傳輸,將ubuntu虛擬機編譯出的ko文件發(fā)送到linux板子中

再來看下tftp傳輸?shù)挠布h(huán)境示意圖:

poYBAGIx__mAJAMxAAFqlflsgR8688.png

然后是傳輸指令以及傳輸結果,可以看到newchrdevbase.ko已經(jīng)從ubuntu虛擬機的tftpboot目錄傳輸?shù)搅薼inux板子的/lib/modules/4.1.15目錄中了。

pYYBAGIyAfuAE3rpAACDeMdklK0816.png

5.2 測試

輸入如下兩條指令加載 newchrdevbase.ko 驅(qū)動模塊:

depmod //第一次加載驅(qū)動的時候需要運行此命令 modprobe newchrdevbase.ko //加載驅(qū)動

驅(qū)動加載成功后,可以看到自動申請到的主設備號和次設備號,如下圖,主設備號為249。

再輸入ls /dev/chrdevbase -l指令驗證/dev/chrdevbase 這個設備節(jié)點文件是否存在,如下圖,可以看到設備存在,注意和上篇舊驅(qū)動方式操作上的不同之處,舊的驅(qū)動方式需要額外使用mknod指令來手動創(chuàng)建該設備節(jié)點

poYBAGIyAgGAbiVoAABRaJSZ9J0244.png

驅(qū)動已經(jīng)加載成功,再來測試APP程序,理論上和上篇的效果一樣,實測也是:

pYYBAGIyAgaAb-B4AAB-1c076Y0255.png

OK,測試完畢,測試完使用rmmod指令卸載驅(qū)動。

6 總結

此篇文章針對上篇文章使用舊字符驅(qū)動編寫方式存在的不足,介紹了一種新的字符驅(qū)動編寫方式,對比兩種方式編寫的主要區(qū)別,在上篇驅(qū)動代碼的基礎上進行修改,并測試通過,和上篇實現(xiàn)一樣的效果,但驅(qū)動的加載更加方便,不再需要人為指定設備號。

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 設備
    +關注

    關注

    2

    文章

    4509

    瀏覽量

    70642
  • 模板
    +關注

    關注

    0

    文章

    108

    瀏覽量

    20566
  • 函數(shù)
    +關注

    關注

    3

    文章

    4331

    瀏覽量

    62622
收藏 人收藏

    評論

    相關推薦

    i.MX6ULL嵌入式Linux開發(fā)1-uboot移植初探

    本系列教程以i.MX6ULL處理器的ARM開發(fā)板為實驗基礎,學習記錄嵌入式Linux開發(fā)的各種知識與經(jīng)驗,主要內(nèi)容包括嵌入式Linux移植,嵌入式Linux驅(qū)動
    的頭像 發(fā)表于 03-07 08:57 ?3888次閱讀
    <b class='flag-5'>i.MX6ULL</b>嵌入式Linux<b class='flag-5'>開發(fā)</b>1-uboot移植初探

    i.MX6ULL驅(qū)動開發(fā)1—字符設備開發(fā)模板

    本篇介紹了嵌入式Linux驅(qū)動開發(fā)中的基礎驅(qū)動——字符驅(qū)動開發(fā)的基本模式,使用了一個虛擬的
    的頭像 發(fā)表于 03-17 09:13 ?3335次閱讀
    <b class='flag-5'>i.MX6ULL</b><b class='flag-5'>驅(qū)動</b><b class='flag-5'>開發(fā)</b>1—<b class='flag-5'>字符</b><b class='flag-5'>設備</b><b class='flag-5'>開發(fā)</b><b class='flag-5'>模板</b>

    使用i.MX6ULL開發(fā)板進行Linux根文件系統(tǒng)的完善

    上一篇推文講了怎么移植根文件系統(tǒng),并在i.MX6ULL開發(fā)板中運行起來,但是會出現(xiàn)一些提示,現(xiàn)在來進行根文件的完善。
    發(fā)表于 10-17 11:13 ?801次閱讀

    移植NXP官方linux 5.4內(nèi)核到i.MX6ULL開發(fā)

    本文描述移植NXP官方 linux 5.4 內(nèi)核到i.MX6ULL開發(fā)板。
    發(fā)表于 12-19 11:10 ?2050次閱讀

    I.MX6ULL終結者開發(fā)板裸機仿真jlink調(diào)試

    I.MX6ULL‘終結者’開發(fā)板預留了JTAG仿真接口,并給出了開發(fā)文檔,可以實現(xiàn)在JLINK仿真器條件下的單步跟蹤、斷點調(diào)試等功能,使得開發(fā)研究i
    發(fā)表于 07-07 10:56

    i.MX6ULL開發(fā)板硬件資源

    迅為i.MX6ULL 終結者開發(fā)板硬件資源非常豐富,幾乎將 i.MX6ULL 芯片的所有資源都擴展引出到底板上了,底板提供了豐富的外設接口,開發(fā)板的尺寸是 190mm*125mm,充分
    發(fā)表于 12-29 06:18

    初識 i.MX6ULL 寄存器

    裸機開發(fā)_L1_匯編LED實驗0. 本節(jié)目標1. 硬件層電路2. 初識 i.MX6ULL 寄存器2.1 i.MX6ULL 時鐘控制寄存器2.2 i.
    發(fā)表于 12-20 07:13

    I.MX6ULL無法枚舉USB2514是為什么?

    你好目前,I.MX6ULL開發(fā)存在一些問題。其中之一是OTG USB2無法正常掛載USB2514,無法正確枚舉下游設備,只顯示設備id。us
    發(fā)表于 04-03 06:55

    飛凌i.MX6ULL開發(fā)板的評測,再次進階擁有更高的性價比

    處理器MCIMX6Y2開發(fā)設計,采用先進的ARMCortex-A7內(nèi)核,運行速度高達800MHz。i.MX6ULL應用處理器包括一個集成的電源管理模塊,降低了外接電源的復雜性,并簡化了上電時序。
    發(fā)表于 10-27 11:55 ?1488次閱讀
    飛凌<b class='flag-5'>i.MX6ULL</b><b class='flag-5'>開發(fā)</b>板的評測,再次進階擁有更高的性價比

    i.MX6ULL驅(qū)動開發(fā)4——點亮LED(寄存器版)

    本篇主要介紹了如何通過操作寄存器來點亮i.MX6ULL開發(fā)板上的led,通過編寫LED對應的驅(qū)動程序和應用程序,實現(xiàn)程序設計的分層。
    的頭像 發(fā)表于 05-21 21:26 ?2981次閱讀
    【<b class='flag-5'>i.MX6ULL</b>】<b class='flag-5'>驅(qū)動</b><b class='flag-5'>開發(fā)</b>4——點亮LED(寄存器版)

    i.MX6ULL|字符設備驅(qū)動開發(fā)實踐

    字符設備驅(qū)動開發(fā)的基本步驟可以看上一篇,本節(jié)就以 chrdevbase 這個虛擬設備為例,完整的編寫一個
    的頭像 發(fā)表于 10-31 11:27 ?675次閱讀

    Linux新字符設備驅(qū)動開發(fā)方式

    Linux字符設備驅(qū)動開發(fā)模板中介紹了舊版本的驅(qū)動開發(fā)
    的頭像 發(fā)表于 04-14 12:02 ?874次閱讀
    Linux<b class='flag-5'>新字符</b><b class='flag-5'>設備</b><b class='flag-5'>驅(qū)動</b><b class='flag-5'>開發(fā)</b>方式

    【北京迅為】i.MX6ULL開發(fā)板移植 Debian 文件系統(tǒng)

    【北京迅為】i.MX6ULL開發(fā)板移植 Debian 文件系統(tǒng)
    的頭像 發(fā)表于 02-10 15:34 ?1151次閱讀
    【北京迅為】<b class='flag-5'>i.MX6ULL</b><b class='flag-5'>開發(fā)</b>板移植 Debian 文件系統(tǒng)

    基于i.MX6ULL的掉電檢測設計與軟件測試

    基于i.MX6ULL的掉電檢測設計與軟件測試基于i.MX6ULL平臺設計實現(xiàn)掉電檢測功能,首先選擇一路IO,利用IO電平變化觸發(fā)中斷,在編寫驅(qū)動時捕獲該路GPIO的中斷,然后在中斷響應函數(shù)中發(fā)
    的頭像 發(fā)表于 11-09 10:40 ?855次閱讀
    基于<b class='flag-5'>i.MX6ULL</b>的掉電檢測設計與軟件測試

    【迅為電子】i.MX6UL和i.MX6ULL芯片區(qū)別與開發(fā)板對比

    【迅為電子】i.MX6UL和i.MX6ULL芯片區(qū)別與開發(fā)板對比
    的頭像 發(fā)表于 11-28 14:31 ?388次閱讀
    【迅為電子】<b class='flag-5'>i.MX6</b>UL和<b class='flag-5'>i.MX6ULL</b>芯片區(qū)別與<b class='flag-5'>開發(fā)</b>板對比
    主站蜘蛛池模板: 夜夜嘿视频免费看| 女人69xxx| 日日草夜夜草| 欧美一级高清黄图片| 美女被免费网站视频在线| 国产精品久久久福利| 欧美人与zoxxxx另类| 亚洲男人的天堂成人| 13日本xxxxxxxxx18| 男女交性视频免费播放视频| 一级aaa毛片| 三级特黄视频| 国内自拍网红在综合图区| 4hc44四虎www亚洲| 日本极度另类网站| 57pao成人永久免费视频 | 婷婷丁香在线观看| 日本午夜视频| 国产视频每日更新| 五月天婷婷网亚洲综合在线| 久久精品免费观看久久| 5566在线观看| 欧美日a| 波多野结衣在线视频免费观看| 日韩美女影院| 9久久99久久久精品齐齐综合色圆 9久热久re爱免费精品视频 | 日本三区四区免费高清不卡| 一级全免费视频播放| 国产香港三级理论在线| 西西人体大胆高清啪啪欧洲| 91九色麻豆| 国产产一区二区三区久久毛片国语| 人人干网站| 亚洲伊人成综合成人网| 成人在线视频网址| 国产视频分类| 国产精品一级香蕉一区| 欧美色吧视频在线观看| 午夜影剧| 一区二区高清在线| 激情综合五月|