日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux 字符设备驱动及一些简单的Linux知识

發(fā)布時(shí)間:2024/8/1 linux 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux 字符设备驱动及一些简单的Linux知识 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、linux系統(tǒng)將設(shè)備分為3類:字符設(shè)備、塊設(shè)備、網(wǎng)絡(luò)設(shè)備

1、字符設(shè)備:是指只能一個(gè)字節(jié)一個(gè)字節(jié)讀寫的設(shè)備,不能隨機(jī)讀取設(shè)備內(nèi)存中的某一數(shù)據(jù),讀取數(shù)據(jù)需要按照先后數(shù)據(jù)。字符設(shè)備是面向流的設(shè)備,常見的字符設(shè)備有鼠標(biāo)、鍵盤、串口、控制臺和LED設(shè)備等。
2、塊設(shè)備:是指可以從設(shè)備的任意位置讀取一定長度數(shù)據(jù)的設(shè)備。塊設(shè)備包括硬盤、磁盤、U盤和SD卡等。

每一個(gè)字符設(shè)備或塊設(shè)備都在/dev目錄下對應(yīng)一個(gè)設(shè)備文件。linux用戶程序通過設(shè)備文件(或稱設(shè)備節(jié)點(diǎn))來使用驅(qū)動程序操作字符設(shè)備和塊設(shè)備。

本文主要是介紹字符設(shè)備驅(qū)動程序,從驅(qū)動程序開始,涉及文件操作,一共四個(gè)函數(shù):包括文件的打開,讀,寫,刪除。還有文件的注冊和注銷。

廢話不多說,上源代碼,以代碼為例開始解釋:

1.mydriver.c:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/uaccess.h>

#if CONFIG_MODVERSIONS == 1
#define MODVERSIONS
#include <linux/version.h>
#endif

#define DEVICE_NUM 0 //隨機(jī)產(chǎn)生一個(gè)設(shè)備號

static int device_num = 0; //用來保存創(chuàng)建成功后的設(shè)備號
static char buffer[1024] = "mydriver"; //數(shù)據(jù)緩沖區(qū)
static int open_nr = 0; //打開設(shè)備的進(jìn)程數(shù),用于內(nèi)核的互斥

//函數(shù)聲明
// inode;linux下文件的管理號。
//file:linux一切皆文件。文件結(jié)構(gòu)體代表一個(gè)打開的文件,系統(tǒng)中的每個(gè)打開的文件在內(nèi)核空間都有一個(gè)關(guān)聯(lián)的 struct file。它由內(nèi)核在打開文件時(shí)創(chuàng)建,并傳遞給在文件上進(jìn)行操作的任何函數(shù)。在文件的所有實(shí)例都關(guān)閉后,內(nèi)核釋放這個(gè)數(shù)據(jù)結(jié)構(gòu)
static int mydriver_open(struct inode *inode, struct file *filp);
static int mydriver_release(struct inode *inode, struct file* filp);
static ssize_t mydriver_read(struct file *file, char __user *buf, size_t count, loff_t *f_pos); //loff-t:long long 型
static ssize_t mydriver_write(struct file *file, const char __user *buf, size_t count, loff_t *f_pos); //__user表明參數(shù)是一個(gè)用戶空間的指針,不能在kernel代碼中直接訪問。
//size_t:一個(gè)基本的無符號整數(shù)的C / C + +類型
//填充file_operations結(jié)構(gòu)相關(guān)入口
static struct file_operations mydriver_fops = {
.read = mydriver_read,
.write = mydriver_write,
.open = mydriver_open,
.release = mydriver_release,
};

//打開函數(shù)
static int mydriver_open(struct inode *inode, struct file *filp)
{
printk("\nMain device is %d, and the slave device is %d\n", MAJOR(inode->i_rdev), MINOR(inode->i_rdev)); //把主從設(shè)備號傳入
if (open_nr == 0) {
open_nr++;
try_module_get(THIS_MODULE); //嘗試打開模塊
return 0;
}
else {
printk(KERN_ALERT "Another process open the char device.\n");//進(jìn)程掛起
return -1;
}
}

//讀函數(shù)
static ssize_t mydriver_read(struct file *file, char __user *buf, size_t count, loff_t *f_pos)
{
//if (buf == NULL) return 0;
if (copy_to_user(buf, buffer, sizeof(buffer))) //讀緩沖 ,第一個(gè)參數(shù)是to:用戶空間的地址,第二個(gè)參數(shù)是from,內(nèi)核空間的地址,第三個(gè)參數(shù)是要從內(nèi)核空間拷貝的字節(jié)數(shù)
{
return -1;
}
return sizeof(buffer);
}

//寫函數(shù),將用戶的輸入字符串寫入
static ssize_t mydriver_write(struct file *file, const char __user *buf, size_t count, loff_t *f_pos)
{
//if (buf == NULL) return 0;
if (copy_from_user(buffer, buf, sizeof(buffer))) //寫緩沖
{
return -1;
}
return sizeof(buffer);
}

//釋放設(shè)備函數(shù)
static int mydriver_release(struct inode *inode, struct file* filp)
{
open_nr--; //進(jìn)程數(shù)減1
printk("The device is released!\n");
module_put(THIS_MODULE); //釋放模塊
return 0;
}

//注冊設(shè)備函數(shù)
static int __init mydriver_init(void)
{
int result;

printk(KERN_ALERT "Begin to init Char Device!"); //注冊設(shè)備
//向系統(tǒng)的字符登記表登記一個(gè)字符設(shè)備
result = register_chrdev(DEVICE_NUM, "mydriver", &mydriver_fops); //第一個(gè)參數(shù)等于0,則表示采用系統(tǒng)動態(tài)分配的主設(shè)備號;不為0,則表示靜態(tài)注冊。 第二個(gè)參數(shù)命名, 第三個(gè)參數(shù)為其地址

if (result < 0) {
printk(KERN_WARNING "mydriver: register failure\n");
return -1;
}
else {
printk("mydriver: register success!\n");
device_num = result;
return 0;
}
}

//注銷設(shè)備函數(shù)
static void __exit mydriver_exit(void)
{
printk(KERN_ALERT "Unloading...\n");
unregister_chrdev(device_num, "mydriver"); //注銷設(shè)備
printk("unregister success!\n");
}

//模塊宏定義
module_init(mydriver_init); //模塊加載函數(shù)
module_exit(mydriver_exit); //設(shè)備卸載函數(shù)

MODULE_LICENSE("GPL"); // "GPL" 是指明了 這是GNU General Public License的任意版本

因?yàn)樽⑨寖?nèi)容有限,在后面貼上一些對源代碼的注釋:

inode;linux下文件的管理號。(靜態(tài)的)
file:linux一切皆文件。文件結(jié)構(gòu)體代表一個(gè)打開的文件,系統(tǒng)中的每個(gè)打開的文件在內(nèi)核空間都有一個(gè)關(guān)聯(lián)的 struct file。它由內(nèi)核在打開文件時(shí)創(chuàng)建,并傳遞給在文件上進(jìn)行操作的任何函數(shù)。在文件的所有實(shí)例都關(guān)閉后,內(nèi)核釋放這個(gè)數(shù)據(jù)結(jié)構(gòu)。(動態(tài)的)
__user:The use of char __user *buf is typically found in the linux kernel...denoting that this address is in the user space. For example when writing to disk the kernel copies the contents of *buf into a kernel space buffer before writing it out to disk. Similarly when a process requests a read operation...the device driver at the behest of the kernel reads the desired disk blocks into a kernel space buffer...and then copies them into the user space buffer pointed to by *buf.
__user表明參數(shù)是一個(gè)用戶空間的指針,不能在kernel代碼中直接訪問。也方便其它工具對代碼進(jìn)行檢查。
file-operations:
用來存儲驅(qū)動內(nèi)核模塊提供的 設(shè)備進(jìn)行各種操作的函數(shù)的指針。該結(jié)構(gòu)體的每個(gè)域都對應(yīng)著驅(qū)動內(nèi)核模塊用來處理某個(gè)被請求的事務(wù)的函數(shù)的地址。
MAJOR(inode->i_rdev), MINOR(inode->i_rdev):
如果inode代表一個(gè)設(shè)備,則i_rdev的值為設(shè)備號。為了代碼更好地可移植性,獲取inode的major和minor號應(yīng)該使用imajor和iminor函數(shù)
#include <linux/module.h> :
寫內(nèi)核驅(qū)動的時(shí)候 必須加載這個(gè)頭文件,作用是動態(tài)的將模塊加載到內(nèi)核中去
#include <linux/version.h> :
當(dāng)設(shè)備驅(qū)動需要同時(shí)支持不同版本內(nèi)核時(shí),在編譯階段,內(nèi)核模塊需要知道當(dāng)前使用的內(nèi)核源碼的版本,從而使用相應(yīng)的內(nèi)核 API
try_module_get(&module), module_put(&module):
靈活的模塊計(jì)數(shù)管理接口
#include <linux/kernel.h> :
kernel.h中包含了內(nèi)核打印函數(shù) printk函數(shù) 等
#include <linux/uaccess.h>:
包含了copy_to_user、copy_from_user等內(nèi)核訪問用戶進(jìn)程內(nèi)存地址的函數(shù)定義。(copy_to_user()完成用戶空間到內(nèi)核空間的復(fù)制,函數(shù)copy_from_user()完成內(nèi)核空間到用戶空間的復(fù)制)
copy_to_user(buf, buffer, sizeof(buffer)//
#include <linux/fs.h> :
包含了文件操作相關(guān)struct的定義,例如大名鼎鼎的struct file_operations

#include <linux/init.h> :
內(nèi)核模塊的初始化和注銷函數(shù)就在這個(gè)文件中

2. makefile:

# if KERNELRELEASE is defined, we've been invoked from the

# kernel build system and can use its language.

ifeq ($(KERNELRELEASE),)

????# Assume the source tree is where the running kernel was built

????# You should set KERNELDIR in the environment if it's elsewhere

KERNELDIR ?= ?/lib/modules/$(shell uname -r)/build

????# The current directory is passed to sub-makes as argument

PWD := $(shell pwd)

modules:

$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

modules_install:

$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install

clean:

rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions

.PHONY: modules modules_install clean

else

????# called from kernel build system: just declare what our modules are

obj-m := mydriver.o

endif

3.

  • test.c
  • #include <sys/types.h>

    #include <sys/stat.h>

    #include <stdlib.h>

    #include <string.h>

    #include <stdio.h>

    #include <fcntl.h>

    #include <unistd.h>

    #define MAX_SIZE 1024

    ?

    int main(void)

    {

    int fd;

    char buf[MAX_SIZE];

    char get[MAX_SIZE];

    char devName[20], dir[49] = "/dev/";

    system("ls /dev/");

    printf("Please input the device's name you wanna to use :");

    gets(devName);

    strcat(dir, devName);

    fd = open(dir, O_RDWR | O_NONBLOCK);

    if (fd != -1)

    {

    read(fd, buf, sizeof(buf));

    printf("The device was inited with a string : %s\n", buf);

    ?// 測試寫

    printf("Please input a string ?:\n");

    gets(get);

    write(fd, get, sizeof(get));

    //測試讀

    read(fd, buf, sizeof(buf));

    system("dmesg");

    printf("\nThe string in the device now is : %s\n", buf);

    close(fd);

    return 0;

    }

    else

    {

    printf("Device open failed\n");

    return -1;

    }

    }

    以上源代碼均可直接使用,以下是本人對基礎(chǔ)知識的一些拙見,如果您有什么高見請務(wù)必指出,多謝各位大佬!

    一.什么是Makefile
    (1)KERNELRELEASE在linux內(nèi)核源代碼中的頂層makefile中有定義
    (2)shell pwd會取得當(dāng)前工作路徑
    (3)shell uname -r會取得當(dāng)前內(nèi)核的版本號
    (4)由于make 后面沒有目標(biāo),所以make會在Makefile中的第一個(gè)不是以.開頭的目標(biāo)作為默認(rèn)的目標(biāo)執(zhí)行。
    于是modules成為make的目標(biāo)
    (5)首先-C表示到存放內(nèi)核的目錄(KERNELDIR)執(zhí)行其makefile,其中保存有內(nèi)核的頂層makefile,M=選項(xiàng)的作用是,
    當(dāng)用戶需要以某個(gè)內(nèi)核為基礎(chǔ)編譯一個(gè)外部模塊的話,需要在make modules 命令中加入M=$(PWD),
    程序會自動到你所指定的dir目錄中查找模塊源碼,將其編譯,生成KO文件。
    (6)obj-m是表示該文件要作為模塊編譯,只是編譯得到globalmem.o而不鏈接進(jìn)內(nèi)核
    (7)每個(gè)Makefile中都應(yīng)該寫一個(gè)清空目標(biāo)文件(.o和執(zhí)行文件)的規(guī)則,這不僅便于重編譯
    ,也很利于保持文件的清潔——clean
    (8)make modules_install是把編譯好的模塊拷貝到系統(tǒng)目錄下(一般是/lib/modules/),
    拷貝到系統(tǒng)目錄下的目的是方便使用,加載驅(qū)動就使用modprobe globalmem命令,該命令從系統(tǒng)目錄下查找名為globalmem的模塊

    二.什么是模塊化編程?為什么要模塊化編程?
    (1)內(nèi)核模塊是一些可以讓操作系統(tǒng)內(nèi)核在需要時(shí)載入和執(zhí)行的代碼,同時(shí)在不需要的時(shí)候可以卸載。
    這是一個(gè)好的功能,擴(kuò)展了操作系統(tǒng)的內(nèi)核功能,卻不需要重新啟動系統(tǒng),是一種動態(tài)加載的技術(shù)。
    (2)內(nèi)核模塊代碼運(yùn)行在內(nèi)核空間,而應(yīng)用程序在用戶空間。應(yīng)用程序的運(yùn)行會形成新的進(jìn)程,而內(nèi)核模塊一般不會
    。每當(dāng)應(yīng)用程序執(zhí)行系統(tǒng)調(diào)用時(shí),Linux執(zhí)行模式從用戶空間切換到內(nèi)核空間。
    答:Linux 內(nèi)核的整體結(jié)構(gòu)非常龐大,其包含的組件也非常多。我們怎樣把需要的部分都包含在內(nèi)核中呢?
    一種方法是把所有需要的功能都編譯到 Linux 內(nèi)核。
    這會導(dǎo)致兩個(gè)問題,一是生成的內(nèi)核會很大,二是如果我們要在現(xiàn)有的內(nèi)核中新增或刪除功能,將不得不重新編譯內(nèi)核。
    有沒有一種機(jī)制使得編譯出的內(nèi)核本身并不需要包含所有功能,而在這些功能需要被使用的時(shí)候,
    其對應(yīng)的代碼可被動態(tài)地加載到內(nèi)核中呢?
    Linux 提供了這樣的一種機(jī)制,這種機(jī)制被稱為模塊(Module),可以實(shí)現(xiàn)以上效果。模塊具有以下特點(diǎn)。
    1.模塊本身不被編譯入內(nèi)核映像,從而控制了內(nèi)核的大小。
    2.模塊一旦被加載,它就和內(nèi)核中的其他部分完全一樣。

    三.如何理解設(shè)備號,什么是主設(shè)備號,什么是次設(shè)備號?

    一個(gè)字符設(shè)備或塊設(shè)備都有一個(gè)主設(shè)備號和一個(gè)次設(shè)備號。主設(shè)備號用來標(biāo)識與設(shè)備文件相連的驅(qū)動程序,用來反映設(shè)備類型。次設(shè)備號被驅(qū)動程序用來辨別操作的是哪個(gè)設(shè)備,用來區(qū)分同類型的設(shè)備。
      linux內(nèi)核中,設(shè)備號用dev_t來描述,2.6.28中定義如下:
      typedef u_long dev_t;
      在32位機(jī)中是4個(gè)字節(jié),高12位表示主設(shè)備號,低12位表示次設(shè)備號。

    四.整個(gè)驅(qū)動從編譯到用測試程序進(jìn)行測試的全過程,需要掌握相關(guān)的各種操作命令
    1.在globalmen這個(gè)目錄里面,先make一下,把globalmem.c編譯成模塊globalmem.ko
    2.lsmod查看這個(gè)Linux里面有沒有g(shù)lobalmem模塊
    3.insmod globalmem.ko 加載globalmem模塊
    4.lsmod查看是否加載成功
    5.cat /proc/devices查看加載驅(qū)動程序時(shí)生成的設(shè)備 (proc目錄是一個(gè)虛擬文件系統(tǒng),
    可以為linux用戶空間和內(nèi)核空間提供交互,它只存在于內(nèi)存中,而不占實(shí)際的flash或硬盤空間)
    6.mknod /dev/globalmem c 200 0 給globalmem設(shè)備創(chuàng)建設(shè)備節(jié)點(diǎn),主設(shè)備號為200,次設(shè)備號為0
    7.cd /dev 進(jìn)入dev目錄
    8.ls 查看dev目錄下是否有g(shù)lobalmem設(shè)備
    9.echo '老師你真的很帥!'>/dev/globalmem 向globalmem設(shè)備寫入一句話
    10.cat /dev/globalmem 查看globalmem設(shè)備里面的內(nèi)容
    11.gcc -o test.c test 用gcc來編譯測試程序
    12../test 運(yùn)行測試程序

    五.三個(gè)重要的數(shù)據(jù)結(jié)構(gòu)(結(jié)構(gòu)體):file_operations、innode、file,尤其是file_operations
    file文件結(jié)構(gòu):
    struct file,定義于<linux/fs.h>.文件結(jié)構(gòu)代表一個(gè)打開的文件.(它不特定給設(shè)備驅(qū)動;
    系統(tǒng)中每個(gè)打開的文件有一個(gè)關(guān)聯(lián)的 struct file 在內(nèi)核空間).
    它由內(nèi)核在 open 時(shí)創(chuàng)建,并傳遞給在文件上操作的任何函數(shù), 直到最后的關(guān)閉.
    在文件的所有實(shí)例都關(guān)閉后, 內(nèi)核釋放這個(gè)數(shù)據(jù)結(jié)構(gòu)
    .struct file的指針常常稱為filp("file pointer"),源代碼里面沒有這個(gè)結(jié)構(gòu)體,
    但是在函數(shù)里面會經(jīng)常用到它,例如
    int globalmem_open(struct inode *inode, struct file *filp);
    int globalmem_release(struct inode *inode, struct file *filp);
    static ssize_t globalmem_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos);
    static ssize_t globalmem_write(struct file *filp, const char __user *buf, size_t size, loff_t *ppos);
    static loff_t globalmem_llseek(struct file *filp, loff_t offset, int orig);
    static long globalmem_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);

    inode結(jié)構(gòu):
    inode 結(jié)構(gòu)由內(nèi)核在內(nèi)部用來表示文件. 因此, 它和代表打開文件描述符的文件結(jié)構(gòu)是不同的.
    可能有代表單個(gè)文件的多個(gè)打開描述符的許多文件結(jié)構(gòu), 但是它們都指向一個(gè)單個(gè) inode 結(jié)構(gòu).
    inode 結(jié)構(gòu)包含大量關(guān)于文件的信息. 作為一個(gè)通用的規(guī)則, 這個(gè)結(jié)構(gòu)只有 2 個(gè)成員對于編寫驅(qū)動代碼有用:
    dev_ti_rdev;
    對于代表設(shè)備文件的節(jié)點(diǎn),這個(gè)成員包含實(shí)際的設(shè)備編號.
    structcdev *i_cdev;
    structcdev 是內(nèi)核的內(nèi)部結(jié)構(gòu), 代表字符設(shè)備; 這個(gè)成員包含一個(gè)指針, 指向這個(gè)結(jié)構(gòu), 當(dāng)節(jié)點(diǎn)指的是一個(gè)字符設(shè)備文件時(shí).

    file_operations結(jié)構(gòu):
    結(jié)構(gòu)體file_operations在頭文件 linux/fs.h中定義,用來存儲驅(qū)動內(nèi)核模塊提供的對設(shè)備進(jìn)行各種操作的函數(shù)的指針。
    該結(jié)構(gòu)體的每個(gè)域都對應(yīng)著驅(qū)動內(nèi)核模塊用來處理某個(gè)被請求的 事務(wù)的函數(shù)的地址。
    如下為C99語法的使用該結(jié)構(gòu)體的方法,并且沒有顯示聲明的結(jié)構(gòu)體成員都被gcc初始化為NULL
    static const struct file_operations globalmem_fops = {
    .owner = THIS_MODULE,
    .llseek = globalmem_llseek,
    .read = globalmem_read,
    .write = globalmem_write,
    .unlocked_ioctl = globalmem_ioctl,/* 在2.6.x的內(nèi)核版本中,文件操作結(jié)構(gòu)體中,
    才會有ioctl的字段,高版本中使用unlocked_ioctl */
    .open = globalmem_open,
    .release = globalmem_release,
    };

    ?

    轉(zhuǎn)載于:https://www.cnblogs.com/yuan233/p/8146261.html

    總結(jié)

    以上是生活随笔為你收集整理的Linux 字符设备驱动及一些简单的Linux知识的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 人人爽人人干 | 日韩av高清| 美国做爰xxxⅹ性视频 | 爱福利视频一区二区 | 亚洲春色另类 | 免费色视频 | 免费毛片在线播放免费 | 91porny首页入口 | 国产视频一二三区 | 日韩少妇毛片 | 久久综合色网 | 91麻豆影院 | 亚洲天堂男人网 | 日韩激情综合 | 阿v免费在线观看 | 欧美性猛交富婆 | 99视频在线精品 | 69中国xxxxxxxxx96| 黑人巨大精品欧美一区免费视频 | 国产页| 亚洲一区有码 | 奇米精品一区二区三区在线观看 | 日韩女优在线播放 | 狠狠操网站 | 99热精品免费 | 亚洲色成人网站www永久四虎 | 九九热精品视频在线播放 | 日韩视频区 | 午夜在线不卡 | 少妇高潮视频 | 欧美成人777 | 国产主播福利在线 | 90岁老太婆乱淫 | 人人舔人人干 | 久久精品韩国 | 玖玖爱这里只有精品 | 黑料网在线观看 | 欧美 日韩 国产精品 | 中文字幕无码日韩专区免费 | 国产乱淫av片免费看 | a级特黄视频 | 日韩av在线一区二区三区 | 亚洲人成电影在线 | 欧美日韩高清一区 | 91一区二区视频 | 成人黄色三级视频 | 亚洲视频一区在线 | 亚洲一区二区电影网 | 午夜精品国产精品大乳美女 | 天堂av最新网址 | 欧美精产国品一二三区 | 亚洲va天堂va欧美ⅴa在线 | 99亚洲国产精品 | 日本在线视频免费 | 人妻互换一区二区激情偷拍 | 欧美高清| 婷婷激情影院 | 色综合久久88| 福利一二三区 | 日本泡妞xxxx免费视频软件 | 9色在线视频 | 日韩欧美综合 | 翔田千里一区二区三区av | 青青操av在线 | 久久久精品中文字幕麻豆发布 | 欧美成人综合网站 | 国产免费高清视频 | 黄色在线小视频 | 鬼眼| 国产一区二区三区视频网站 | 91这里只有精品 | 12av毛片| 黄色av影视 | 2019日韩中文字幕mv | 日韩成人在线影院 | 求毛片网站 | 影音先锋制服 | 欧美一区二区三区电影 | 美女一级视频 | 亚洲中文字幕久久无码 | 国产又爽又黄的激情精品视频 | 欧美三个黑人玩3p | 黄色三级三级 | 色无极在线 | 亚洲成人精 | 视频免费1区二区三区 | 色涩色| 亚洲热在线视频 | 国产精品久久久久精 | 日本午夜网站 | 国产不卡一区二区视频 | 看日本黄色录像 | 奇米99| 大波大乳videos巨大 | 婷婷激情丁香 | 超碰碰碰碰 | 欧美成人黄色 | 毛片毛片毛片毛片毛片毛片毛片毛片 | 国外成人在线视频 |