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

歡迎訪問(wèn) 生活随笔!

生活随笔

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

linux

Linux 文件 IO

發(fā)布時(shí)間:2024/7/23 linux 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux 文件 IO 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

參考:http://blog.csdn.net/wanxiao009/article/details/5648583

C 和 C++ 文件操作詳解:http://blog.csdn.net/freeking101/article/details/60959624

標(biāo)準(zhǔn)IO與文件IO 的區(qū)別:http://blog.csdn.net/big_bit/article/details/51804391

參考 APUE 整理。如有疑問(wèn),可以直接看 APUE 。。。? ?linux 文件IO


IO文件操作時(shí)最常用的也最基本的內(nèi)容。linux文件系統(tǒng)是由兩層結(jié)構(gòu)構(gòu)建:第一層是虛擬文件系統(tǒng)(VFS),第二層是各種不同的具體文件系統(tǒng)。VFS是吧、把各種具體的文件系統(tǒng)的公共部分抽取出來(lái),形成一個(gè)抽象層,是系統(tǒng)內(nèi)核的一部分。它位于用戶(hù)程序和具體的文件系統(tǒng)中間。它對(duì)用戶(hù)程序提供了標(biāo)準(zhǔn)的文件系統(tǒng)的調(diào)用接口,對(duì)具體的文件系統(tǒng),它通過(guò)一系列的對(duì)不同文件系統(tǒng)公用的函數(shù)指針來(lái)實(shí)際調(diào)用具體的文件系統(tǒng)函數(shù),完成實(shí)際的各有的操作。任何使用文件系統(tǒng)的程序必須經(jīng)過(guò)這層接口來(lái)使用它。通過(guò)這種方式,VFS就對(duì)用于屏蔽了底層文件系統(tǒng)的實(shí)現(xiàn)細(xì)節(jié)和差異。
通過(guò) cat /proc/filesystems命令可以查看系統(tǒng)支持哪些文件系統(tǒng)。


先來(lái)一張總結(jié)圖




1. 引言


? ? ? ? 先說(shuō)明可用的文件 I/O 函數(shù)——打開(kāi)文件、讀文件、寫(xiě)文件等等。大多數(shù)UNIX文件 I/O只需用到5個(gè)函數(shù): open、 read、 write、 lseek 以及 close。然后說(shuō)明不同緩存器長(zhǎng)度對(duì) read 和 write 函數(shù)的影響 。

? ? ? ? 本文所說(shuō)明的函數(shù)經(jīng)常被稱(chēng)之為不帶緩存的 I/O(unbuffered I/O)。標(biāo)準(zhǔn) I/O函數(shù),即庫(kù)函數(shù)的 I/O,是帶緩存的I/O。不帶緩沖的I/O,直接調(diào)用系統(tǒng)調(diào)用,速度快,如函數(shù)open(), read(), write()等。而帶緩沖的I/O,在系統(tǒng)調(diào)用前采用一定的策略,速度慢,比不帶緩沖的I/O安全,如fopen(), fread()、 fwrite()等。


? ? ? ? 術(shù)語(yǔ)——不帶緩存指的是每個(gè) read 和 write都調(diào)用內(nèi)核中的一個(gè)系統(tǒng)調(diào)用。這些不帶緩存的 I/O 函數(shù)不是 ANSI C的組成部分,但是是 POSIX .1和XPG3的組成部分。

? ? ? ? 只要涉及在多個(gè)進(jìn)程間共享資源,原子操作的概念就變成非常重要。我們將通過(guò)文件 I/O 和傳送給 open 函數(shù)的參數(shù)來(lái)討論此概念。并進(jìn)一步討論在多個(gè)進(jìn)程間如何共享文件,并涉及內(nèi)核的有關(guān)數(shù)據(jù)結(jié)構(gòu)。在討論了這些特征后,將說(shuō)明 dup、 fcntl 和 ioctl 函數(shù)。

? ? ? ? 其實(shí),上面所說(shuō)的可以分為 文件I/O(即系統(tǒng)調(diào)用) 和 標(biāo)準(zhǔn) I/O(庫(kù)函數(shù))。

  • 文件I/O:文件I/O稱(chēng)之為不帶緩存的IO(unbuffered I/O)。不帶緩存指的是每個(gè)read,write都調(diào)用內(nèi)核中的一個(gè)系統(tǒng)調(diào)用。也就是一般所說(shuō)的低級(jí)I/O——操作系統(tǒng)提供的基本IO服務(wù),與os綁定,特定于linix或unix平臺(tái)。
  • 標(biāo)準(zhǔn)I/O:標(biāo)準(zhǔn)I/O是ANSI C建立的一個(gè)標(biāo)準(zhǔn)I/O模型,是一個(gè)標(biāo)準(zhǔn)函數(shù)包和stdio.h頭文件中的定義,具有一定的可移植性。標(biāo)準(zhǔn)I/O庫(kù)處理很多細(xì)節(jié)。例如緩存分配,以?xún)?yōu)化長(zhǎng)度執(zhí)行I/O等。標(biāo)準(zhǔn)的I/O提供了三種類(lèi)型的緩存。
    (1)全緩存:當(dāng)填滿(mǎn)標(biāo)準(zhǔn)I/O緩存后才進(jìn)行實(shí)際的I/O操作。
    (2)行緩存:當(dāng)輸入或輸出中遇到新行符時(shí),標(biāo)準(zhǔn)I/O庫(kù)執(zhí)行I/O操作。
    (3)不帶緩存:stderr就是了。

二者的區(qū)別

? ? ? ? 文件I/O 又稱(chēng)為低級(jí)磁盤(pán)I/O,遵循POSIX相關(guān)標(biāo)準(zhǔn)。任何兼容POSIX標(biāo)準(zhǔn)的操作系統(tǒng)上都支持文件I/O。標(biāo)準(zhǔn)I/O被稱(chēng)為高級(jí)磁盤(pán)I/O,遵循ANSI C相關(guān)標(biāo)準(zhǔn)。只要開(kāi)發(fā)環(huán)境中有標(biāo)準(zhǔn)I/O庫(kù),標(biāo)準(zhǔn)I/O就可以使用。(Linux 中使用的是GLIBC,它是標(biāo)準(zhǔn)C庫(kù)的超集。不僅包含ANSI C中定義的函數(shù),還包括POSIX標(biāo)準(zhǔn)中定義的函數(shù)。因此,Linux 下既可以使用標(biāo)準(zhǔn)I/O,也可以使用文件I/O)。
? ? ? ? 通過(guò)文件I/O讀寫(xiě)文件時(shí),每次操作都會(huì)執(zhí)行相關(guān)系統(tǒng)調(diào)用。這樣處理的好處是直接讀寫(xiě)實(shí)際文件,壞處是頻繁的系統(tǒng)調(diào)用會(huì)增加系統(tǒng)開(kāi)銷(xiāo),標(biāo)準(zhǔn)I/O可以看成是在文件I/O的基礎(chǔ)上封裝了緩沖機(jī)制。先讀寫(xiě)緩沖區(qū),必要時(shí)再訪問(wèn)實(shí)際文件,從而減少了系統(tǒng)調(diào)用的次數(shù)。
? ? ? ? 文件I/O中用文件描述符表現(xiàn)一個(gè)打開(kāi)的文件,可以訪問(wèn)不同類(lèi)型的文件如普通文件、設(shè)備文件和管道文件等。而標(biāo)準(zhǔn)I/O中用FILE(流)表示一個(gè)打開(kāi)的文件,通常只用來(lái)訪問(wèn)普通文件。


使用的一些函數(shù)




2. 文件描述符


? ? ? ? 對(duì)于內(nèi)核而言,所有打開(kāi)的文件(Linux 中一切皆文件)都由一個(gè)文件描述符標(biāo)識(shí)。文件描述符是一個(gè)非負(fù)整數(shù)。當(dāng)打開(kāi)一個(gè)現(xiàn)存文件或創(chuàng)建一個(gè)新文件時(shí),內(nèi)核向進(jìn)程返回一個(gè)文件描述符。當(dāng)讀、寫(xiě)一個(gè)文件時(shí),用?open?或?creat?返回的文件描述符標(biāo)識(shí)該文件,將其作為參數(shù)傳送給read?或?write。
? ? ? ? 按照慣例,
UNIX shell使文件描述符0與進(jìn)程的標(biāo)準(zhǔn)輸入相結(jié)合,文件描述符1與標(biāo)準(zhǔn)輸出相結(jié)合,文件描述符2與標(biāo)準(zhǔn)出錯(cuò)輸出相結(jié)合。這是UNIX shell以及很多應(yīng)用程序使用的慣例,而與內(nèi)核無(wú)關(guān)。盡管如此,如果不遵照這種慣例,那么很多UNIX應(yīng)用程序就不能工作。

? ? ? ? 在? POSIX.1 應(yīng)用程序中, 0 1、 2? 被代換成 符號(hào)常數(shù)? STDIN_FILENO 、 STDOUT_FILENO? 和? STDERR_FILENO 。這些常數(shù)都定義在頭文件 < unistd.h > 中。

? ? ? ? 文件描述符的范圍是 0 ~ OPEN_MAX(見(jiàn)表2-7)。早期的?UNIX版本采用的上限值是19 (允許每個(gè)進(jìn)程打開(kāi)?20?個(gè)文件),現(xiàn)在很多系統(tǒng)則將其增加至63。



3. 文件 I/O 相關(guān)系統(tǒng)調(diào)用


APUE 中 關(guān)于文件 I/O 的幾個(gè)基礎(chǔ)系統(tǒng)調(diào)用:open()、creat()、close()、lseek()、read()、write()。

上面的函數(shù)都可以直接通過(guò) man 幫助查看。man 查看的內(nèi)容包括:

man可以查看一下內(nèi)容: 1.一般命令(shell命令) 2.系統(tǒng)調(diào)用(open write等直接陷入內(nèi)核的函數(shù)) 3.子函數(shù)(C函數(shù)庫(kù)等不直接陷入內(nèi)核的函數(shù)) 4.特殊文件(/dev/zero等linux系統(tǒng)中有特殊用途的文件) 5.文件格式(linux系統(tǒng)的配置文件格式 host.conf) 6.游戲 7.宏和地方傳統(tǒng)定義(本地配置) 8.維護(hù)命令(tcpdump等用來(lái)觀察linux系統(tǒng)運(yùn)行情況的命令)


open函數(shù)

open函數(shù):調(diào)用它可以打開(kāi)或者創(chuàng)建一個(gè)文件。(man 2 open

注意:open 創(chuàng)建文件不在同一目錄時(shí),如果目錄不存在則創(chuàng)建失敗。所以創(chuàng)建的文件不在同一目錄時(shí),必須先創(chuàng)建目錄,然后在創(chuàng)建文件。

NAMEopen, openat, creat - open and possibly create a fileSYNOPSIS#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>int open(const char *pathname, int flags);int open(const char *pathname, int flags, mode_t mode);int creat(const char *pathname, mode_t mode);int openat(int dirfd, const char *pathname, int flags);int openat(int dirfd, const char *pathname, int flags, mode_t mode);返回值:成功返回新分配的文件描述符,出錯(cuò)返回-1并設(shè)置errno參數(shù)解析: pathname是要打開(kāi)或者創(chuàng)建的文件名。flags 參數(shù)有一系列常數(shù)值可供選擇,可以同時(shí)選擇多個(gè)常數(shù)用按位或運(yùn)算符連接起來(lái),所以這些常數(shù)的宏定義都以O(shè)_開(kāi)頭,表示or。flags 文件打開(kāi)時(shí)候的選項(xiàng),有三個(gè)選項(xiàng)是必選的!必選項(xiàng):以下三個(gè)常數(shù)中必須指定一個(gè),且僅允許指定一個(gè)。O_RDONLY以只讀方式打開(kāi)文件。O_WRONLY以只寫(xiě)方式打開(kāi)文件。 O_RDWR以讀、寫(xiě)方式打開(kāi)文件。flags 可選選項(xiàng):可選項(xiàng)可以同時(shí)指定0個(gè)或多個(gè),和必選項(xiàng)按位或起來(lái)作為flags參數(shù)。 可選項(xiàng)有很多,這里只介紹一部分,其它選項(xiàng)可參考o(jì)pen(2)的Man Page: O_APPEND 以追加方式打開(kāi)文件,每次寫(xiě)時(shí)都寫(xiě)在文件末尾。 O_CREAT 如果文件不存在,則創(chuàng)建一個(gè),存在則打開(kāi)它。 O_EXCL 與O_CREAT一起使用時(shí),如果文件已經(jīng)存在則返回出錯(cuò)。 O_TRUNC 以只寫(xiě)或讀寫(xiě)方式打開(kāi)時(shí),把文件截?cái)酁? O_DSYNC 每次write時(shí),等待數(shù)據(jù)寫(xiě)到磁盤(pán)上。 O_RSYNC 每次讀時(shí),等待相同部分先寫(xiě)到磁盤(pán)上。 O_NONBLOCK 對(duì)于設(shè)備文件,以O(shè)_NONBLOCK方式打開(kāi)可以做非阻塞I/O(Nonblock I/O) O_SYNC 每次write時(shí),等到數(shù)據(jù)寫(xiě)到磁盤(pán)上并接更新文件屬性。 SYNC選項(xiàng)都會(huì)影響降低性能,有時(shí)候也取決于文件系統(tǒng)的實(shí)現(xiàn)。mode 只有創(chuàng)建文件時(shí)才使用此參數(shù),指定文件的訪問(wèn)權(quán)限。模式有:S_IRWX[UGO] 可讀 可寫(xiě) 可執(zhí)行S_IR[USR GRP OTH] 可讀S_IW[USR GRP OTH] 可寫(xiě)S_IX[USR GRP OTH] 可執(zhí)行S_ISUID 設(shè)置用戶(hù)IDS_ISGID 設(shè)置組ID U->user G->group O->others


由 open 返回的文件描述符一定是最小的未用描述符數(shù)字。

在早期的 UNIX 版本中, open 的第二個(gè)參數(shù)只能是 0、1 或 2。沒(méi)有辦法打開(kāi)一個(gè)尚未存在的文件,因此需要另一個(gè)系統(tǒng)調(diào)用 creat 以創(chuàng)建新文件?,F(xiàn)在 open 函數(shù)提供了選擇項(xiàng) O_CREAT 和 O_TRUNC,于是也就不再需要 creat 函數(shù)了。

示例代碼1:

#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <fcntl.h>int main(void) {int fd;char buf[64];int ret = 0;fd = open("./file.txt", O_RDONLY);if (fd == -1) {printf("open file error\n");exit(1);}printf("---open ok---\n");while((ret = read(fd, buf, sizeof(buf)))) {write(1, buf, ret);}close(fd);return 0; }

示例代碼2(命令行參數(shù)實(shí)現(xiàn)簡(jiǎn)單的cp命令):

/**./mycp src dst 命令行參數(shù)實(shí)現(xiàn)簡(jiǎn)單的cp命令*/ #include <unistd.h> #include <stdlib.h> #include <fcntl.h> #include <stdio.h>char buf[1024];int main(int argc, char *argv[]) {int src, dst;int n;src = open(argv[1], O_RDONLY); //只讀打開(kāi)源文件if(src < 0){perror("open src error");exit(1);}//只寫(xiě)方式打開(kāi),覆蓋原文件內(nèi)容,不存在則創(chuàng)建,rw-r--r--dst = open(argv[2], O_WRONLY|O_TRUNC|O_CREAT, 0644);if(src < 0){perror("open dst error");exit(1);}while((n = read(src, buf, 1024))){if(n < 0){perror("read src error");exit(1);}write(dst, buf, n); //不應(yīng)寫(xiě)出1024, 讀多少寫(xiě)多少}close(src);close(dst);return 0; }

示例代碼3:

#include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <stdlib.h>#define N 1204int main(int argc, char *argv[]) {int fd, fd_out;int n;char buf[N];fd = open("src.txt", O_RDONLY);if(fd < 0){perror("open src.txt error");exit(1);}fd_out = open("des.txt", O_WRONLY|O_CREAT|O_TRUNC, 0644);if(fd < 0){perror("open des.txt error");exit(1);}while((n = read(fd, buf, N))){if(n < 0){perror("read error");exit(1);}write(fd_out, buf, n);}close(fd);close(fd_out);return 0; }

示例代碼:使用庫(kù)函數(shù) fopen

#include <stdio.h> #include <stdlib.h>int main(void) {FILE *fp, *fp_out;int n;fp = fopen("src.txt", "r");if(fp == NULL){perror("fopen error");exit(1);}fp_out = fopen("des.cp", "w");if(fp == NULL){perror("fopen error");exit(1);}while((n = fgetc(fp)) != EOF){fputc(n, fp_out);}fclose(fp);fclose(fp_out);return 0; }

示例代碼:打開(kāi)錯(cuò)誤

#include <unistd.h> //read write #include <fcntl.h> //open close O_WRONLY O_RDONLY O_CREAT O_RDWR #include <stdlib.h> //exit #include <errno.h> #include <stdio.h> //perror #include <string.h>int main(void) {int fd; #if 1//打開(kāi)文件不存在fd = open("test", O_RDONLY | O_CREAT);if(fd < 0){printf("errno = %d\n", errno);//perror("open test error");printf("open test error: %s\n" , strerror(errno));//printf("open test error\n");exit(1);} #elif 0//打開(kāi)的文件沒(méi)有對(duì)應(yīng)權(quán)限(以只寫(xiě)方式打開(kāi)一個(gè)只有讀權(quán)限的文件)fd = open("test", O_WRONLY); //O_RDWR也是錯(cuò)誤的if(fd < 0){printf("errno = %d\n", errno);perror("open test error");//printf("open test error\n");exit(1);}#endif #if 0//以寫(xiě)方式打開(kāi)一個(gè)目錄fd = open("testdir", O_RDWR); //O_WRONLY也是錯(cuò)的 if(fd < 0){perror("open testdir error");exit(1);} #endifreturn 0; }

注意open函數(shù)與C標(biāo)準(zhǔn)I/O庫(kù)的fopen函數(shù)有些細(xì)微的區(qū)別:

  • 以可寫(xiě)的方式fopen一個(gè)文件時(shí),如果文件不存在會(huì)自動(dòng)創(chuàng)建,而open一個(gè)文件時(shí)必須明確指定O_CREAT才會(huì)創(chuàng)建文件,否則文件不存在就出錯(cuò)返回。
  • 以w或w+方式fopen一個(gè)文件時(shí),如果文件已存在就截?cái)酁?字節(jié),而open一個(gè)文件時(shí)必須明確指定O_TRUNC才會(huì)截?cái)辔募?#xff0c;否則直接在原來(lái)的數(shù)據(jù)上改寫(xiě)。
  • 第三個(gè)參數(shù)mode指定文件權(quán)限,可以用八進(jìn)制數(shù)表示,比如0644表示-rw-r-r–,也可以用S_IRUSR、S_IWUSR等宏定義按位或起來(lái)表示,詳見(jiàn)open(2)的Man Page。要注意的是,文件權(quán)限由open的mode參數(shù)和當(dāng)前進(jìn)程的umask掩碼共同決定。

補(bǔ)充說(shuō)明一下Shell的umask命令。Shell進(jìn)程的umask掩碼可以用umask命令查看:(反掩碼 的數(shù)字是要去掉的權(quán)限

$ umask 0002


用touch命令創(chuàng)建一個(gè)文件時(shí),創(chuàng)建權(quán)限是0666,而touch進(jìn)程繼承了Shell進(jìn)程的umask掩碼,所以最終的文件權(quán)限是0666&~022=0644。


同樣道理,用gcc編譯生成一個(gè)可執(zhí)行文件時(shí),創(chuàng)建權(quán)限是0777,而最終的文件權(quán)限是:0777 & ~022 = 0755。


我們看到的都是被umask掩碼修改之后的權(quán)限,那么如何證明touch或gcc創(chuàng)建文件的權(quán)限本來(lái)應(yīng)該是0666和0777呢?我們可以把Shell進(jìn)程的umask改成0,再重復(fù)上述實(shí)驗(yàn)。


最大打開(kāi)文件個(gè)數(shù)

查看當(dāng)前系統(tǒng)允許打開(kāi)最大文件個(gè)數(shù):cat /proc/sys/fs/file-max

修改默認(rèn)設(shè)置最大打開(kāi)文件個(gè)數(shù)為4096:ulimit -n 4096


creat函數(shù)

creat 以只寫(xiě)方式創(chuàng)建一個(gè)文件,若文件已經(jīng)存在,則把它截?cái)酁?

#include <fcntl.h> int creat(const char *pathname, mode_t mode) // 返回:若成功為只寫(xiě)打開(kāi)的文件描述符,若出錯(cuò)為- 1參數(shù)解析: pathname 要?jiǎng)?chuàng)建的文件名稱(chēng)mode 跟open的第三個(gè)參數(shù)相同,可讀,可寫(xiě),可執(zhí)行 。如果失敗 ,返回值為-1creat 函數(shù) 等同于 open (pathname, O_WRONLY | O_CREAT | O_TRUNC, mode)在早期的 UNIX 版本中, open 的第二個(gè)參數(shù)只能是 0、1 或 2。沒(méi)有辦法打開(kāi)一個(gè)尚未存在的文件,因此需要另一個(gè)系統(tǒng)調(diào)用 creat 以創(chuàng)建新文件。 現(xiàn)在 open 函數(shù)提供了選擇項(xiàng) O_CREAT 和 O_TRUNC,于是也就不再需要 creat 函數(shù)了。

creat 的一個(gè)不足之處是它以只寫(xiě)方式打開(kāi)所創(chuàng)建的文件。在提供 open的新版本之前,如果要?jiǎng)?chuàng)建一個(gè)臨時(shí)文件,并要先寫(xiě)該文件,然后又讀該文件,則必須先調(diào)用 creat, clo se,然后再調(diào)用 open。現(xiàn)在則可用下列方式調(diào)用open:open(pathname, O_RDWR|O_CREAT|O_TRUNC, m o d e) ;


close函數(shù)

close 關(guān)閉已經(jīng)打開(kāi)的文件,并釋放文件描述符

#include <unistd.h> int close(int fd) // 返回值:成功返回0,出錯(cuò)返回-1并設(shè)置errno 參數(shù)解析:fd 文件描述符,由 open 或者 creat 返回的非負(fù)整數(shù)。 當(dāng)一個(gè)進(jìn)程結(jié)束時(shí),操作系統(tǒng)會(huì)自動(dòng)釋放該進(jìn)程打開(kāi)的所有文件。但還是推薦用close來(lái)關(guān)閉文件。 lsof命令可以查看進(jìn)程打開(kāi)了那些文件。

? ? ? ? 參數(shù)fd是要關(guān)閉的文件描述符。需要說(shuō)明的是,當(dāng)一個(gè)進(jìn)程終止時(shí),內(nèi)核對(duì)該進(jìn)程所有尚未關(guān)閉的文件描述符調(diào)用close關(guān)閉,所以即使用戶(hù)程序不調(diào)用close,在終止時(shí)內(nèi)核也會(huì)自動(dòng)關(guān)閉它打開(kāi)的所有文件。但是對(duì)于一個(gè)長(zhǎng)年累月運(yùn)行的程序(比如網(wǎng)絡(luò)服務(wù)器),打開(kāi)的文件描述符一定要記得關(guān)閉,否則隨著打開(kāi)的文件越來(lái)越多,會(huì)占用大量文件描述符和系統(tǒng)資源。
? ? ? ? 由open返回的文件描述符一定是該進(jìn)程尚未使用的最小描述符。由于程序啟動(dòng)時(shí)自動(dòng)打開(kāi)文件描述符0、1、2,因此第一次調(diào)用open打開(kāi)文件通常會(huì)返回描述符3,再調(diào)用open就會(huì)返回4。可以利用這一點(diǎn)在標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出或標(biāo)準(zhǔn)錯(cuò)誤輸出上打開(kāi)一個(gè)新文件,實(shí)現(xiàn)重定向的功能。例如,首先調(diào)用close關(guān)閉文件描述符1,然后調(diào)用open打開(kāi)一個(gè)常規(guī)文件,則一定會(huì)返回文件描述符1,這時(shí)候標(biāo)準(zhǔn)輸出就不再是終端,而是一個(gè)常規(guī)文件了,再調(diào)用printf就不會(huì)打印到屏幕上,而是寫(xiě)到這個(gè)文件中了。后面要講的dup2函數(shù)提供了另外一種辦法在指定的文件描述符上打開(kāi)文件。

/* 本程序演示了,在一個(gè)函數(shù)中打開(kāi)一個(gè)文件,然后在另一個(gè)函數(shù)中關(guān)閉文件。 可以看到fd相關(guān)數(shù)據(jù)結(jié)構(gòu)是由內(nèi)核維護(hù)的, 所以如果你打開(kāi)了一個(gè)文件而沒(méi)有關(guān)閉,那些數(shù)據(jù)結(jié)構(gòu)就會(huì)占用內(nèi)存。 需要說(shuō)明的是,當(dāng)一個(gè)進(jìn)程終止時(shí),內(nèi)核對(duì)該進(jìn)程所有尚未關(guān)閉的文件描述符調(diào)用close關(guān)閉, 所以即使用戶(hù)程序不調(diào)用close,在終止時(shí)內(nèi)核也會(huì)自動(dòng)關(guān)閉它打開(kāi)的所有文件。 */#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <fcntl.h>int openFile(void) {int fd=-1; fd = open("./test.txt", O_RDONLY);if(fd>0) printf("open file fd : %d\n", fd);else printf("open file fail\n");return fd; }int closeFile(int fd) {int retVal;retVal=close(fd);if(retVal<0) printf("close file fail\n");else printf("close file sueccess\n");return retVal; }void main(void) {int fd=openFile();closeFile(fd); } 程序運(yùn)行截圖:




lseek函數(shù)

Linux文件空洞與稀疏文件:http://blog.csdn.net/freeking101/article/details/78190379

lseek 用來(lái)定位當(dāng)前文件偏移量,既你對(duì)文件操作從文件的那一部分開(kāi)始。

每個(gè)打開(kāi)文件都有一個(gè)與其相關(guān)聯(lián)的“當(dāng)前文件位移量”。它是一個(gè)非負(fù)整數(shù),用以度量從文件開(kāi)始處計(jì)算的字節(jié)數(shù)。通常,讀、寫(xiě)操作都從當(dāng)前文件位移量處開(kāi)始,并使位移量增加所讀或?qū)懙淖止?jié)數(shù)。按系統(tǒng)默認(rèn),當(dāng)打開(kāi)一個(gè)文件時(shí),除非指定 O_APPEND 選擇項(xiàng),否則該位移量被設(shè)置為0??梢哉{(diào)用 lseek 顯式地定位一個(gè)打開(kāi)文件。

#include <unistd.h> off_t lseek(int fd, off_t offset, int whence); // 如果失敗,返回值為-1,成功返回移動(dòng)后的文件偏移量。參數(shù)解析:fd 文件描述符。offset 必須與whence一同解析whence為 SEEK_SET, 則offset從文件的開(kāi)頭算起。whence為 SEEK_CUR, 則offset從當(dāng)前位置算起,既新偏移量為當(dāng)前偏移量加上offsetwhence為 SEEK_END, 則offset從文件末尾算起。 可以通過(guò)lseek、write來(lái)快速創(chuàng)建一個(gè)大文件。

每個(gè)打開(kāi)的文件都記錄著當(dāng)前讀寫(xiě)位置,打開(kāi)文件時(shí)讀寫(xiě)位置是0,表示文件開(kāi)頭,通常讀寫(xiě)多少個(gè)字節(jié)就會(huì)將讀寫(xiě)位置往后移多少個(gè)字節(jié)。但是有一個(gè)例外,如果以O(shè)_APPEND方式打開(kāi),每次寫(xiě)操作都會(huì)在文件末尾追加數(shù)據(jù),然后將讀寫(xiě)位置移到新的文件末尾。lseek和標(biāo)準(zhǔn)I/O庫(kù)的fseek函數(shù)類(lèi)似,可以移動(dòng)當(dāng)前讀寫(xiě)位置(或者叫偏移量)。

參數(shù)offset和whence的含義和fseek函數(shù)完全相同。只不過(guò)第一個(gè)參數(shù)換成了文件描述符。和fseek一樣,偏移量允許超過(guò)文件末尾,這種情況下對(duì)該文件的下一次寫(xiě)操作將延長(zhǎng)文件,中間空洞的部分讀出來(lái)都是0。若lseek成功執(zhí)行,則返回新的偏移量,因此可用以下方法確定一個(gè)打開(kāi)文件的當(dāng)前偏移量:

off_t currpos;
currpos = lseek(fd, 0, SEEK_CUR);

這種方法也可用來(lái)確定文件或設(shè)備是否可以設(shè)置偏移量,常規(guī)文件都可以設(shè)置偏移量,而設(shè)備一般是不可以設(shè)置偏移量的。如果設(shè)備不支持lseek,則lseek返回-1,并將errno設(shè)置為ESPIPE。注意fseek和lseek在返回值上有細(xì)微的差別,fseek成功時(shí)返回0失敗時(shí)返回-1,要返回當(dāng)前偏移量需調(diào)用ftell,而lseek成功時(shí)返回當(dāng)前偏移量失敗時(shí)返回-1。

lseek 僅將當(dāng)前的文件位移量記錄在內(nèi)核內(nèi),它并不引起任何 I/O操作。然后,該位移量用于下一個(gè)讀或?qū)懖僮鳌?/span>文件位移量可以大于文件的當(dāng)前長(zhǎng)度,在這種情況下,對(duì)該文件的下一次寫(xiě)將延長(zhǎng)該文件,并在文件中構(gòu)成一個(gè)空調(diào),這一點(diǎn)是允許的。位于文件中但沒(méi)有寫(xiě)過(guò)的字節(jié)都被讀為 0。


示例代碼:

新建一個(gè)文件 lseek.txt ,文件內(nèi)容:It's a test for lseek。然后新建一個(gè) lseek.c 文件,內(nèi)容如下:

#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <fcntl.h>int main(void) {int fd, n;char msg[] = "It's a test for lseek\n";char ch;fd = open("lseek.txt", O_RDWR|O_CREAT|O_TRUNC, 0644);if(fd < 0){perror("open lseek.txt error");exit(1);}write(fd, msg, strlen(msg));lseek(fd, 0, SEEK_SET);while((n = read(fd, &ch, 1))){if(n < 0){perror("read error");exit(1);}write(STDOUT_FILENO, &ch, n);//putchar(ch);//printf("%c", ch);}close(fd);return 0; }

使用 lseek 得出文件大小

#include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <stdlib.h>int main(void) {int fd;fd = open("lseek.txt", O_RDWR | O_CREAT, 0644);if (fd < 0) {perror("open error");exit(1);} #if 0int ret = lseek(fd, 99, SEEK_SET);if (ret < 0) {perror("lseek error");exit(1);}write(fd, "a", 1); #endifint ret = lseek(fd, 0, SEEK_END);if (ret < 0) {perror("lseek error");exit(1);}printf("the lenth of lseek.txt is %d\n", ret);close(fd);return 0; }

示例代碼:

#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <fcntl.h>int main(void) {int fd;fd = open("lseek.txt", O_RDONLY);if(fd < 0){perror("open lseek.txt error");exit(1);}int len = lseek(fd, 0, SEEK_END);if(len == -1){perror("lseek error");exit(1);}printf("len of msg = %d\n", len);off_t cur = lseek(fd, -10, SEEK_END);if(cur == -1){perror("lseek error");exit(1);}printf("--------| %ld\n", cur);close(fd);return 0; }


read函數(shù)

read 從打開(kāi)的設(shè)備或文件偏移量處讀入指定大小的數(shù)據(jù)。

#include <unistd.h> ssize_t read(int fd, void *buf, size_t count);返回值:成功返回讀取的字節(jié)數(shù),出錯(cuò)返回-1并設(shè)置errno,如果在調(diào)read之前已到達(dá)文件末尾,則這次read返回0參數(shù)解析 fd 文件描述符 ,有open返回。buf 讀入文件內(nèi)容存放的內(nèi)存首地址。count 要讀取的字節(jié)數(shù)。 實(shí)際讀入的字節(jié)數(shù)可能會(huì)小于要求讀入的字節(jié)數(shù)。比如文件只有所剩的字節(jié)數(shù)小于你要讀入的字節(jié)數(shù),讀取fifo文件和網(wǎng)絡(luò)套接字時(shí)都可能出現(xiàn)這種情況

? ? ? ? 參數(shù)count是請(qǐng)求讀取的字節(jié)數(shù),讀上來(lái)的數(shù)據(jù)保存在緩沖區(qū)buf中,同時(shí)文件的當(dāng)前讀寫(xiě)位置向后移。注意這個(gè)讀寫(xiě)位置和使用C標(biāo)準(zhǔn)I/O庫(kù)時(shí)的讀寫(xiě)位置有可能不同,這個(gè)讀寫(xiě)位置是記在內(nèi)核中的,而使用C標(biāo)準(zhǔn)I/O庫(kù)時(shí)的讀寫(xiě)位置是用戶(hù)空間I/O緩沖區(qū)中的位置。比如用fgetc讀一個(gè)字節(jié),fgetc有可能從內(nèi)核中預(yù)讀1024個(gè)字節(jié)到I/O緩沖區(qū)中,再返回第一個(gè)字節(jié),這時(shí)該文件在內(nèi)核中記錄的讀寫(xiě)位置是1024,而在FILE結(jié)構(gòu)體中記錄的讀寫(xiě)位置是1。注意返回值類(lèi)型是ssize_t,表示有符號(hào)的size_t,這樣既可以返回正的字節(jié)數(shù)、0(表示到達(dá)文件末尾)也可以返回負(fù)值-1(表示出錯(cuò))。read函數(shù)返回時(shí),返回值說(shuō)明了buf中前多少個(gè)字節(jié)是剛讀上來(lái)的。有些情況下,實(shí)際讀到的字節(jié)數(shù)(返回值)會(huì)小于請(qǐng)求讀的字節(jié)數(shù)count,

? ? ? ? 例如:讀常規(guī)文件時(shí),在讀到count個(gè)字節(jié)之前已到達(dá)文件末尾。例如,距文件末尾還有30個(gè)字節(jié)而請(qǐng)求讀100個(gè)字節(jié),則read返回30,下次read將返回0。從終端設(shè)備讀,通常以行為單位,讀到換行符就返回了。從網(wǎng)絡(luò)讀,根據(jù)不同的傳輸層協(xié)議和內(nèi)核緩存機(jī)制,返回值可能小于請(qǐng)求的字節(jié)數(shù),后面socket編程部分會(huì)詳細(xì)講解。


write函數(shù)

write向打開(kāi)的設(shè)備或文件中寫(xiě)入一定字節(jié)的數(shù)據(jù)。

#include <unistd.h> ssize_t write(int fd, const void *buf, size_t count); // 返回值:成功返回寫(xiě)入的字節(jié)數(shù),出錯(cuò)返回-1并設(shè)置errno失敗返回-1,成功返回實(shí)際寫(xiě)入的字節(jié)數(shù)。當(dāng)磁盤(pán)滿(mǎn)或者文件到達(dá)上限時(shí)可能寫(xiě)入失敗。 一般從當(dāng)前文件偏移量出寫(xiě)入,但如果打開(kāi)時(shí)使用了O_APPEND,那么無(wú)論當(dāng)前文件偏移量在哪里,都會(huì)移動(dòng)到文件末尾寫(xiě)入。

寫(xiě)常規(guī)文件時(shí),write的返回值通常等于請(qǐng)求寫(xiě)的字節(jié)數(shù)count,而向終端設(shè)備或網(wǎng)絡(luò)寫(xiě)則不一定


阻塞和非阻塞

? ? ? ? 讀常規(guī)文件是不會(huì)阻塞的,不管讀多少字節(jié),read一定會(huì)在有限的時(shí)間內(nèi)返回。從終端設(shè)備或網(wǎng)絡(luò)讀則不一定,如果從終端輸入的數(shù)據(jù)沒(méi)有換行符,調(diào)用read讀終端設(shè)備就會(huì)阻塞,如果網(wǎng)絡(luò)上沒(méi)有接收到數(shù)據(jù)包,調(diào)用read從網(wǎng)絡(luò)讀就會(huì)阻塞,至于會(huì)阻塞多長(zhǎng)時(shí)間也是不確定的,如果一直沒(méi)有數(shù)據(jù)到達(dá)就一直阻塞在那里。同樣,寫(xiě)常規(guī)文件是不會(huì)阻塞的,而向終端設(shè)備或網(wǎng)絡(luò)寫(xiě)則不一定。
? ? ? ? 現(xiàn)在明確一下阻塞(Block)這個(gè)概念。當(dāng)進(jìn)程調(diào)用一個(gè)阻塞的系統(tǒng)函數(shù)時(shí),該進(jìn)程被置于睡眠(Sleep)狀態(tài),這時(shí)內(nèi)核調(diào)度其它進(jìn)程運(yùn)行,直到該進(jìn)程等待的事件發(fā)生了(比如網(wǎng)絡(luò)上接收到數(shù)據(jù)包,或者調(diào)用sleep指定的睡眠時(shí)間到了)它才有可能繼續(xù)運(yùn)行。與睡眠狀態(tài)相對(duì)的是運(yùn)行(Running)狀態(tài),在Linux內(nèi)核中,處于運(yùn)行狀態(tài)的進(jìn)程分為兩種情況:
? ? ? ? 正在被調(diào)度執(zhí)行。CPU處于該進(jìn)程的上下文環(huán)境中,程序計(jì)數(shù)器(eip)里保存著該進(jìn)程的指令地址,通用寄存器里保存著該進(jìn)程運(yùn)算過(guò)程的中間結(jié)果,正在執(zhí)行該進(jìn)程的指令,正在讀寫(xiě)該進(jìn)程的地址空間。
? ? ? ? 就緒狀態(tài)。該進(jìn)程不需要等待什么事件發(fā)生,隨時(shí)都可以執(zhí)行,但CPU暫時(shí)還在執(zhí)行另一個(gè)進(jìn)程,所以該進(jìn)程在一個(gè)就緒隊(duì)列中等待被內(nèi)核調(diào)度。系統(tǒng)中可能同時(shí)有多個(gè)就緒的進(jìn)程,那么該調(diào)度誰(shuí)執(zhí)行呢?內(nèi)核的調(diào)度算法是基于優(yōu)先級(jí)和時(shí)間片的,而且會(huì)根據(jù)每個(gè)進(jìn)程的運(yùn)行情況動(dòng)態(tài)調(diào)整它的優(yōu)先級(jí)和時(shí)間片,讓每個(gè)進(jìn)程都能比較公平地得到機(jī)會(huì)執(zhí)行,同時(shí)要兼顧用戶(hù)體驗(yàn),不能讓和用戶(hù)交互的進(jìn)程響應(yīng)太慢。


下面這個(gè)小程序從終端讀數(shù)據(jù)再寫(xiě)回終端。

阻塞讀終端

#include <unistd.h> #include <stdlib.h> int main(void) {char buf[10];int n;n = read(STDIN_FILENO, buf, 10);if (n < 0) {perror("read STDIN_FILENO\n");exit(1);}write(STDOUT_FILENO, buf, n);return 0; }


第一次執(zhí)行a.out的結(jié)果很正常,而第二次執(zhí)行的過(guò)程有點(diǎn)特殊。

現(xiàn)在分析一下:Shell進(jìn)程創(chuàng)建a.out進(jìn)程,a.out進(jìn)程開(kāi)始執(zhí)行,而Shell進(jìn)程睡眠等待a.out進(jìn)程退出。a.out調(diào)用read時(shí)睡眠等待,直到終端設(shè)備輸入了換行符才從read返回,read只讀走10個(gè)字符,剩下的字符仍然保存在內(nèi)核的終端設(shè)備輸入緩沖區(qū)中。a.out進(jìn)程打印并退出,這時(shí)Shell進(jìn)程恢復(fù)運(yùn)行,Shell繼續(xù)從終端讀取用戶(hù)輸入的命令,于是讀走了終端設(shè)備輸入緩沖區(qū)中剩下的字符d和換行符,把它當(dāng)成一條命令解釋執(zhí)行,結(jié)果發(fā)現(xiàn)執(zhí)行不了,沒(méi)有 abcd 這個(gè)命令。如果在open一個(gè)設(shè)備時(shí)指定了O_NONBLOCK標(biāo)志,read/write就不會(huì)阻塞。以read為例,如果設(shè)備暫時(shí)沒(méi)有數(shù)據(jù)可讀就返回-1,同時(shí)置errno為EWOULDBLOCK(或者EAGAIN,這兩個(gè)宏定義的值相同),表示本來(lái)應(yīng)該阻塞在這里(would block,虛擬語(yǔ)氣),事實(shí)上并沒(méi)有阻塞而是直接返回錯(cuò)誤,調(diào)用者應(yīng)該試著再讀一次(again)。這種行為方式稱(chēng)為輪詢(xún)(Poll),調(diào)用者只是查詢(xún)一下,而不是阻塞在這里死等,這樣可以同時(shí)監(jiān)視多個(gè)設(shè)備:

while(1) {非阻塞read(設(shè)備1);if(設(shè)備1有數(shù)據(jù)到達(dá))處理數(shù)據(jù);非阻塞read(設(shè)備2);if(設(shè)備2有數(shù)據(jù)到達(dá))處理數(shù)據(jù); ... }

如果read(設(shè)備1)是阻塞的,那么只要設(shè)備1沒(méi)有數(shù)據(jù)到達(dá)就會(huì)一直阻塞在設(shè)備1的read調(diào)用上,即使設(shè)備2有數(shù)據(jù)到達(dá)也不能處理,使用非阻塞I/O就可以避免設(shè)備2得不到及時(shí)處
理。非阻塞I/O有一個(gè)缺點(diǎn),如果所有設(shè)備都一直沒(méi)有數(shù)據(jù)到達(dá),調(diào)用者需要反復(fù)查詢(xún)做無(wú)用功,如果阻塞在那里,操作系統(tǒng)可以調(diào)度別的進(jìn)程執(zhí)行,就不會(huì)做無(wú)用功了。在使用非阻塞I/O時(shí),通常不會(huì)在一個(gè)while循環(huán)中一直不停地查詢(xún)(這稱(chēng)為T(mén)ight Loop),而是每延遲等待一會(huì)兒來(lái)查詢(xún)一下,以免做太多無(wú)用功,在延遲等待的時(shí)候可以調(diào)度其它進(jìn)程執(zhí)行。

while(1) {非阻塞read(設(shè)備1);if(設(shè)備1有數(shù)據(jù)到達(dá))處理數(shù)據(jù);非阻塞read(設(shè)備2);if(設(shè)備2有數(shù)據(jù)到達(dá))處理數(shù)據(jù);...sleep(n); }

這樣做的問(wèn)題是,設(shè)備1有數(shù)據(jù)到達(dá)時(shí)可能不能及時(shí)處理,最長(zhǎng)需延遲n秒才能處理,而且反復(fù)查詢(xún)還是做了很多無(wú)用功。以后要學(xué)習(xí)的select(2)函數(shù)可以阻塞地同時(shí)監(jiān)視多個(gè)設(shè)備,還可以設(shè)定阻塞等待的超時(shí)時(shí)間,從而圓滿(mǎn)地解決了這個(gè)問(wèn)題。

以下是一個(gè)非阻塞I/O的例子。目前我們學(xué)過(guò)的可能引起阻塞的設(shè)備只有終端,所以我們用終端來(lái)做這個(gè)實(shí)驗(yàn)。程序開(kāi)始執(zhí)行時(shí)在0、1、2文件描述符上自動(dòng)打開(kāi)的文件就是終端,但是沒(méi)有O_NONBLOCK標(biāo)志。所以就像例 28.2 “阻塞讀終端”一樣,讀標(biāo)準(zhǔn)輸入是阻塞的。我們可以重新打開(kāi)一遍設(shè)備文件/dev/tty(表示當(dāng)前終端),在打開(kāi)時(shí)指定O_NONBLOCK標(biāo)志。

非阻塞讀終端示例代碼:

#include <unistd.h> #include <fcntl.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h>#define MSG_TRY "try again\n"int main(void) {char buf[10];int fd, n;fd = open("/dev/tty", O_RDONLY|O_NONBLOCK); //使用O_NONBLOCK標(biāo)志設(shè)置非阻塞讀終端if(fd < 0){perror("open /dev/tty");exit(1);} tryagain:n = read(fd, buf, 10);if(n < 0){//由于open時(shí)指定了O_NONBLOCK標(biāo)志,read讀設(shè)備,沒(méi)有數(shù)據(jù)到達(dá)返回-1,同時(shí)將errno設(shè)置為EAGAIN或EWOULDBLOCKif(errno != EAGAIN){ //也可以是 if(error != EWOULDBLOCK)兩個(gè)宏值相同perror("read /dev/tty");exit(1);}sleep(3);write(STDOUT_FILENO, MSG_TRY, strlen(MSG_TRY));goto tryagain;}write(STDOUT_FILENO, buf, n);close(fd);return 0; }

非阻塞I/O實(shí)現(xiàn)等待超時(shí)的例子。既保證了超時(shí)退出的邏輯又保證了有數(shù)據(jù)到達(dá)時(shí)處理延遲較小。

#include <unistd.h> #include <fcntl.h> #include <stdlib.h> #include <stdio.h> #include <errno.h> #include <string.h>#define MSG_TRY "try again\n" #define MSG_TIMEOUT "time out\n"int main(void) {char buf[10];int fd, n, i;fd = open("/dev/tty", O_RDONLY|O_NONBLOCK);if(fd < 0){perror("open /dev/tty");exit(1);}printf("open /dev/tty ok... %d\n", fd);for(i = 0; i < 5; i++){n = read(fd, buf, 10);if(n > 0){ //說(shuō)明讀到了東西break;}if(errno != EAGAIN){ //EWOULDBLK perror("read /dev/tty");exit(1);}sleep(3);write(STDOUT_FILENO, MSG_TRY, strlen(MSG_TRY));}if(i == 5){write(STDOUT_FILENO, MSG_TRY, strlen(MSG_TIMEOUT));}else{write(STDOUT_FILENO, buf, n);}close(fd);return 0; }


內(nèi)核用于所有 I/O 的數(shù)據(jù)結(jié)構(gòu)

內(nèi)核使用了三種數(shù)據(jù)結(jié)構(gòu),來(lái)實(shí)現(xiàn)I/O?

  • 每個(gè)進(jìn)程在進(jìn)程表中都有一個(gè)記錄項(xiàng),每個(gè)記錄項(xiàng)中有一張打開(kāi)文件描述符表,可將其視為一個(gè)矢量,每個(gè)描述符占用一項(xiàng)。與每個(gè) 文 件描述符相關(guān)聯(lián)的是:
    (a) 文件描述符標(biāo)志。
    (b) 指向一個(gè)文件表項(xiàng)的指針。
  • 內(nèi)核為所有打開(kāi)文件維持一張文件表。每個(gè)文件表項(xiàng)包含:
    (a) 文件狀態(tài)標(biāo)志(讀、寫(xiě)、增寫(xiě)、同步等)。
    (b) 當(dāng)前文件位移量。
    (c) 指向該文件v節(jié)點(diǎn)表項(xiàng)的指針。
  • 每個(gè)打開(kāi)文件(或設(shè)備)都有一個(gè)v節(jié)點(diǎn)結(jié)構(gòu)。v節(jié)點(diǎn)包含了文件類(lèi)型和對(duì)此文件進(jìn)行各種操作的函數(shù)的指針信息。對(duì)于大多數(shù)文件, v節(jié)點(diǎn)還包含了該文件的i節(jié)點(diǎn)(索引節(jié)點(diǎn))。例如, i節(jié)點(diǎn)包含了文件的所有者、文件長(zhǎng)度、文件所在的設(shè)備、指向文件在盤(pán)上所使用的實(shí)際數(shù)據(jù)塊的指針等等
  • 如圖顯示了進(jìn)程的三張表之間的關(guān)系。該進(jìn)程有兩個(gè)不同的打開(kāi)文件:一個(gè)文件打開(kāi)為標(biāo)準(zhǔn)輸入(文件描述符0),另一個(gè)打開(kāi)為標(biāo)準(zhǔn)輸出(文件描述符為 1)。

    打開(kāi)文件的內(nèi)核數(shù)據(jù)結(jié)構(gòu)


    兩個(gè)獨(dú)立進(jìn)程各自打開(kāi)了同一文件,它們擁有各自的文件表項(xiàng),但共享v節(jié)點(diǎn)表。

    如圖所示,假定第一個(gè)進(jìn)程使該文件在文件描述符 3上打開(kāi),而另一個(gè)進(jìn)程則使此文件在文件描述符 4上打開(kāi)。打開(kāi)此文件的每個(gè)進(jìn)程都得到一個(gè)文件表項(xiàng),但對(duì)一個(gè)給定的文件只有一個(gè) v節(jié)點(diǎn)表項(xiàng)。每個(gè)進(jìn)程都有自己的文件表項(xiàng)的一個(gè)理由是:這種安排使每個(gè)進(jìn)程都有它自己的對(duì)該文件的當(dāng)前位移量

    兩個(gè)獨(dú)立進(jìn)程各自打開(kāi)同一個(gè)文件



    原子操作

    假定 A、B 兩個(gè)進(jìn)程以 O_APPEND 方式打開(kāi)同一個(gè)文件。A 進(jìn)程去寫(xiě)該文件,假設(shè)此時(shí)文件偏移量為1000,B進(jìn)程同時(shí)去寫(xiě)該文件,此時(shí)由于A進(jìn)程未寫(xiě)完,則B進(jìn)程得到的文件偏移量仍為1000。最后B進(jìn)程的內(nèi)容可能會(huì)覆蓋掉A進(jìn)程寫(xiě)的內(nèi)容。pread , pwrite是原子讀寫(xiě)操作。相當(dāng)于先把文件偏移量定位到offset,然后在進(jìn)行讀寫(xiě)。這都是一步完成,不存在競(jìng)爭(zhēng)問(wèn)題。

    #include <unistd.h> ssize_t pread(int filedes, void *buf, size_t nbytes, off_t offset) ssize_t pwrite(int filedes, const void *buf, size_t nbytes, off_t offset) 返回值跟read和write一樣。offset為文件偏移量。

    調(diào)用 pread 相當(dāng)于 順序調(diào)用 lseek 和 read ,但是 pread 又與這種順序調(diào)用有下列重要區(qū)別:

    • 調(diào)用 pread 時(shí),無(wú)法中斷其定位和讀操作
    • 不能更新文件指針

    調(diào)用 pwrite 相當(dāng)于 順序調(diào)用 lseek 和 write ,但但也與他們有上述類(lèi)似的區(qū)別。


    dup 和 dup2 函數(shù)

    dup/dup2用來(lái)復(fù)制一個(gè)已經(jīng)存在的文件描述符

    #include <unistd.h> int dup(int filedes) ; int dup2(int filedes, int filedes2) ; 失敗返回-1,成功返回新文件描述符。filedes2是新文件描述符,如果已經(jīng)打開(kāi)則先關(guān)閉它。 ssize_t pread(int filedes, void *buf, size_t nbytes, off_t offset); 共享文件表項(xiàng)。

    dup 和 dup2 的使用

    • dup 返回的新文件描述符一定是當(dāng)前可用文件描述符中的最小數(shù)值。
    • dup2 則可以用 filedes2 參數(shù)指定新描述符的數(shù)值。如果 filedes2 已經(jīng)打開(kāi),則先將其關(guān)閉。如若filedes 等于 filedes2,則 dup2 返回 filedes2,而不關(guān)閉它。

    這些函數(shù)返回的新文件描述符與參數(shù) filedes 共享同一個(gè)文件表項(xiàng)。如圖所示:


    ? ? ? ? 在此圖中,我們假定進(jìn)程執(zhí)行了:newfd = dup(1) 。當(dāng)此函數(shù)開(kāi)始執(zhí)行時(shí),假定下一個(gè)可用的描述符是 3 (這是非常有可能的,因?yàn)?0, 1和2由 shell 打開(kāi))。因?yàn)閮蓚€(gè)描述符指向同一文件表項(xiàng),所以它們共享同一文件狀態(tài)標(biāo)志 (讀、寫(xiě)、添寫(xiě)等)以及同一當(dāng)前文件位移量。
    ? ? ? ? 每個(gè)文件描述符都有它自己的一套文件描述符標(biāo)志。正如我們將在下一節(jié)中說(shuō)明的那樣,新描述符的執(zhí)行時(shí)關(guān)閉( close-on-exec )文件描述符標(biāo)志總是由 dup 函數(shù)清除。
    ? ? ? ? 復(fù)制一個(gè)描述符的另一種方法是使用 fcntl 函數(shù),下一節(jié)將對(duì)該函數(shù)進(jìn)行說(shuō)明。

    實(shí)際上,調(diào)用:dup( filedes ) ; 等效于:fcntl (filedes , F_DUPFD, 0);而調(diào)用:dup2(filedes, filedes2); 等效于:close ( filedes2 ) ;fcntl(filedes, F_DUPFD, filedes2);

    在上面的第二種情況下,dup2并不完全等同于close加上fcntl。它們之間的區(qū)別是:

  • ?dup2是一個(gè)原子操作,而close及fcntl則包括兩個(gè)函數(shù)調(diào)用。有可能在close和fcntl之間插入執(zhí)行信號(hào)捕獲函數(shù),它可能修改文件描述符。(第10章將說(shuō)明信號(hào)。)
  • ?在dup2和fcntl之間有某些不同的errno。
  • 示例代碼:

    #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <string.h>int main(void) {int fd, save_fd;char msg[] = "It's a test!\n";fd = open("file1", O_RDWR|O_CREAT, 0644); if(fd < 0){perror("open error");exit(1);}printf("------>fd = %d\n", fd); //新打開(kāi)的文件描述符是3,里面保存指向feil1文件的指針save_fd = dup(STDOUT_FILENO); //把文件描述符1所保存的stdout指針復(fù)制給文件描述符save_fdprintf("save_fd = %d\n", save_fd); //save_fd是文件描述符4,里面保存指向stdout的文件指針write(save_fd, msg, strlen(msg)); //向save_fd寫(xiě),既是向stdout寫(xiě),會(huì)寫(xiě)到屏幕//將fd(3)保存的指向file1的文件指針復(fù)制給STDOUT_FILENO(1),并覆蓋1原來(lái)保存的文件指針int ret = dup2(fd, STDOUT_FILENO); //結(jié)果是fd指向file1文件,STDOUT_FILENO(1)也指向file1文件printf(" -------> m = %d\n", ret); //printf默認(rèn)對(duì)應(yīng)文件描述符1,但是現(xiàn)在1指向file1文件close(fd); //fd(3)被關(guān)閉puts(msg); return 0; }

    dup2 示例代碼:

    #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <string.h>int main(void) {int fd, save_fd;char msg[] = "It's just a test for dup2!\n";fd = open("test", O_RDWR|O_CREAT|O_TRUNC, 0644); //<fcntl.h>if(fd < 0){perror("open error");exit(1);}save_fd = dup(STDOUT_FILENO); //STDOUT_FILENO <unistd.h>printf("save_fd = %d\n", save_fd); #if 0dup2(STDOUT_FILENO, fd);write(fd, msg, strlen(msg)); #elsedup2(fd, STDOUT_FILENO);puts(msg); write(fd, msg, strlen(msg));//??? #endifclose(fd);return 0; }

    示例代碼:

    /**如果使用dup2給一個(gè)文件制定了兩個(gè)描述符的時(shí)候*一個(gè)文件描述符關(guān)閉,依然能使用dup2的新文件描述符對(duì)該文件讀寫(xiě)*/ #include <unistd.h> #include <fcntl.h> #include <stdlib.h> #include <string.h> #include <stdio.h>int main(void) {int fd, fd2;char *str = "use fd write in\n";char *str2 = "use ====fd2==== write\n";fd = open("test", O_WRONLY|O_TRUNC|O_CREAT, 0644);if(fd < 0){perror("open test error");exit(1);}fd2 = open("test", O_WRONLY);dup2(fd, fd2);write(fd, str, strlen(str));close(fd);printf("----------------done close(fd)--------------\n");int ret = write(fd2, str2, strlen(str2));if(ret == -1){perror("write fd2 error");exit(1);}close(fd2);return 0; }

    示例代碼:

    #include <unistd.h> #include <fcntl.h> #include <stdlib.h> #include <string.h> #include <stdio.h>int main(void) {int fd;char *str = "hello dup2\n";//write(STDOUT_FILENO, str, strlen(str));fd = open("test", O_WRONLY|O_TRUNC|O_CREAT, 0644);if(fd < 0){perror("open test1 error");exit(1);}//dup2(STDOUT_FILENO, fd); dup2(fd, STDOUT_FILENO);close(fd);//做文件關(guān)閉之前同樣的事。//int n = write(STDOUT_FILENO, str, strlen(str)); int n = write(fd, str, strlen(str)); printf("--------|%d\n", n);return 0; }

    代碼:

    /*編程程序,要求程序執(zhí)行效果等同于命令 cat file1 - file2 > out 執(zhí)行效果。 注:Linux 系統(tǒng)下, Ctrl+d 可輸出一個(gè)文件結(jié)束標(biāo)記 EOF。 */#include <unistd.h> #include <fcntl.h> #include <stdlib.h> #include <string.h> #include <stdio.h>void sys_err(int fd, char *err_name) {if(fd < 0){perror(err_name);exit(1);} }int main(void) {int fd_f1, fd_f2, fd_out;int ret;char buf[1024];fd_f1 = open("file1", O_RDONLY);sys_err(fd_f1, "open file1 error");fd_f2 = open("file2", O_RDONLY);sys_err(fd_f2, "open file2 error");fd_out = open("out", O_WRONLY|O_TRUNC|O_CREAT, 0644);sys_err(fd_out, "open out error");dup2(fd_out, STDOUT_FILENO);while ((ret = read(fd_f1, buf, sizeof(buf)))) {write(fd_out, buf, ret);}while ((ret = read(STDIN_FILENO, buf, sizeof(buf)))) {write(fd_out, buf, ret);}while ((ret = read(fd_f2, buf, sizeof(buf)))) {write(fd_out, buf, ret);}close(fd_f1);close(fd_f2);close(fd_out);return 0; }


    fcntl 函數(shù)

    fcntl 可以改變一個(gè)已打開(kāi)的文件的屬性,可以重新設(shè)置讀、寫(xiě)、追加、非阻塞等標(biāo)志(這些標(biāo)志稱(chēng)為File Status Flag),而不必重新open文件

    #include <unistd.h> #include <fcntl.h> int fcntl(int fd, int cmd, ... /* arg */ );int fcntl(int fd, int cmd); int fcntl(int fd, int cmd, long arg); int fcntl(int fd, int cmd, struct flock *lock); 獲取和設(shè)置文件的訪問(wèn)控制屬性 參數(shù)解析:第一個(gè)為已經(jīng)打開(kāi)的文件描述符第二個(gè)為要對(duì)文件描述采取的動(dòng)作 F_DUPFD 復(fù)制一個(gè)文件描述,返回值為新描述符。F_GETFD/F_SETFD 目前只有FD_CLOEXEC一個(gè),set時(shí)候會(huì)用到第三個(gè)參數(shù)。 F_GETFL / F_SETFL 得到或者設(shè)置目前的文件描述符屬性,返回值為當(dāng)前屬性。設(shè)置時(shí)使用第三個(gè)參數(shù)。在本節(jié)的各實(shí)例中,第三個(gè)參數(shù)總是一個(gè)整數(shù),與上面所示函數(shù)原型中的注釋部分相對(duì)應(yīng)。 但在說(shuō)明記錄鎖時(shí),第三個(gè)參數(shù)則是指向一個(gè)結(jié)構(gòu)的指針。 fcntl函數(shù)有五種功能:?復(fù)制一個(gè)現(xiàn)存的描述符(cmd=F_DUPFD)。?獲得/設(shè)置文件描述符標(biāo)記(cmd=F_GETFD或F_SETFD)。?獲得/設(shè)置文件狀態(tài)標(biāo)志(cmd=F_GETFL或F_SETFL)。?獲得/設(shè)置異步I/O有權(quán)(cmd=F_GETOWN或F_SETOWN)。?獲得/設(shè)置記錄鎖(cmd=F_GETLK,F_SETLK或F_SETLKW)。 我們先說(shuō)明這十種命令值中的前七種(后三種都與記錄鎖有關(guān),當(dāng)講解記錄鎖時(shí)說(shuō)明) 將涉及與進(jìn)程表項(xiàng)中各文件描述符相關(guān)聯(lián)的文件描述符標(biāo)志,以及每個(gè)文件表項(xiàng)中的文件狀態(tài)標(biāo)志,

    這個(gè)函數(shù)和open一樣,也是用可變參數(shù)實(shí)現(xiàn)的,可變參數(shù)的類(lèi)型和個(gè)數(shù)取決于前面的cmd參數(shù)。下面的例子使用F_GETFL和F_SETFL這兩種fcntl命令改變STDIN_FILENO的屬性,加上O_NONBLOCK選項(xiàng),實(shí)現(xiàn)和 “非阻塞讀終端” 同樣的功能。

    簡(jiǎn)單使用:

    1、獲取文件的flags,即open函數(shù)的第二個(gè)參數(shù):flags = fcntl(fd,F_GETFL,0);2、設(shè)置文件的flags:fcntl(fd,F_SETFL,flags);3、增加文件的某個(gè)flags,比如文件是阻塞的,想設(shè)置成非阻塞:flags = fcntl(fd,F_GETFL,0);flags |= O_NONBLOCK;fcntl(fd,F_SETFL,flags);4、取消文件的某個(gè)flags,比如文件是非阻塞的,想設(shè)置成為阻塞:flags = fcntl(fd,F_GETFL,0);flags &= ~O_NONBLOCK;fcntl(fd,F_SETFL,flags);

    用fcntl改變File Status Flag

    #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <stdio.h> #include <stdlib.h>#define N 1024int main(void) {int flags, n;char buf[N];flags = fcntl(STDIN_FILENO, F_GETFL);flags |= O_NONBLOCK;fcntl(STDIN_FILENO, F_SETFL, flags);again:n = read(STDIN_FILENO, buf, N);if(n == -1){if(errno == EWOULDBLOCK) // errno == EAGAIN(非阻塞讀終端){ printf("no data...\n");sleep(3);goto again;}else {perror("read error");exit(1);}}write(STDOUT_FILENO, buf, n);return 0; }

    或者?

    #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h>#define MSG_TRY "try again\n"int main(void) {char buf[10];int flags, n;flags = fcntl(STDIN_FILENO, F_GETFL);if(flags == -1){perror("fcntl error");exit(1);}flags |= O_NONBLOCK;int ret = fcntl(STDIN_FILENO, F_SETFL, flags);if(ret == -1){perror("fcntl error");exit(1);}tryagain:n = read(STDIN_FILENO, buf, 10);if(n < 0){if(errno != EAGAIN){ perror("read /dev/tty");exit(1);}sleep(3);write(STDOUT_FILENO, MSG_TRY, strlen(MSG_TRY));goto tryagain;}write(STDOUT_FILENO, buf, n);return 0; }

    示例程序2:

    //獲取和設(shè)置文件flags舉例#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <error.h>char buf[500000];int main(int argc,char *argv[]) {int ntowrite,nwrite;const char *ptr ;int flags;ntowrite = read(STDIN_FILENO,buf,sizeof(buf));if(ntowrite <0) { perror("read STDIN_FILENO fail:");exit(1);} fprintf(stderr, "read %d bytes\n", ntowrite);if((flags = fcntl(STDOUT_FILENO,F_GETFL,0))==-1){ perror("fcntl F_GETFL fail:");exit(1);} flags |= O_NONBLOCK;if(fcntl(STDOUT_FILENO,F_SETFL,flags)==-1){ perror("fcntl F_SETFL fail:");exit(1);} ptr = buf;while(ntowrite > 0){ nwrite = write(STDOUT_FILENO,ptr,ntowrite);if(nwrite == -1) { perror("write file fail:");} if(nwrite > 0){ ptr += nwrite;ntowrite -= nwrite;} } flags &= ~O_NONBLOCK;if(fcntl(STDOUT_FILENO,F_SETFL,flags)==-1){ perror("fcntl F_SETFL fail2:");} return 0; }


    sync函數(shù)




    #include <unistd.h> int fsync(int filedes) //把指定文件的數(shù)據(jù)和屬性寫(xiě)入到磁盤(pán)。 int fdatasync(int filedes) //把指定文件的數(shù)據(jù)部分寫(xiě)到磁盤(pán)。 void sync(void) //把修改部分排入磁盤(pán)寫(xiě)隊(duì)列,但并不意味著已經(jīng)寫(xiě)入磁盤(pán)。


    ioctl 函數(shù)

    ioctl 函數(shù)是 I/O 操作的雜物箱。不能用本章中其他函數(shù)表示的 I/O 操作通常都能用 ioctl 表示。終端 I/O是 ioctl 的最大使用方面

    #include <sys/ioctl.h> int ioctl(int fd, unsigned long request, ...); // 獲取和設(shè)置文件特有的物理屬性fd 是某個(gè)設(shè)備的文件描述符。 request 是ioctl的命令,可變參數(shù)取決于request,通常是一個(gè)指向變量或結(jié)構(gòu)體的指針。 若出錯(cuò)則返回-1,若成功則返回其他值,返回值也是取決于request。

    ioctl用于向設(shè)備發(fā)控制和配置命令,有些命令也需要讀寫(xiě)一些數(shù)據(jù),但這些數(shù)據(jù)是不能用read/write讀寫(xiě)的,稱(chēng)為Out-of-band數(shù)據(jù)。也就是說(shuō),read/write讀寫(xiě)的數(shù)據(jù)是in-band數(shù)據(jù),是I/O操作的主體,而ioctl命令傳送的是控制信息,其中的數(shù)據(jù)是輔助的數(shù)據(jù)。例如,在串口線上收發(fā)數(shù)據(jù)通過(guò)read/write操作,而串口的波特率、校驗(yàn)位、停止位通過(guò)ioctl設(shè)置,A/D轉(zhuǎn)換的結(jié)果通過(guò)read讀取,而A/D轉(zhuǎn)換的精度和工作頻率通過(guò)ioctl設(shè)置。

    以下程序使用TIOCGWINSZ命令獲得終端設(shè)備的窗口大小。

    #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/ioctl.h>int main(void) {struct winsize size;if (isatty(STDOUT_FILENO) == 0)exit(1);if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &size)<0) {perror("ioctl TIOCGWINSZ error");exit(1);}printf("%d rows, %d columns\n", size.ws_row, size.ws_col);return 0; }


    /dev/fd

    ? ? ? ? 比較新的系統(tǒng)都提供名為 /dev/fd 的目錄,其目錄項(xiàng)是名為 0、1、2等的文件。打開(kāi)文件 /dev/fd/n 等效于復(fù)制描述符n (假定描述符n是打開(kāi)的)。

    在函數(shù)中調(diào)用:

    ? ? ? ? fd = open("/dev/fd/0", mode);
    大多數(shù)系統(tǒng)忽略所指定的 mode,而另外一些則要求 mode 是所涉及的文件 (在這里則是標(biāo)準(zhǔn)輸入)原先打開(kāi)時(shí)所使用的 mode 的子集。因?yàn)樯厦娴拇蜷_(kāi)等效于:
    ? ? ? ? fd = dup(0);
    描述符 0 和 fd 共享同一文件表項(xiàng)(見(jiàn)圖3 - 3 )。例如,若描述符0被只讀打開(kāi),那么我們也只對(duì) fd 進(jìn)行讀操作。即使系統(tǒng)忽略打開(kāi)方式,并且下列調(diào)用成功:
    ? ? ? ? fd = open("/dev/fd/0", O_RDWR);
    我們?nèi)匀徊荒軐?duì) fd 進(jìn)行寫(xiě)操作。

    ? ? ? ? 我們也可以用/dev/fd作為路徑名參數(shù)調(diào)用creat,或調(diào)用open,并同時(shí)指定O_CREAT。這就允許調(diào)用creat的程序,如果路徑名參數(shù)是/dev/fd/1等仍能工作。
    某些系統(tǒng)提供路徑名/dev/stdin,/dev/stdout和/dev/stderr。這些等效于/dev/fd/0,/dev/fd/1和/dev/fd/2。
    ? ? ? ? /dev/fd文件主要由shell使用,這允許程序以對(duì)待其他路徑名一樣的方式使用路徑名參數(shù)來(lái)處理標(biāo)準(zhǔn)輸入和標(biāo)準(zhǔn)輸出。例如,cat(1)程序?qū)⒚钚兄械囊粋€(gè)單獨(dú)的-特別解釋為一個(gè)輸入文件名,該文件指的是標(biāo)準(zhǔn)輸入。例如:
    ? ? ? ? filterfile2|catfile1-file3|lpr
    首先cat讀file1,接著讀其標(biāo)準(zhǔn)輸入(也就是filterfile2命令的輸出),然后讀file3,如若支持/dev/fd,則可以刪除cat對(duì)-的特殊處理,于是我們就可鍵入下列命令行:
    ? ? ? ? filterfile2|catfile1/dev/fd/0file3|lpr
    在命令行中用-作為一個(gè)參數(shù)特指標(biāo)準(zhǔn)輸入或標(biāo)準(zhǔn)輸出已由很多程序采用。但是這會(huì)帶來(lái)一些問(wèn)題,例如若用-指定第一個(gè)文件,那么它看來(lái)就像開(kāi)始了另一個(gè)命令行的選擇項(xiàng)。/dev/fd則提高了文件名參數(shù)的一致性,也更加清晰。


    最后些一個(gè)測(cè)試程序,希望可以用到里面大多數(shù)函數(shù),用于測(cè)試其功能。這個(gè)程序功能是打開(kāi)一個(gè)文件,在里面寫(xiě)入hello world,然后調(diào)用dup函數(shù)復(fù)制一個(gè)文件描述符,隨后調(diào)用lseek將偏移量設(shè)置到hello之后,最后讀出文件內(nèi)容world打印到終端顯示。代碼如下所示

    #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <fcntl.h> #include <string.h> int main(void) { int fd, fdd, ret; char str[]="hello world!"; char buf[10]; fd = open("file", O_RDWR|O_CREAT|O_TRUNC, 755); if(fd < 0){ perror("open error"); exit(1); } ret = write(fd, str, sizeof(str)); if(ret != sizeof(str)){ perror("write error"); exit(1); } fdd = dup(fd); if(ret == -1){ perror("dup error"); exit(1); } lseek(fdd, 6, SEEK_SET); memset(buf,0,sizeof(buf)); ret = read(fdd, buf, sizeof(buf)); if(ret < 0){ perror("read error"); exit(1); } printf("%s/n",buf); return 0; }


    統(tǒng)計(jì)一個(gè)目錄下普通文件個(gè)數(shù):

    /*編程統(tǒng)計(jì)指定目錄下普通文件個(gè)數(shù)。 包括其子目錄下的普通文件.將文件總數(shù)打印至屏幕。 */#include <unistd.h> #include <string.h> #include <dirent.h> #include <stdio.h> #include <stdlib.h> #include <sys/stat.h>int count(char *root) {DIR *dp;struct dirent *item;int n = 0; char path[1024];dp = opendir(root); //打開(kāi)目錄if (dp == NULL) {perror("----opendir error");exit(1); }//遍歷每一個(gè)目錄項(xiàng),NULL表示讀完while ((item = readdir(dp))) { struct stat statbuf;//排除.目錄和..目錄if (strcmp(item->d_name, ".") == 0 || strcmp(item->d_name, "..") == 0)continue;//將子目錄和當(dāng)前工作目錄拼接成一個(gè)完整文件訪問(wèn)路徑sprintf(path, "%s/%s", root, item->d_name);/*取文件的屬性, lstat防止穿透*/if (lstat(path, &statbuf) == -1) {perror("lstat error");exit(1);}if (S_ISREG(statbuf.st_mode)) {n++;} else if (S_ISDIR(statbuf.st_mode)) {n += count(path);//遞歸調(diào)用該函數(shù)}}closedir(dp);return n; }int main(int argc, char *argv[]) {int total = 0;if (argc == 1) {total = count(".");printf("There are %d files in ./\n", total);} else if (argv[1]) {total = count(argv[1]);printf("There are %d files in %s\n", total, argv[1]);}return 0; }






    總結(jié)

    以上是生活随笔為你收集整理的Linux 文件 IO的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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

    91国内在线视频 | 亚洲精品欧美专区 | 中文字幕在线观看av | 国产高清在线免费 | 中文字幕在线一区二区三区 | 天天操天天摸天天爽 | 色综合天天综合在线视频 | 国产精品欧美久久久久三级 | 中文字幕网站 | 97视频免费观看 | 成x99人av在线www | 久草免费在线观看 | free,性欧美| 国产91成人在在线播放 | www天天干 | 欧美日韩综合在线观看 | 国产精品专区在线 | 香蕉网在线播放 | 久久视频免费在线 | 欧美一级电影免费观看 | 久久久久久久毛片 | 韩国av免费 | 国产视频1区2区3区 久久夜视频 | 蜜桃视频成人在线观看 | 久久久久一区二区三区四区 | 免费看的av片 | 91视频在线网址 | 国产精品免费在线视频 | 91成人免费在线视频 | 成人免费影院 | 国内精品久久久久久久久久久 | 欧美高清视频不卡网 | 久久香蕉电影 | 日日夜夜综合网 | 在线黄色国产电影 | 国产精品一区二区av日韩在线 | 精品久久久久国产免费第一页 | 69人人| 中文字幕免费一区 | 欧美日韩视频一区二区三区 | 欧美二区在线播放 | 在线中文字幕电影 | 久久精品视频日本 | 日韩欧美在线观看一区二区三区 | 中文字幕中文字幕中文字幕 | www.黄色片网站 | 999成人免费视频 | 人人爽人人爽人人爽人人爽 | 色婷婷成人网 | 国产精品久久电影观看 | 亚洲精品色婷婷 | 黄色特级毛片 | 国产精品久久久久久久久久久久 | 日韩v在线 | 色综合天天射 | 免费a视频在线观看 | 欧美精品久久久久久久久久久 | 天天综合久久综合 | 四虎www| 国产精品18久久久久久久久久久久 | 欧美成人999 | 亚洲老妇xxxxxx | av大全在线观看 | 欧美一区二区三区在线 | 国产精品 视频 | 免费在线黄 | 精品自拍sae8—视频 | 最新中文字幕在线观看视频 | 国产视频精品在线 | 精品一区二区三区久久久 | 亚洲综合在线五月天 | 在线看片中文字幕 | 在线观看网站黄 | 在线精品视频免费播放 | 亚洲视频免费在线观看 | 91亚洲精品视频 | 一区二区三区免费在线播放 | 久操久 | 国产又粗又猛又爽又黄的视频先 | 免费视频一二三区 | 免费看一级片 | 人人狠狠综合久久亚洲 | 精品一区二区久久久久久久网站 | 国产一区免费看 | 成人日韩av| 玖玖玖国产精品 | 久久国产热视频 | 五月天丁香亚洲 | 欧美极品xxx | 日本久久精品 | 日韩大片在线观看 | 99热播精品 | 2018好看的中文在线观看 | 久久国产精品视频免费看 | 国产97av| 色婷婷激情五月 | 国产成人精品网站 | 超碰99在线 | 久久草在线免费 | 在线视频日韩一区 | 中文字幕资源在线观看 | 青春草免费视频 | 久久夜夜爽 | 日韩中文免费视频 | 久久视频在线观看中文字幕 | 中文字幕在线看视频国产 | 十八岁以下禁止观看的1000个网站 | 久久99精品国产99久久6尤 | 欧美激情精品一区 | 少妇资源站 | 日韩电影在线观看一区 | 四虎国产 | 2021国产视频 | 久草视频在 | 中文字幕av专区 | 在线视频一二区 | 97香蕉久久国产在线观看 | 三级午夜片 | 久久人人看 | 日韩网站免费观看 | 亚洲精品小区久久久久久 | 精品免费久久久久久 | 精品一区在线看 | 亚洲免费小视频 | 91视频91蝌蚪 | 天天爽人人爽 | 91精品国产综合久久久久久久 | 日韩中文字幕亚洲一区二区va在线 | 国产999免费视频 | 午夜久久久久久久久久久 | 91.麻豆视频 | 亚洲高清精品在线 | 国产日韩欧美在线影视 | 99re8这里有精品热视频免费 | 久久久精品视频网站 | 黄色日批网站 | 三级黄在线 | 欧美三人交 | 久久大片 | 久久久精品网 | 久久人人爽 | 国产视频精品在线 | 久久精品首页 | 国产不卡一区二区视频 | 欧美一级片免费观看 | 三级黄在线 | 91免费的视频在线播放 | 欧美在线观看视频一区二区 | 国产精品一区二区你懂的 | 成人91在线观看 | 欧美精品一区在线 | 国产又粗又硬又爽的视频 | 蜜臀av免费一区二区三区 | 菠萝菠萝在线精品视频 | 免费麻豆| 欧美日韩伦理一区 | 91麻豆免费版 | 日日操天天操夜夜操 | 人人讲| 欧美在线观看小视频 | 国产99一区 | 中文在线a√在线 | 欧美一区三区四区 | 国产成人专区 | 亚洲成人中文在线 | 欧美在线aaa | 狠狠狠狠狠干 | 国产中文欧美日韩在线 | 免费能看的av | 麻豆传媒在线免费看 | 在线性视频日韩欧美 | 亚洲欧美综合 | 91精品国产综合久久久久久久 | 亚洲免费婷婷 | 国内精品久久久久 | 欧美aaaxxxx做受视频 | 免费观看成年人视频 | 欧美日韩在线播放 | 久久精品人人做人人综合老师 | 91精品影视 | 91精品国产自产老师啪 | 久久高清 | 日韩午夜电影网 | 国产福利av在线 | 欧美一区二区伦理片 | 91精品久久久久久综合五月天 | 97超碰人人澡 | 波多野结依在线观看 | 97精品国产aⅴ | 丁香久久激情 | 免费看国产a | 久久午夜国产精品 | 中文字幕第 | 国产精品成人久久久久久久 | 一区中文字幕 | 亚洲黄色大片 | 九色porny真实丨国产18 | 日韩精品一区二区三区免费观看视频 | 久久一区二区免费视频 | 国产精品毛片网 | 久久99国产精品久久 | 亚洲欧美在线观看视频 | 伊人色播 | 国产中文在线视频 | 亚洲综合日韩在线 | 激情欧美一区二区三区免费看 | 不卡电影一区二区三区 | 国产美女搞久久 | 六月色婷 | 国产91免费看 | 成人h电影 | 欧美va电影 | 欧美日韩国产高清视频 | 久黄色| 91爱在线| 日韩网站在线免费观看 | 国产在线观看 | 黄色av一级 | 81国产精品久久久久久久久久 | 婷婷丁香综合 | a在线免费 | 狠狠干狠狠久久 | 天堂在线免费视频 | av成人免费在线看 | 亚洲欧洲国产视频 | 中文字幕在线看人 | av软件在线观看 | 精品亚洲免费 | 九九免费视频 | 天天在线视频色 | av免费网站 | 欧美激情视频一区 | 日本精品久久久一区二区三区 | www蜜桃视频 | 免费看国产一级片 | 欧美在线视频不卡 | 国产精品久久久久久久久毛片 | 色婷婷在线观看视频 | 精品久久网| 国产视频二区三区 | 亚洲成a人片77777潘金莲 | 国产精品av在线 | 日日夜夜天天综合 | 手机看片久久 | 黄色av网站在线观看免费 | 天天超碰 | 午夜精品视频一区二区三区在线看 | 成人精品视频 | 天天干夜夜 | 亚洲每日更新 | 欧美日韩不卡在线视频 | 五月天婷婷在线播放 | 国产在线观看免费 | 麻豆影视在线免费观看 | 欧美一级黄色网 | 在线免费av电影 | 久久免费看av | av中文在线观看 | 日韩av区| 丁香六月在线 | 国产美女在线精品免费观看 | 欧美一级性 | 五月婷婷六月丁香激情 | 97超碰超碰 | 免费精品人在线二线三线 | 久久福利精品 | 久久成人精品电影 | 日韩特黄av | 国产精品久久99综合免费观看尤物 | 国精产品999国精产品视频 | 久久久激情视频 | 中文字幕亚洲欧美日韩2019 | 九九九国产| 欧美日韩国产一区二 | 一级免费看视频 | 欧美美女一级片 | 久久 一区 | 黄色三级网站在线观看 | 免费av观看 | 国产精品一区二区久久 | 在线观看91久久久久久 | 久久久亚洲国产精品麻豆综合天堂 | 国内精品在线观看视频 | 国产黄色片免费观看 | 亚洲精品视频观看 | 天天天天天天天天操 | 婷婷丁香久久五月婷婷 | 综合网欧美 | 国产又黄又爽无遮挡 | 久久精品女人毛片国产 | 免费www视频 | 色窝资源 | 69绿帽绿奴3pvideos | 91免费在线 | 911精品视频 | 欧美在线观看禁18 | 另类五月激情 | 久久96国产精品久久99软件 | 成人宗合网 | 免费看国产视频 | 日韩欧美区 | 国产成人精品区 | 国产精品扒开做爽爽的视频 | 久久久这里有精品 | 久久久久久久久久久综合 | 亚洲一区久久 | 91香蕉视频 mp4| 亚州精品成人 | 日本精品午夜 | 一区二区中文字幕在线播放 | 色婷婷中文| 中文国产字幕 | 日韩成人av在线 | 91麻豆精品国产自产在线游戏 | 精品一区二区三区四区在线 | 美国人与动物xxxx | 中文字幕在线观看一区二区三区 | 黄色一级在线视频 | 精品久久久免费 | 99久精品 | www黄com| 天天色中文 | www.五月婷婷 | 欧美色精品天天在线观看视频 | 人人爽人人爽 | 国产色在线观看 | 91成人小视频 | 一区二区视频欧美 | 日日色综合 | 久久视讯 | av一区二区在线观看中文字幕 | 日本精品视频在线播放 | 97小视频 | 97电影在线看视频 | 黄色免费高清视频 | 国产在线精品一区 | 精品国产一区二区三区久久久蜜臀 | 日韩av手机在线观看 | 久久精品国产99国产 | 国产 日韩 在线 亚洲 字幕 中文 | 蜜臀av免费一区二区三区 | 国产一区视频在线 | 最近免费中文字幕 | 午夜久久电影网 | 夜夜躁日日躁狠狠久久av | 97色在线观看免费视频 | 国产精品久久久久久久久久东京 | 国产精品99精品久久免费 | 婷婷六月丁香激情 | 久久精品三级 | 日本最新中文字幕 | 2021国产精品 | 国产精品国产三级国产不产一地 | 欧美a级在线 | 成人久久18免费网站图片 | av中文字幕免费在线观看 | 日韩精品一区二区三区免费观看视频 | 99视频在线免费 | 91av视频免费观看 | 国产精品永久久久久久久久久 | 色视频 在线 | 国产精品中文久久久久久久 | 久久手机免费观看 | 91在线视频观看免费 | 免费高清在线观看电视网站 | av成人免费网站 | 一级一片免费看 | 欧美性生活小视频 | 中文字幕精品三级久久久 | 97超碰中文 | 国内亚洲精品 | 91精选在线观看 | 在线成人中文字幕 | 色综合网 | 日韩免费视频网站 | 久久精品国产精品亚洲精品 | 欧美精品首页 | 麻豆免费观看视频 | 日韩亚洲在线视频 | 日韩高清一二三区 | 久久九九精品 | 97天堂网 | 日av免费 | 综合亚洲视频 | 亚洲v欧美v国产v在线观看 | 黄色av电影| 一区二区三区精品久久久 | 中文字幕在线观看一区二区三区 | 国产成人久久精品77777综合 | 免费看色的网站 | 欧美亚洲国产一卡 | 欧美性网站 | 亚洲精品99久久久久中文字幕 | 中文字幕在线看视频 | 免费不卡中文字幕视频 | 久久久久久国产精品久久 | 悠悠av资源片 | av福利第一导航 | 黄色的视频网站 | 亚洲国产成人精品久久 | 久久免费视频这里只有精品 | 日韩在线三级 | 免费看高清毛片 | 亚洲视频播放 | 青青久草在线 | 日韩免费看 | 麻豆小视频在线观看 | 亚洲国产精品免费 | 在线观看免费视频 | 日韩高清一区二区 | 中文字幕一区二区三区久久蜜桃 | 精品国产亚洲一区二区麻豆 | 在线播放国产一区二区三区 | 日韩精品综合在线 | 精品一区电影国产 | 日韩特级片 | 四虎影视成人永久免费观看亚洲欧美 | 91色偷偷| 国产三级午夜理伦三级 | 国内精品久久久久久久久久久 | 久久手机视频 | 亚洲高清色综合 | 91综合久久一区二区 | 日韩成人在线免费观看 | 久久久电影网站 | 国产在线观看国语版免费 | 国产人成看黄久久久久久久久 | 久久视频在线看 | 激情五月在线 | 在线v| 日韩久久一区二区 | 亚洲人av免费网站 | 国产亚洲成av人片在线观看桃 | 国产手机在线播放 | 96超碰在线 | 久久久穴 | 高清美女视频 | 成人av免费在线 | 日韩精品第一区 | 久久精品亚洲 | 色播亚洲婷婷 | 波多野结衣在线观看一区二区三区 | 国产91在线播放 | 午夜av免费| 成人免费在线播放 | 精品国产亚洲一区二区麻豆 | 亚洲精区二区三区四区麻豆 | 美女网站色免费 | 超级碰碰视频 | 婷婷久久五月 | 国产精品永久免费观看 | 韩国精品一区二区三区六区色诱 | 欧美成人影音 | 国产香蕉视频 | 日韩欧美在线视频一区二区三区 | 色网址99 | 久久亚洲欧美 | 国产精品久久在线观看 | 91最新视频 | 激情五月婷婷激情 | 四虎影视8848aamm| 中文字幕在线观看播放 | 国产精品精品国产色婷婷 | 国产精品久久久久久超碰 | 51久久夜色精品国产麻豆 | 99久久精品免费看国产一区二区三区 | 精品一区二区影视 | 亚洲精品视频网站在线观看 | 日韩视频免费 | 色婷婷激情电影 | 亚洲国产精品99久久久久久久久 | 狠狠躁日日躁狂躁夜夜躁 | 手机看国产毛片 | 欧美日韩二区在线 | 久久激情五月激情 | 色香蕉在线视频 | 久久成人高清视频 | 久草在线免费在线观看 | 国内精品免费 | 九九视频免费在线观看 | 操操操夜夜操 | 天天操天天色天天射 | 99c视频高清免费观看 | 91大神精品视频在线观看 | www免费在线观看 | 国产免费高清 | 精品亚洲成人 | 亚洲片在线观看 | 在线观看成人小视频 | 中文字幕亚洲情99在线 | 日韩一级成人av | 国产免费黄视频在线观看 | 久久免费视频3 | 久久久久久久久久免费 | 色爱区综合激月婷婷 | 国产精品久久久久亚洲影视 | av黄色成人 | av性在线| 国产小视频网站 | 青青河边草免费视频 | 免费看片在线观看 | 久久99精品视频 | 中文字幕av影院 | 热久久国产精品 | 99久久精品一区二区成人 | 日韩网站在线看片你懂的 | 精品久久久久免费极品大片 | 色网站黄| 视频一区二区视频 | 欧美超碰在线 | 国产一级二级在线 | 亚洲黄色片一级 | 国产手机视频在线播放 | 久久久91精品国产一区二区三区 | 91精品在线免费观看 | 五月黄色 | 又黄又爽又无遮挡免费的网站 | 在线性视频日韩欧美 | 欧美日韩二区三区 | 成人国产精品入口 | 免费精品视频在线 | 日韩羞羞| 一二区精品| 91视频午夜 | www.色就是色 | 久久午夜色播影院免费高清 | 亚洲国产中文字幕 | 久久免费视频99 | 亚洲午夜av | 国产精品久久久久久久久软件 | 最近能播放的中文字幕 | 国产.精品.日韩.另类.中文.在线.播放 | 亚洲精品乱码久久久久久蜜桃欧美 | 欧美日韩一区二区三区在线免费观看 | 天堂av免费看 | 久久久久国产精品厨房 | 一区二区三区在线电影 | 日韩欧美在线免费观看 | 免费在线成人 | 毛片888| 久久毛片网 | 久久国产精品免费一区 | 日韩在线电影一区 | 91成人网在线观看 | av色图天堂网 | 免费精品视频在线 | 婷婷激情五月 | 美女久久久久久久 | 日本少妇视频 | 日韩av在线网站 | 91成人免费观看视频 | 国产91亚洲精品 | 五月天精品视频 | 国产精品久久在线观看 | 国产伦精品一区二区三区高清 | 狠狠操夜夜 | 亚洲视频分类 | 国产美女视频 | 综合精品在线 | 91精品视频免费看 | 中文字幕av最新更新 | 四虎影视久久久 | 日韩精品久久中文字幕 | 五月天激情电影 | 亚洲精品视频在线播放 | 亚洲精品高清视频 | 91在线视频免费播放 | 天天操天天舔天天爽 | 日韩在线电影 | 欧美成人区 | 在线超碰av| 伊人婷婷激情 | 成年人免费看av | 懂色av一区二区在线播放 | 国产精品精品国产 | 日本成人黄色片 | zzijzzij日本成熟少妇 | 欧美 日韩精品 | 精品视频在线视频 | 国产一区二区三区在线免费观看 | 狠狠狠狠狠狠操 | 福利片免费看 | 亚洲在线视频免费 | 久久综合九色综合久99 | 国产69精品久久99的直播节目 | 久久精品国产免费 | 亚洲精品视频免费观看 | 婷婷视频 | 五月天婷婷在线视频 | 午夜丁香视频在线观看 | 久久香蕉电影 | 97av视频| 亚洲一区二区三区毛片 | 日日干美女 | 中文字幕av日韩 | av视屏在线 | wwwwwww色| 天天操天天操天天操天天操天天操 | 日韩av在线看| 91成熟丰满女人少妇 | 国产精品嫩草69影院 | 在线观看一级片 | 久草视频在线资源 | 国产亚洲视频在线免费观看 | 伊人五月天.com | 久久成 | 久久婷婷国产色一区二区三区 | 国产成人久久精品77777综合 | 99电影| 国产精品 中文在线 | 久久夜夜爽 | 99精品国产福利在线观看免费 | 免费视频久久 | 久久99精品久久只有精品 | 午夜精品婷婷 | 国产免费叼嘿网站免费 | 精品国产一区二区三区四区在线观看 | 激情婷婷av | 黄色视屏免费在线观看 | 亚洲精品视频在线播放 | 中文字幕在线观看一区 | 国产91在线看| 国产免费又黄又爽 | 九九色综合 | 日韩精品aaa | 日韩欧美精品免费 | 亚洲精品男人天堂 | 日韩精品一区二区三区中文字幕 | 亚洲国产精品资源 | av电影不卡 | 日韩精品短视频 | 69国产盗摄一区二区三区五区 | av资源免费观看 | 精品久久一区 | 国产精久久久久久妇女av | 97韩国电影 | 久久91久久久久麻豆精品 | 国产亚洲视频中文字幕视频 | 久久天天躁狠狠躁夜夜不卡公司 | 少妇av片 | 亚洲精品国产综合久久 | 国产麻豆视频网站 | 国产成人精品av在线观 | 色窝资源 | 国产一区二区三区高清播放 | 在线精品视频在线观看高清 | 国产欧美精品一区二区三区 | 日本激情视频中文字幕 | 日韩免费一区二区三区 | 97超碰在线免费观看 | 99久久精品免费看国产免费软件 | 国产香蕉97碰碰碰视频在线观看 | 免费观看日韩av | 国产精品一区二区美女视频免费看 | 欧美久久久久久久久 | 叶爱av在线 | 中文不卡视频在线 | 91看片淫黄大片在线播放 | 午夜美女福利直播 | 9在线观看免费高清完整 | 久久国产手机看片 | av免费看看 | 欧美激情第一页xxx 午夜性福利 | 天天操偷偷干 | 国内精品二区 | 在线视频欧美精品 | 中文字幕 国产视频 | 免费看污污视频的网站 | 综合色播 | 国产一区二区在线播放视频 | 亚洲精品ww | 久久精品久久久久电影 | 久久久99国产精品免费 | 亚洲六月丁香色婷婷综合久久 | 毛片无卡免费无播放器 | 欧美一级久久 | 免费看搞黄视频网站 | 在线视频成人 | 欧美久久久一区二区三区 | 色在线最新| 国产精品久久久久久久久久ktv | 国产资源在线观看 | 五月综合激情网 | 欧洲激情综合 | 在线观看av网站 | 日韩高清免费观看 | 日韩电影一区二区三区 | 国产精品成人一区二区 | 欧美精品久久久久久久久老牛影院 | 亚洲美女在线国产 | 91久久久久久国产精品 | 天天色天天射天天综合网 | 国产精品免费久久久久久 | 日本中文字幕在线 | 在线播放你懂 | 欧美日韩99 | 日韩精品久久久 | 国产999免费视频 | 婷婷久操 | 国产一级片直播 | 91视频久久久久 | 婷婷综合亚洲 | 天天干天天操天天入 | 亚洲成人一二三 | 日韩欧美电影网 | 九九热在线观看 | 国产精品igao视频网网址 | 香蕉免费| 成人在线黄色 | 亚洲一一在线 | 午夜久久电影网 | 婷婷六月中文字幕 | 91视频免费播放 | 91精品啪在线观看国产81旧版 | 99人久久精品视频最新地址 | 91成人蝌蚪 | 中文字幕电影高清在线观看 | 波多野结依在线观看 | 亚洲精品国产精品国自产观看 | 在线视频 一区二区 | 丁香资源影视免费观看 | 亚洲国产日本 | 国产精品久久久久久久久久99 | 日韩欧美不卡 | 国产在线中文字幕 | 免费视频久久久 | 欧美性久久久 | 探花视频免费观看 | 国产日韩欧美视频在线观看 | 免费一级黄色 | 日韩精品一区二区三区水蜜桃 | 高清不卡一区二区三区 | 97成人在线观看视频 | 国产97超碰| 欧美在线99 | 91禁在线看 | 国偷自产视频一区二区久 | 激情网五月婷婷 | 五月婷婷六月丁香在线观看 | 国产中文字幕在线免费观看 | 激情喷水 | 日韩精品一区二区三区在线视频 | 日韩三级久久 | 永久av免费在线观看 | 日韩黄色在线电影 | 欧美色综合久久 | 色婷婷福利| 亚洲一级黄色片 | 国产精品丝袜 | 免费观看性生活大片 | 精品国产一区二区三区不卡 | 久久免费国产精品 | 高潮久久久 | 日韩精品视频第一页 | 久艹在线免费观看 | www在线免费观看 | 天天干夜夜夜操天 | 成人国产精品 | 丁香视频在线观看 | 国产高清视频免费在线观看 | 韩国精品一区二区三区六区色诱 | 日韩有码中文字幕在线 | 玖玖视频精品 | 最近免费观看的电影完整版 | 国内久久视频 | 国产成人一区三区 | 日本精品va在线观看 | 亚洲综合成人在线 | 久久精品视频免费 | 久久高清片 | 首页中文字幕 | 久久精品视频在线 | 国产精品毛片一区视频 | 一区二区三区电影 | 亚洲在线视频免费 | 久久久免费看片 | aa级黄色大片 | 高清不卡毛片 | 天天综合网~永久入口 | 亚洲精品国产第一综合99久久 | 亚洲精品午夜久久久 | 一区二区电影在线观看 | 国产精品久久久久久久久久三级 | 天天操天天操天天操 | 中文字幕视频 | 国产精品国产精品 | 综合精品久久 | 国产成人精品999在线观看 | 人人干在线| 中文字幕一区二 | 黄色片网站大全 | 超碰97在线人人 | 精品综合久久 | 四虎影视精品成人 | 激情影音 | 天天天天天操 | 99在线观看视频 | 亚洲欧美在线视频免费 | 精品国产欧美一区二区三区不卡 | 深爱激情综合网 | 日韩婷婷 | 亚洲天天做 | 久久不卡国产精品一区二区 | 激情伊人五月天久久综合 | 美女精品国产 | 精品一区二区免费 | 国产欧美综合视频 | 免费一级毛毛片 | 国产视频观看 | 亚洲高清久久久 | 国产香蕉av | 国产一区二区不卡视频 | av在线h| 国产一卡二卡四卡国 | 亚洲午夜精品一区二区三区电影院 | 免费看污片| 欧美色久 | 午夜精品视频一区二区三区在线看 | 久久99国产视频 | 国产高清久久 | 99在线观看视频网站 | 久久伦理网 | 蜜臀精品久久久久久蜜臀 | 日韩成人在线免费观看 | 国产爽视频 | 蜜桃传媒一区二区 | 久草免费在线视频观看 | 久久久精华网 | 在线看片成人 | 97成人啪啪网 | 黄色福利网站 | av电影亚洲| 精品福利在线视频 | 欧美一区,二区 | 欧美日在线 | 91看片一区二区三区 | 粉嫩av一区二区三区四区在线观看 | 在线观看a视频 | 亚州精品国产 | 最近中文国产在线视频 | 97精品久久 | 国产精品video爽爽爽爽 | 热久在线| 热久久在线视频 | av资源免费在线观看 | 国产精品a成v人在线播放 | 五月天丁香| 日韩欧美高清一区二区三区 | 正在播放国产91 | 亚洲视频精品在线 | 国产亚洲无 | 天天做日日爱夜夜爽 | 久久一二三四 | 日韩免费专区 | 久久国产精品系列 | 成人性生交大片免费看中文网站 | 五月天综合激情 | 青青网视频 | 免费观看国产成人 | 手机av电影在线观看 | 国产三级国产精品国产专区50 | 在线观看成人福利 | 91精品系列| 国产高清专区 | 久国产在线播放 | 亚洲婷婷免费 | 精品一区二区在线免费观看 | 久在线观看视频 | 波多野结衣在线播放一区 | 久久香蕉电影 | 在线观看中文字幕 | 91久久一区二区 | 美女久久精品 | 蜜臀一区二区三区精品免费视频 | 国产高清视频在线观看 | 99精品热视频 | 久久五月婷婷丁香社区 | 欧美日韩调教 | 国产精品一区二区三区四区在线观看 | 波多野结衣在线观看一区 | 亚洲视频axxx | 成人av.com | www四虎影院| 亚洲高清色综合 | 亚洲一区精品人人爽人人躁 | 99久精品| 综合色久 | 久久午夜影院 | 美女视频是黄的免费观看 | 天天拍天天色 | 久久高视频 | 欧美精品久久久久久久久老牛影院 | 久久精品一区二区三区中文字幕 | 狠狠狠色丁香婷婷综合久久88 | 国产精品美女久久久久久 | 美女视频一区二区 | 亚洲视频在线观看 | 亚洲丁香日韩 | 久久精品国产成人 | 日日夜日日干 | 亚洲黄色av网址 | 操老逼免费视频 | a黄色片在线观看 | 久草视频在线免费看 | 丝袜美腿一区 | 日日干av | 亚洲精品高清视频在线观看 | 亚洲精品白浆高清久久久久久 | 不卡国产在线 | 日av免费| 黄色小说免费在线观看 | 亚洲国产成人av网 | 日韩精品短视频 | 国产美女在线精品免费观看 | 九色精品免费永久在线 | 午夜视频久久久 | 激情网在线观看 | 久久人人97超碰精品888 | 玖玖爱国产在线 | 91av久久| 免费成人黄色 | 狠狠狠狠狠狠狠狠 | 亚洲韩国一区二区三区 | 久草视频在线资源站 | 国产精品3| 欧美日韩国产一区二区三区 | 亚洲视频高清 | 久久99精品久久久久久 | 99久久99久久免费精品蜜臀 | 亚洲日本黄色 | 91九色在线观看视频 | 国产又粗又猛又黄又爽视频 | 天天操天天吃 | 国产美女视频免费观看的网站 | 欧美一区二区三区在线播放 | 日韩欧美在线观看一区二区三区 | 一级淫片在线观看 | 天天射综合 | 欧美日本不卡高清 | 成人在线观看资源 | a√国产免费a| 国产精品av免费 | 欧美日高清视频 | 久久精品视频播放 | 天天色天天爱天天射综合 | 国产亲近乱来精品 | 日本精品一区二区 | 免费视频a| 九九热99视频 | 国产中文字幕av | www.天天射.com| 久精品一区 | 在线精品播放 | 麻花豆传媒mv在线观看 | 激情网五月婷婷 | 日韩成人黄色 | 午夜久久电影网 | 久久久久一区二区三区 | 国产在线精品播放 | 久久日本视频 | 黄色精品久久久 | 狠狠操夜夜操 | 91精品成人久久 | 91成人亚洲| 日韩精品一区二区三区第95 | 欧美一区在线观看视频 | 欧美一区三区四区 | 免费看亚洲毛片 | 九九综合久久 | 四虎成人精品 | 国产毛片久久 | 久操伊人 | 中文在线免费一区三区 | 久久精品8| 婷婷六月天综合 | 亚洲三级网站 | 亚洲激情综合 | 99在线精品视频 | 亚洲国产无 | 91高清视频免费 | av成人黄色| 又黄又刺激的网站 | 日韩r级电影在线观看 | 成人网中文字幕 | www.人人干| 波多野结衣在线观看一区二区三区 | 日韩狠狠操 | 国产高清在线视频 | 精品成人a区在线观看 | 欧美精品久久99 | 国内丰满少妇猛烈精品播放 | 日韩乱码在线 | 免费a v观看 | 丁香九月婷婷 | 日韩av一区二区三区四区 | 黄色的视频| 天天曰夜夜操 | 国产高清在线精品 |