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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

UNIX再学习 -- 文件I/O

發(fā)布時間:2025/3/15 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 UNIX再学习 -- 文件I/O 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

上一篇講完文件描述符,接下來進(jìn)入正題,文件的處理函數(shù)

一、函數(shù) open

詳細(xì)內(nèi)容,可自行 man creat 查看 #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);

1、參數(shù)解析

第一個參數(shù):字符串形式的路徑和文件名 第二個參數(shù):操作標(biāo)志 O_RDONLY 只讀模式 O_WRONLY 只寫模式 O_RDWR 讀寫模式 O_EXEC 只執(zhí)行打開 O_SEARCH 只搜索打開(應(yīng)用于目錄) 上述 5 種標(biāo)志位是互斥的,也就是不可同時使用,但可與下列的標(biāo)志位利用 OR(|) 運算符組合。 O_APPEND:每次寫時追加到文件的尾端。 O_CLOEXEC:把FD_CLOEXEC常量設(shè)置為文件描述符標(biāo)志。 O_CREAT:若此文件不存在則創(chuàng)建它。使用此選項時,open函數(shù)需同時說明第3個參數(shù)mode(openat函數(shù)需說明第4個參數(shù)mode),用mode指定該新文件的訪問權(quán)限位。 O_DIRECTORY:如果path引用的不是目錄,則出錯。 O_EXCL:如果同時指定了O_CREAT,而文件已經(jīng)存在,則出錯。用此可以測試一個文件是否存在,如果不存在,則創(chuàng)建此文件,這使測試和創(chuàng)建兩者稱為一個原子操作。 O_NOCTTY:如果path引用的是終端設(shè)備,則不將該設(shè)備分配作為此進(jìn)程的控制終端。 O_NOFOLLOW:如果path引用的是一個符號鏈接,則出錯。 O_NONBLOCK:如果path引用的是一個FIFO、一個特殊文件或一個字符特殊文件,則此選項為文件的本次打開操作和后序的I/O操作設(shè)置非阻塞方式。 O_SYNC :使每次write等待物理I/O操作完成,包括由該write操作引起的文件屬性更新所需的I/O。 O_TRUNC:如果此文件存在,而且為只讀或讀-寫成功打開,則將其長度截斷為0。 O_TTY_INIT:如果打開一個還未打開的終端設(shè)備,設(shè)置非標(biāo)準(zhǔn)termios參數(shù)值,使其符合Single UNIX Specification(以及POSIX.1)中同步輸入和輸出選項的一部分。 O_DSYNC:使每次write要等待物理I/O操作完成,但是如果該寫操作并不影響讀取剛寫入的數(shù)據(jù),則不需要等待文件屬性被更新。 O_RSYNC:使每一個以文件描述符作為參數(shù)進(jìn)行的read操作等待,直至所有對文件同一部分掛起的寫操作都完成。 第三個參數(shù):操作模式 僅當(dāng)創(chuàng)建新文件時才使用,用于指定創(chuàng)建的新文件權(quán)限。可以使用宏定義或者八進(jìn)制文件權(quán)限碼。 注:此為Linux2.2以后特有的標(biāo)志位,以避免一些系統(tǒng)安全問題。參數(shù)mode 則有下列數(shù)種組合,只有在建立新文件時才會生效,此外真正建文件時的權(quán)限會受到umask值所影響,因此該文件權(quán)限應(yīng)該為(mode-umaks)。

(1)八進(jìn)制文件權(quán)限碼(常用)

詳解參看:C語言再學(xué)習(xí) -- 修改linux文件權(quán)限
# ls -la 總用量 20 drwxrwxr-x 2 tarena tarena 4096 Mar 27 14:44 . drwxrwxr-x 4 tarena tarena 4096 Mar 14 11:14 .. -rwxr-xr-x 1 root root 7158 Mar 27 14:44 a.out -rw-r--r-- 1 root root 79 Mar 27 14:44 test.c 以 test.c 為例: - 代表文件類型 rw 代表屬主 r 代表屬組 r 代表其它 1 代表硬鏈接數(shù) root 代表屬主名稱 root 代表屬組名稱 79 代表文件大小 Mar 27 14:44 代表文件最后修改時間 test.c 代表文件名 按照:0 表示沒有權(quán)限,1 表示可執(zhí)行權(quán)限,2 表示可寫權(quán)限,4 表示可讀權(quán)限,然后將其相加。所以數(shù)字屬性的格式應(yīng)為 3 個從 0 到 7 的八進(jìn)制數(shù),其順序是文件屬主(u)、與文件屬組(g)、其他用戶(o)
因此上面,test.c 的權(quán)限為 0644 注:可以在程序中用八進(jìn)制方式表示數(shù)字必須以 0 作為開頭,采用?%o 作為占位符可以把一個整數(shù)的八進(jìn)制表示方式打印在屏幕上?。

(2)宏定義方式

可查看 /usr/include/linux/stat.h 看到具體定義
S_IRWXU, 00700權(quán)限,代表該文件所有者具有可讀、可寫及可執(zhí)行的權(quán)限。 S_IRUSR 或 S_IREAD, 00400權(quán)限,代表該文件所有者具有可讀取的權(quán)限。 S_IWUSR 或 S_IWRITE,00200權(quán)限,代表該文件所有者具有可寫入的權(quán)限。 S_IXUSR 或 S_IEXEC, 00100權(quán)限,代表該文件所有者具有可執(zhí)行的權(quán)限。S_IRWXG 00070權(quán)限,代表該文件用戶組具有可讀、可寫及可執(zhí)行的權(quán)限。 S_IRGRP 00040權(quán)限,代表該文件用戶組具有可讀的權(quán)限。 S_IWGRP 00020權(quán)限,代表該文件用戶組具有可寫入的權(quán)限。 S_IXGRP 00010權(quán)限,代表該文件用戶組具有可執(zhí)行的權(quán)限。S_IRWX O00007權(quán)限,代表其他用戶具有可讀、可寫及可執(zhí)行的權(quán)限。 S_IROTH 00004權(quán)限,代表其他用戶具有可讀的權(quán)限 S_IWOTH 00002權(quán)限,代表其他用戶具有可寫入的權(quán)限。 S_IXOTH 00001權(quán)限,代表其他用戶具有可執(zhí)行的權(quán)限。同八進(jìn)制方法格式一樣,不過就顯得尤為復(fù)雜了,例如:設(shè)置權(quán)限 0644:S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH

2、返回值:

成功返回一個新的文件描述符,失敗返回 -1。文件描述符就是非負(fù)的整數(shù),用于代表一個打開的文件。

3、錯誤代碼

EEXIST 參數(shù)pathname 所指的文件已存在, 卻使用了O_CREAT 和O_EXCL 旗標(biāo). EACCESS 參數(shù)pathname 所指的文件不符合所要求測試的權(quán)限. EROFS 欲測試寫入權(quán)限的文件存在于只讀文件系統(tǒng)內(nèi). EFAULT 參數(shù)pathname 指針超出可存取內(nèi)存空間. EINVAL 參數(shù)mode 不正確. ENAMETOOLONG 參數(shù) pathname 太長. ENOTDIR 參數(shù)pathname 不是目錄. ENOMEM 核心內(nèi)存不足. ELOOP 參數(shù)pathname 有過多符號連接問題. EIO I/O 存取錯誤.

4、函數(shù)功能

打開/創(chuàng)建 一個文件/設(shè)備。

5、與 openat 函數(shù)區(qū)別

可自行 man openat 查看 openat 的詳細(xì)內(nèi)容,在此不多講解了。openat 函數(shù)是 POSIX.1 最新版本中新增的一類函數(shù)之一,希望解決兩個問題。第一,讓線程可以使用相對路徑名打開目錄中的文件,而不再只能打開當(dāng)前工作目錄。第二,可以避免time-of-check-to-time-of-use(TOCTTOU錯誤

6、與 creat 函數(shù)區(qū)別

調(diào)用creat函數(shù)創(chuàng)建一個新文件。返回值:若成功,返回只寫打開的文件描述符;若出錯,返回-1。此函數(shù)等效于:
open (path, O_RDWR | O_CREAT | O_TRUNC, mode);

二、函數(shù) close

#include <unistd.h> int close(int fd);

1、函數(shù)功能:

close()關(guān)閉一個文件描述符,所以它不再引用任何文件,可以重用。 任何記錄鎖(見fcntl(2))舉行與該進(jìn)程關(guān)聯(lián)并擁有的文件被刪除(不管用于獲取的文件描述符)鎖)。
如果 fd 是引用底層打開文件描述的最后一個文件描述符(見open(2)),則與打開的文件描述被釋放; 如果描述符是使用 unlink(2)文件刪除的文件的最后引用被刪除。

2、示例說明

//open 函數(shù)和 close 函數(shù)的使用 #include <stdio.h> #include <sys/stat.h> #include <sys/types.h> #include <fcntl.h> #include <unistd.h> #include <stdlib.h>int main (void) { //文件不存在則創(chuàng)建,存在則打開 // int fd = open ("a.txt", O_RDONLY | O_CREAT, 0644);//文件不存在則創(chuàng)建,存在則創(chuàng)建失敗 // int fd = open ("a.txt", O_RDONLY | O_CREAT | O_EXCL, 0644);//文件存在,且為普通文件,打開方式有寫權(quán)限,則清空文件 int fd = open ("a.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);if (-1 == fd)perror ("open"), exit (-1);printf ("打開文件成功!\n");printf("fd = %d\n", fd);int res = close (fd);if (-1 == res)perror ("cosee"), exit (-1);printf("關(guān)閉文件成功!\n");return 0; } 輸出結(jié)果: 打開文件成功! fd = 3 關(guān)閉文件成功!

三、函數(shù) lseek

可參看:C語言再學(xué)習(xí) -- 文件 每個打開文件都有一個與其相關(guān)聯(lián)的“當(dāng)前文件偏移量”。它通常是一個非負(fù)數(shù),用以度量從文件開始處計算的字節(jié)數(shù)。通常,讀、寫操作都從當(dāng)前文件偏移量處開始,并使偏移量增加所讀寫的字節(jié)數(shù)。按系統(tǒng)默認(rèn)的情況,當(dāng)打開一個文件時,除非指定 O_APPEND 選項,否則該偏移量被設(shè)置為 0. 可以調(diào)用 lseek 顯式地為一個打開文件設(shè)置偏移量。 #include <sys/types.h> #include <unistd.h> off_t lseek (int fd, off_t offset, int whence);

1、參數(shù)解析

第一個參數(shù):文件描述符 第二個參數(shù):偏移量 第三個參數(shù):從什么地方開始偏移 若whence是SEEK_SET,則將該文件的偏移量設(shè)置為距文件開始處offset個字節(jié)。?
若whence是SEEK_CUR,則將該文件的偏移量設(shè)置為其當(dāng)前值加offset,offset可為正或負(fù)。?
若whence是SEEK_END,則將該文件的偏移量設(shè)置為文件長度加offset,offset可正可負(fù)。

偏移起始位置:文件頭0(SEEK_SET),當(dāng)前位置1(SEEK_CUR),文件尾2(SEEK_END))為基準(zhǔn),偏移offset(指針偏移量)個字節(jié)的位置。

2、返回值

若成功,返回新的文件偏移量;若出錯,返回為 -1。為此可以用下列方式確定打開文件的當(dāng)前偏移量: off_t currpos; currpos = lseek(fd, 0, SEEK_CUR);這種方法也可用來確定所涉及的文件是否可以設(shè)置偏移量。如果文件描述符指向的是一個管道、FIFO或網(wǎng)絡(luò)套接字,則 lseek 返回 -1,并將 errno 設(shè)置為 ESPIPE (Illegal seek)。

3、函數(shù)功能

表示調(diào)整文件的讀寫位置。

4、示例說明

//示例一 #include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <fcntl.h> #include <stdlib.h> #include <sys/stat.h>int main (void) {int fd = open ("a.txt", O_RDWR);if (-1 == fd)perror ("open"), exit (-1);printf ("打開文件成功!\n");printf ("ABCDEFGHIJKLMN\n");char c;//第一次讀 從開頭讀取 Aread (fd, &c, sizeof (char));printf ("c = %c\n", c);//第二次讀,移到下一個 Bread (fd, &c, sizeof (char));printf ("c = %c\n", c);printf ("-------------------\n");//SEEK_CUR 當(dāng)前位置讀取 (2+0 = 2)(CDE)lseek (fd, 2L, SEEK_CUR);read (fd, &c, sizeof (char));printf ("c = %c\n", c);//SEEK_CUR 當(dāng)前位置讀取(-2+0 = -2) (DEF)lseek (fd, -2L, SEEK_CUR);read (fd, &c, sizeof (char));printf ("c = %c\n", c);//SEEK_SET 從開頭位置讀取,(3 + 1 = 4)(ABCD)lseek (fd, 3L, SEEK_SET);read (fd, &c, sizeof (char));printf ("c = %c\n", c);//SEEK_SET 從開頭位置讀取,(-5 + 1 = -4)錯誤,指向當(dāng)前位置lseek (fd, -5L, SEEK_SET);read (fd, &c, sizeof (char));printf ("c = %c\n", c);//從結(jié)尾位置讀取,(-3 + 2 = -1) (MN)lseek (fd, -3L, SEEK_END);read (fd, &c, sizeof (char));printf ("c = %c\n", c);close (fd);printf ("關(guān)閉文件成功!\n");return 0; } 輸出結(jié)果: 打開文件成功! ABCDEFGHIJKLMN c = A c = B ------------------- c = E c = D c = D c = E c = M 關(guān)閉文件成功!//示例二 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int main() {if (lseek (STDIN_FILENO, 0, SEEK_CUR) == -1)printf ("cannot seek\n");else printf ("seek OK\n");return 0; } 使用重定向測試: # ./a.out < /etc/passwd seek OK# cat < /etc/passwd | ./a.out cannot seek# ./a.out < /var/spool/cron/FIFO cannot seek//示例三 #include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <fcntl.h> #include <stdlib.h> #include <sys/stat.h> #include <string.h>int main (void) {int fd = open ("a.txt", O_RDWR | O_APPEND);//nt fd = open ("a.txt", O_RDWR);if (-1 == fd)perror ("open"), exit (-1);printf ("打開文件成功!\n");char c;lseek (fd, 3, SEEK_SET);read (fd, &c, sizeof (char));printf ("c = %c\n", c);char buffer[5] = "1234";if(write(fd,buffer,strlen(buffer)) !=strlen(buffer))perror("write error"), exit(-1);close (fd);return 0; } 查看 a.txt # cat a.txt ABCDEFJHIJKLMN 1234說明: (1)示例一,說明偏移起始位置:文件頭0(SEEK_SET),當(dāng)前位置1(SEEK_CUR),文件尾2(SEEK_END))為基準(zhǔn),偏移offset(指針偏移量)個字節(jié)的位置。lseek()函數(shù)允許將文件偏移量設(shè)置為超出文件結(jié)尾(但不會更改文件的大小)。如果偏移量超出范圍,則打印當(dāng)前位置。 (2)示例二,說明如果文件描述符指向的是一個管道、FIFO或網(wǎng)絡(luò)套接字,則 lseek 返回 -1。比較 lseek 的返回值時,不要測試它是否小于 0,而要測試它是否等于 -1。 (3)示例三,說明按系統(tǒng)默認(rèn)的情況,當(dāng)打開一個文件時,除非指定?O_APPEND?選項,否則該偏移量被設(shè)置為 0。 O_APPEND的含義是在每次寫之前,都講標(biāo)志位移動到文件的末端。而?O_APPEND 打開后,是一個原子操作:移動到末端,寫數(shù)據(jù),跟位移 lseek 無關(guān)。

5、與 fseek 區(qū)別

int fseek(FILE *stream, long offset, int fromwhere); off_t lseek (int fd, off_t offset, int whence);

fseek 函數(shù)和 lseek 函數(shù)類似,但 lseek 返回的是一個 off_t 數(shù)值,而 fseek 返回的是一個整型。一個打開的是文件流指針、一個打開的是文件描述符

6、off_t 類型

查看:/usr/include/i386-linux-gnu/sys/types.h?

#ifndef __off_t_defined # ifndef __USE_FILE_OFFSET64 typedef __off_t off_t; # else typedef __off64_t off_t; # endif # define __off_t_defined #endif如果定義了__USE_FILE_OFFSET64 就把 off_t 定義為 __off64_t ,否則定義為 32 位。

使用 gdb 查看:

編譯gdb文件 # gcc -g test.c# gdb a.out GNU gdb (Ubuntu/Linaro 7.4-2012.02-0ubuntu2) 7.4-2012.02 Copyright (C) 2012 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "i686-linux-gnu". For bug reporting instructions, please see: <http://bugs.launchpad.net/gdb-linaro/>... Reading symbols from /home/tarena/project/c_test/a.out...done. (gdb) ptype off_t type = long int

所以,linux中的 off_t 類型默認(rèn)是 32 位的 long int。

四、函數(shù) read

#include <unistd.h> ssize_t read(int fd, void *buf, size_t count);

1、參數(shù)解析

第一個參數(shù):文件描述符第二個參數(shù):緩沖區(qū)的首地址第三個參數(shù):讀取的數(shù)據(jù)大小

2、返回值

成功返回讀取到的數(shù)據(jù)大小,若已到文件尾,返回 0,失敗返回 -1。
很多種情況可使實際讀到的字節(jié)數(shù)少于要求讀的字節(jié)數(shù):
(1)讀普通文件時,在讀到要求字節(jié)數(shù)之前已經(jīng)到達(dá)了文件尾端。
(2)當(dāng)從終端設(shè)備讀時,通常一次最多讀一行。
(3)當(dāng)從網(wǎng)絡(luò)讀時,網(wǎng)絡(luò)中的緩沖機(jī)制可能造成返回值小于所要求讀的字節(jié)數(shù)。
(4)當(dāng)從管道或FIFO讀時,如若管道包含的字節(jié)少于所需的數(shù)量,那么read將只返回實際可用的字節(jié)數(shù)。
(5)當(dāng)從某些面向記錄的設(shè)別(如磁帶)讀時,一次最多返回一個記錄。
(6)當(dāng)一信號造成中斷,而已經(jīng)讀了部分?jǐn)?shù)據(jù)量時。

讀操作從文件的當(dāng)前偏移量處開始,在成功返回之前,該偏移量將增加實際讀到的字節(jié)數(shù)。

3、函數(shù)功能

表示從指定的文件中讀取指定的數(shù)據(jù)。

4、示例說明

#include <stdio.h> #include <sys/stat.h> #include <sys/types.h> #include <fcntl.h>int main (void) {char buffer[100];int fd = open("a.txt", O_RDWR);lseek (fd, 2L, SEEK_SET);int size = read (fd, buffer, sizeof (buffer));printf ("buffer = %ssize = %d\n", buffer, size);close (fd);return 0; } 輸出結(jié)果: buffer = CDEFJHIJKLMN size = 13 說明:讀操作從文件的當(dāng)前偏移量處開始,在成功返回之前,該偏移量將增加實際讀到的字節(jié)數(shù)。

五、函數(shù) write

#include <unistd.h> ssize_t write(int fd, const void *buf, size_t count);

1、參數(shù)解析

第一個參數(shù):文件描述符第二個參數(shù):緩沖區(qū)首地址第三個參數(shù):數(shù)據(jù)的大小

2、返回值

成功返回寫入的數(shù)據(jù)大小,失敗返回 -1。
其返回值通常與 count 的值相同,否則表示出錯。write 出錯的一個常見原因是磁盤已寫滿,或者超過了一個給定進(jìn)程的文件長度限制對于普通文件,寫操作從文件的當(dāng)前偏移量處開始。如果在打開文件時,指定了O_APPEND選項,則在每次寫操作之前,將文件偏移量設(shè)置在文件的當(dāng)前結(jié)尾處。在一次成功寫之后,該文件偏移量增加實際寫的字節(jié)數(shù)。

3、函數(shù)功能

表示向指定的文件中寫入指定的數(shù)據(jù)

4、示例說明

#include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <fcntl.h> #include <stdlib.h> #include <sys/stat.h> #include <string.h>int main (void) {//int fd = open ("a.txt", O_RDWR | O_APPEND);int fd = open ("a.txt", O_RDWR);if (-1 == fd)perror ("open"), exit (-1);lseek (fd, 3, SEEK_SET);char buffer[5] = "1234";int size = write(fd,buffer,strlen(buffer));printf ("size = %d\n", size);close (fd);return 0; } 輸出結(jié)果: size = 4查看 a.txt # cat a.txt ABC1234HIJKLMN 說明:對于普通文件,寫操作從文件的當(dāng)前偏移量處開始。如果在打開文件時,指定了O_APPEND選項,則在每次寫操作之前,將文件偏移量設(shè)置在文件的當(dāng)前結(jié)尾處。在一次成功寫之后,該文件偏移量增加實際寫的字節(jié)數(shù)。

六、I/O的效率

UNIX環(huán)境高級編程書上示例位置在?apue.3e/figlinks?比如本例的 fig3.5 #include "apue.h"#define BUFFSIZE 4096int main(void) {int n;char buf[BUFFSIZE];while ((n = read(STDIN_FILENO, buf, BUFFSIZE)) > 0)if (write(STDOUT_FILENO, buf, n) != n)err_sys("write error");if (n < 0)err_sys("read error");exit(0); } 重定向操作:標(biāo)準(zhǔn)輸入 # ./a.out < 1.txt? 12345678重定向操作:標(biāo)準(zhǔn)輸出 # ./a.out > 2.txt? ABCDEF ^C 查看2.txt: # cat 2.txt? ABCDEF 上篇講文件描述符時講過,POSIX 定義了?STDIN_FILENO、STDOUT_FILENO 和 STDERR_FILENO 來代替 0、1、2這三個符號常量的定義位于頭文件?<unistd.h> 查看 /usr/include/unistd.h /* Standard file descriptors. */ #define STDIN_FILENO 0 /* Standard input. */ #define STDOUT_FILENO 1 /* Standard output. */ #define STDERR_FILENO 2 /* Standard error output. */

1、問題來了,STDIN_FILENO與 stdin的區(qū)別?

參看:UNIX下STDIN_FILENO與stdin區(qū)別

(1)數(shù)據(jù)類型不一致

stdin 等類型為 FILE *
STDIN_FILENO 等類型為 int
使用 stdin 的函數(shù)主要有:fread、fwrite、fclose等,基本上都以 f 開頭
使用 STDIN_FILENO 的函數(shù)有:read、write、close等

(2)層次不一致

stdin 等屬于標(biāo)準(zhǔn)I/O,高級的輸入輸出函數(shù)。在<stdio.h>。
STDIN_FILENO 等是文件描述符,是非負(fù)整數(shù),一般定義為 0, 1, 2,直接調(diào)用系統(tǒng)調(diào)用,在<unistd.h>。
#define STDIN_FILENO 0
#define STDOUT_FILENO 1
#define STDERR_FILENO 2
stdin等屬于標(biāo)準(zhǔn)庫處理的輸入流,其聲明為 FILE 型的,對應(yīng)的函數(shù)前面都有f開頭,如fopen/fread/fwrite/fclose 標(biāo)準(zhǔn)庫調(diào)用等
STDIN_FILENO等屬于系統(tǒng)API接口庫,其聲明為 int 型,是一個打開文件句柄,對應(yīng)的函數(shù)主要包括 open/read/write/close 等系統(tǒng)級調(diào)用。

2、兩者關(guān)系

對于 stdin 等可以使用 fileno() 函數(shù)(用來取得參數(shù) stream 指定的文件流所使用的文件描述符)來取得該文件流對應(yīng)的文件描述符。
fileno(stdin) = STDIN_FILENO = 0
fileno(stdout) = STDOUT_FILENO = 1
fileno(stderr) = STDERR_FILENO = 2
例如:#include "apue.h"#define BUFFSIZE 4096int main(void) {int n;char buf[BUFFSIZE];while ((n = read(fileno(stdin), buf, BUFFSIZE)) > 0)if (write(fileno(stdout), buf, n) != n)err_sys("write error");if (n < 0)err_sys("read error");exit(0); }

七、文件共享

UNIX系統(tǒng)支持在不同進(jìn)程間共享打開文件。
內(nèi)核使用3種數(shù)據(jù)結(jié)構(gòu)表示打開文件,它們之間的關(guān)系決定了在文件共享方面一個進(jìn)程對另一個進(jìn)程可能產(chǎn)生的影響。
1)每個進(jìn)程在進(jìn)程表中都有一個記錄項,記錄項中包含一張打開文件描述符表,可將其視為一個矢量,每個描述符占用一項。與每個文件描述符相關(guān)聯(lián)的是:?
? ? 文件描述符標(biāo)志;?
? ? 指向一個文件表項的指針。
2)內(nèi)核為所有打開文件維持一張文件表。每個文件表項包含:?
? ? 文件狀態(tài)標(biāo)志(讀、寫、添寫、同步和非阻塞等);?
? ? 當(dāng)前文件偏移量;?
? ? 指向該文件v節(jié)點表項的指針。
3)每個打開文件(或設(shè)備)都有一個v節(jié)點(v-node)結(jié)構(gòu)。v節(jié)點包含了文件類型和對此文件進(jìn)行各種操作函數(shù)的指針。對于大多數(shù)文件,v節(jié)點還包含了該文件的i節(jié)點(i-node,索引節(jié)點)。這些信息是打開文件時從磁盤上讀入內(nèi)存的,所以,文件的所有相關(guān)信息都是隨時可用的。如i節(jié)點包含了文件的所有者、文件長度、指向文件實際數(shù)據(jù)塊在磁盤上所在位置的指針等。?
例如:一個進(jìn)程有兩個不同的打開文件:一個文件從標(biāo)準(zhǔn)輸入打開(文件描述符為 0),另一個從標(biāo)準(zhǔn)輸出打開(文件描述符為 1)。#include "apue.h" #define BUFFSIZE 4096 int main(void) { int n; char buf[BUFFSIZE]; while ((n = read(STDIN_FILENO, buf, BUFFSIZE)) > 0) if (write(STDOUT_FILENO, buf, n) != n) err_sys("write error"); if (n < 0) err_sys("read error"); exit(0); } 執(zhí)行: # ./a.out < 1.txt > 2.txt # cat 1.txt 12345678 # cat 2.txt 12345678該進(jìn)程對應(yīng)的 3 張表之間的關(guān)系:

再如:兩個進(jìn)程各自打開了同一個文件,這部分參看:Linux中的文件描述符與打開文件之間的關(guān)系對于以上數(shù)據(jù)結(jié)構(gòu),其相關(guān)操作的說明如下:在完成每個 write 后,在文件表項中的當(dāng)前文件偏移量即增加所寫入的字節(jié)數(shù)。如果這導(dǎo)致當(dāng)前文件偏移量超出了當(dāng)前文件長度,則將 i 節(jié)點表項中的當(dāng)前文件長度設(shè)置為當(dāng)前文件偏移量(即該文件增加了);
如果用 O_APPEND 標(biāo)志打開一個文件,則相應(yīng)標(biāo)志也被設(shè)置到文件表項的文件狀態(tài)標(biāo)志中。每次對這種具有追加寫標(biāo)志的文件執(zhí)行寫操作時,文件表現(xiàn)中的當(dāng)前文件偏移量首先會被設(shè)置為 i 節(jié)點表現(xiàn)中的文件長度。這就使得每次寫入的數(shù)據(jù)都追加到文件的當(dāng)前尾端處;
若一個文件用 lseek 定位到文件當(dāng)前的尾端,則文件表項中的當(dāng)前文件偏移量被設(shè)置為 i 節(jié)點表項中的當(dāng)前文件長度;
lseek函數(shù)只修改文件表項中的當(dāng)前文件偏移量,不進(jìn)行任何I/O操作。

八、函數(shù) dup 和 dup2

1、函數(shù) dup

#include <unistd.h> int dup(int oldfd);函數(shù)功能: 表示根據(jù)參數(shù)指定的文件描述符進(jìn)行拷貝, 返回值: 成功返回新的文件描述符,失敗返回 -1。 注意:
文件描述符的復(fù)制本質(zhì)上就是讓多個文件描述符對應(yīng)同一個文件表,也就是對應(yīng)同一個文件。
由 dup 返回的心的文件描述符一定是當(dāng)前可用文件描述符中的最小數(shù)值。 示例: #include <stdio.h> #include <unistd.h> #include <stdlib.h> int main (void) {int newfd = dup (STDOUT_FILENO);if (-1 == newfd)perror ("Fail to dup"), exit (-1);printf ("newfd = %d\n", newfd);write (newfd, "hello world\n", 12);return 0; } 輸出結(jié)果: newfd = 3 hello world

2、函數(shù) dup2

#include <unistd.h> int dup2(int oldfd, int newfd);函數(shù)功能:
表示將 newfd 作為參數(shù) oldfd 的拷貝,如果 newfd 已經(jīng)打開,則先將其關(guān)閉;如若 oldfd 等于 newfd,則 dup2 返回 newfd,而不關(guān)閉它。否則,newfd 的 FD_CLOEXEC 文件描述符標(biāo)志被清除,這樣 newfd 在進(jìn)程調(diào)用 exec 時是打開狀態(tài)。
返回值: 成功返回新描述符,也就是 newfd,失敗返回 -1。 示例: //dup/dup2函數(shù)的使用 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>int main(void) {//1.打開/創(chuàng)建一個文件int fd = open("d.txt",O_RDWR|O_CREAT/*|O_EXCL*/,0644);if(-1 == fd){perror("open"),exit(-1);}printf("fd = %d\n",fd);//3//2.使用dup函數(shù)復(fù)制文件描述符// int fd2 = fd;int fd2 = dup(fd);if(-1 == fd2){perror("dup"),exit(-1);}printf("fd2 = %d\n",fd2);//4//3.針對不同的描述符進(jìn)行處理write(fd,"A",1);write(fd2,"a",1);//打開/創(chuàng)建一個新文件int fd3 = open("e.txt",O_RDWR|O_CREAT,0644);if(-1 == fd3){perror("open"),exit(-1);}printf("fd3 = %d\n",fd3);//5//使用dup2函數(shù)進(jìn)行描述符的拷貝// fd 到 fd3的拷貝 fd3 和 fd4相等int fd4 = dup2(fd,fd3);printf("fd3 = %d,fd4 = %d\n",fd3,fd4);// 5 5 write(fd3,"1",1); //d.txtwrite(fd4,"2",1); //d.txtwrite(fd,"3",1); //d.txt//4.關(guān)閉所有描述符close(fd);close(fd2);close(fd3);return 0; }輸出結(jié)果: fd = 3 fd2 = 4 fd3 = 5 fd3 = 5,fd4 = 5查看:d.txt 和 e.txt # cat d.txt Aa123 # cat e.txt 為空od 命令查看 # od -c d.txt? 0000000 ? A ? a ? 1 ? 2 ? 3 0000005 擴(kuò)展:使用 od 命令觀察文件的實際內(nèi)容。命令行中的 -c 標(biāo)志表示以字符方式打印文件內(nèi)容 參看:od 命令

九、函數(shù) fcntl?

#include <unistd.h> #include <fcntl.h> int fcntl(int fd, int cmd, ... /* arg */ );

1、參數(shù)解析

第一個參數(shù):文件描述符 第二個參數(shù):操作的命令 ? ? F_DUPFD/F_DUPFD_CLOEXEC??復(fù)制文件描述符的功能,尋找最小的有效的大于等于第三個參數(shù) arg 的描述符作為新的描述符。 ? ? ? ? 與 dup2 函數(shù)有所不同的是,不會強(qiáng)制關(guān)閉已經(jīng)被占用的描述符。 ? ? F_GETFD/F_SETFD ?獲取/設(shè)置文件描述符的標(biāo)志 ? ? F_GETFL/F_SETFL ?獲取/設(shè)置文件狀態(tài)的標(biāo)志 ???F_GETOWN/F_SETOWN??獲取/設(shè)置異步 I/O 所有權(quán)
? ? F_SETLK/F_GETLK ?加鎖/解鎖/測試鎖是否存在 第三個參數(shù):可變長參數(shù) 參數(shù)是否需要,主要取決于參數(shù) cmd

2、返回值

F_DUPFD ?成功返回新的文件描述符 F_GETFD ?成功返回文件描述符的標(biāo)志值 F_GETFL ?成功返回文件狀態(tài)的標(biāo)志值 F_GETOWN ?成功返回異步 I/O 所有權(quán) 其他操作成功返回 0, 所有的操作失敗返回 -1

3、函數(shù)功能

主要表示根據(jù)文件描述符對文件執(zhí)行的操作 (1)復(fù)制文件描述符 (2)獲取/設(shè)置文件描述符的標(biāo)志 (3)獲取/設(shè)置文件狀態(tài)的標(biāo)志 (4)獲取/設(shè)置異步 I/O 所有權(quán) (5)實現(xiàn)文件鎖的功能

4、功能講解

(1)F_DUPFD?

復(fù)制文件描述符 fd。新的文件描述符作為函數(shù)值返回。它是尚未打開的各描述符中大于或等于第 3 參數(shù)值中各值的最小值。新描述符與 fd 共享同一文件表項。但是,新描述符有它自己的一套文件描述符,其中 FD_CLOEXEC 文件描述符標(biāo)志被消除(這表示該描述符在 exec 時仍保持有效)。
實際上:調(diào)用 dup (fd); ?等效于 fcntl (fd, F_DUPFD, 0); 調(diào)用 dup2 (fd, fd2); ?等效于 close (fd2); ?fcntl (fd, F_DUPFD, fd2); 在后一種情況下,dup2 并不完全等同于 close 加上 fcntl。它們之間的區(qū)別具體如下: --dup2 是一個原子操作,而 close 和 fcntl 包括兩個函數(shù)調(diào)用。有可能在 close 和 fcntl 之間調(diào)用了信號捕獲函數(shù),它可能修改文件描述符。如果不同的線程改變了文件描述符的話也會出現(xiàn)相同的問題。 --dup2 和 fcntl 有不同的 errno。 示例說明:? //示例一 #include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <stdlib.h>int main (void) {int fd = fcntl (STDOUT_FILENO, F_DUPFD, 0);if (-1 == fd)perror ("Fail to fcntl"), exit (-1);printf ("fd = %d\n", fd);write (fd, "hell world\n", 12);return 0; } 輸出結(jié)果: fd = 3 hell world //示例二 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>int main(void) {//1.打開/創(chuàng)建一個文件int fd = open("d.txt",O_RDWR|O_CREAT/*|O_EXCL*/,0644);if(-1 == fd){perror("open"),exit(-1);}printf("fd = %d\n",fd);//3//2.使用dup函數(shù)復(fù)制文件描述符// int fd2 = fd;int fd2 = dup(fd);if(-1 == fd2){perror("dup"),exit(-1);}printf("fd2 = %d\n",fd2);//4//3.針對不同的描述符進(jìn)行處理write(fd,"A",1);write(fd2,"a",1);//打開/創(chuàng)建一個新文件int fd3 = open("e.txt",O_RDWR|O_CREAT,0644);if(-1 == fd3){perror("open"),exit(-1);}printf("fd3 = %d\n",fd3);//5close (fd3);//使用fcntl函數(shù)進(jìn)行描述符的拷貝// fd 到 fd3的拷貝 fd3 和 fd4相等int fd4 = fcntl (fd, F_DUPFD, fd3);printf("fd3 = %d,fd4 = %d\n",fd3,fd4);// 5 5 write(fd3,"1",1); //d.txtwrite(fd4,"2",1); //d.txtwrite(fd,"3",1); //d.txt//4.關(guān)閉所有描述符close(fd);close(fd2);close(fd3);return 0; } 輸出結(jié)果: fd = 3 fd2 = 4 fd3 = 5 fd3 = 5,fd4 = 5od命令查看: # od -c d.txt 0000000 A a 1 2 3 0000005

(2)F_DUPFD_CLOEXEC

復(fù)制文件描述符,設(shè)置與新描述符關(guān)聯(lián)的 FD_CLOEXEC 文件描述符標(biāo)志的值,返回新文件描述符。

(3)F_GETFD

對應(yīng)于 fd 的文件描述符標(biāo)志作為函數(shù)值返回。當(dāng)前只定義了一個文件描述符標(biāo)志 FD_CLOEXEC。

1)上面出現(xiàn)了好幾次 FD_CLOEXEC 文件描述符標(biāo)志,需要對它了解一下:

參看:執(zhí)行時關(guān)閉標(biāo)識位 FD_CLOEXEC 的作用 FD_CLOEXEC 是“文件描述符”的標(biāo)志,用來設(shè)置文件的 close-on-exec 狀態(tài)。
此標(biāo)志用來控制在執(zhí)行 exec 后,是否關(guān)閉對應(yīng)的文件描述符(關(guān)閉文件描述符即不能對文件描述符指向的文件進(jìn)行任何操作)

2)這里又有個新概念 exec :

exec 應(yīng)該是指 exec系列函數(shù),在此只了解其中的 execl 函數(shù): #include <unistd.h> int execl(const char *path, const char *arg, ...);execl() 其中后綴 "l" 代表 list 也就是參數(shù)列表的意思,第一參數(shù)path字符指針?biāo)赶蛞獔?zhí)行的文件路徑, 接下來的參數(shù)代表執(zhí)行該文件時傳遞的參數(shù)列表:argv[0],argv[1]... 最后一個參數(shù)須用空指針NULL作結(jié)束
返回值:如果執(zhí)行成功則函數(shù)不會返回, 執(zhí)行失敗則直接返回-1, 失敗原因存于errno 中. 函數(shù)功能:主要用于實現(xiàn)跳轉(zhuǎn)的功能
示例: #include <unistd.h> int main (void) {// 執(zhí)行/bin目錄下的ls, 第一參數(shù)為程序名ls, 第二個參數(shù)為"-al", 第三個參數(shù)為"/etc/passwd"execl("/bin/ls", "ls", "-al", "/etc/passwd", NULL);return 0; } 輸出結(jié)果: -rw-r--r-- 1 root root 1918 Dec 1 10:28 /etc/passwd

3)FD_CLOEXEC 標(biāo)志使用

第一、此標(biāo)志用來控制在執(zhí)行 exec 后,是否關(guān)閉對應(yīng)的文件描述符
#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h>int main (int argc, char *argv[]) {if (argc > 1){int flags = fcntl (STDOUT_FILENO, F_GETFD);if (-1 == flags)perror ("fail to F_GETFD"), exit (-1);flags |= FD_CLOEXEC;if (fcntl (STDOUT_FILENO, F_SETFD, flags) == -1)perror ("fail to F_SETFD"), exit (-1);}execl("/bin/ls", "ls", "-al", "/etc/passwd", NULL);return 0; } 輸出結(jié)果: 不含有FD_CLOEXEC標(biāo)志,未關(guān)閉對應(yīng)的文件描述符 STDOUT_FILENO # ./a.out -rw-r--r-- 1 root root 1918 Dec 1 10:28 /etc/passwd含有FD_CLOEXEC標(biāo)志,關(guān)閉了對應(yīng)的文件描述符 STDOUT_FILENO # ./a.out 1 ls: 寫入錯誤: 錯誤的文件描述符
第二、在使用fork調(diào)用的子進(jìn)程中,此描述符并不關(guān)閉,仍可使用。(驗證失敗)
//vfork函數(shù)和execl函數(shù)的使用 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <fcntl.h>int main (int argc, char *argv[]) {if (argc > 1){int flags = fcntl (STDOUT_FILENO, F_GETFD);if (-1 == flags)perror ("fail to F_GETFD"), exit (-1);flags |= FD_CLOEXEC;if (fcntl (STDOUT_FILENO, F_SETFD, flags) == -1)perror ("fail to F_SETFD"), exit (-1);}//1.使用vfork函數(shù)創(chuàng)建子進(jìn)程pid_t pid = vfork();if(-1 == pid)perror("vfork"),exit(-1);//2.子進(jìn)程調(diào)用execl函數(shù)跳轉(zhuǎn)if(0 == pid) //子進(jìn)程{printf("子進(jìn)程%d開始運行\(zhòng)n",getpid());sleep(2);//調(diào)用execl函數(shù)進(jìn)行跳轉(zhuǎn)execl("/bin/ls", "ls", "-al", "/etc/passwd", NULL);//執(zhí)行不到printf("子進(jìn)程結(jié)束\n");}sleep (2);//3.父進(jìn)程執(zhí)行printf("父進(jìn)程%d開始執(zhí)行\(zhòng)n",getpid());printf("父進(jìn)程結(jié)束\n");return 0; } 不含有FD_CLOEXEC標(biāo)志,未關(guān)閉對應(yīng)的文件描述符 STDOUT_FILENO # ./a.out 子進(jìn)程3488開始運行 -rw-r--r-- 1 root root 1918 Dec 1 10:28 /etc/passwd 父進(jìn)程3487開始執(zhí)行 父進(jìn)程結(jié)束含有FD_CLOEXEC標(biāo)志,關(guān)閉了對應(yīng)的文件描述符 STDOUT_FILENO # ./a.out 1 子進(jìn)程3550開始運行 ls: 寫入錯誤: 錯誤的文件描述符 父進(jìn)程3549開始執(zhí)行 父進(jìn)程結(jié)束

4)總結(jié):

FD_CLOEXEC 用來設(shè)置文件的 close-on-exec 狀態(tài)標(biāo)準(zhǔn)。在 exec() 調(diào)用后,close-on-exec 標(biāo)志為0的情況,此文件不被關(guān)閉。非零則在 exec() 后被關(guān)閉。默認(rèn)close-on-exec狀態(tài)為 0,需要通過FD_CLOEXEC設(shè)置 看見有這句話,“在使用fork調(diào)用的子進(jìn)程中,此描述符并不關(guān)閉,仍可使用。”但是我驗證了下,在子進(jìn)程中也是可以關(guān)閉的。 (不過還是不太確認(rèn),如果哪位看到這里,可以告訴我一下,這句話是否正確)。

(4)F_SETFD

對于 fd 設(shè)置文件描述符標(biāo)志。新標(biāo)志值按第 3 個參數(shù)(取為整型值)設(shè)置。
示例同上。

(5)F_GETFL

對應(yīng)于 fd 的文件狀態(tài)標(biāo)志作為函數(shù)值返回。下面是 open 函數(shù)時描述的文件狀態(tài)標(biāo)志。
文件狀態(tài)標(biāo)志說明
O_RDONLY只讀打開
O_WRONLY只寫打開
O_RDWR讀、寫打開
O_EXEC只執(zhí)行打開
O_SEARCH只搜索打開目錄
O_APPEND追加寫
O_NONBLOCK非阻塞模式
O_SYNC等待寫完成(數(shù)據(jù)和屬性)
O_DSYNC等待寫完成(僅數(shù)據(jù))
O_RSYNC同步讀和寫
O_FSYNC等待寫完成(僅FreeBSD和Mac OS X)
O_ASYNC異步I/O(僅FreeBSD和Mac OS X)
不過,5 個訪問方式標(biāo)志(O_RDONLY、O_WRONLY、O_RDWR、O_EXEC以及O_SEARCH)并不各占1位。因此首先必須用屏蔽字 O_ACCMODE 取得訪問方式位,然后將結(jié)果與這5個值的每一個相比較。 通過下面的宏定義可以看出: O_RDONLY、O_WRONLY、O_RDWR這3種標(biāo)志的值各是0 , 1和2,由于歷史原因,這 5 種值互斥 ,?一個文件的訪問只能有這 5 個值之一 示例說明: #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int main (void) { //1.打開/創(chuàng)建一個文件 int fd = open ("a.txt", O_WRONLY); if (-1 == fd) perror("open"),exit(-1); int flags = fcntl (fd, F_GETFL, 0);printf ("flags = %d\n", flags);close(fd); return 0; } 輸出結(jié)果: flags = 1 對應(yīng)的函數(shù)值查看/usr/include/asm-generic/fcntl.h? 最前面有 0 可以看出數(shù)值為八進(jìn)制,打印轉(zhuǎn)化為十進(jìn)制,擴(kuò)展:進(jìn)制轉(zhuǎn)換器 #define O_ACCMODE 00000003 #define O_RDONLY 00000000 #define O_WRONLY 00000001 #define O_RDWR 00000002 #ifndef O_CREAT #define O_CREAT 00000100 /* not fcntl */ #endif #ifndef O_EXCL #define O_EXCL 00000200 /* not fcntl */ #endif #ifndef O_NOCTTY #define O_NOCTTY 00000400 /* not fcntl */ #endif #ifndef O_TRUNC #define O_TRUNC 00001000 /* not fcntl */ #endif #ifndef O_APPEND #define O_APPEND 00002000 #endif #ifndef O_NONBLOCK #define O_NONBLOCK 00004000 #endif #ifndef O_DSYNC #define O_DSYNC 00010000 /* used to be O_SYNC, see below */ #endif后面還有一個更好玩的,現(xiàn)在講的功能都可用數(shù)字表示的: #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get close_on_exec */ #define F_SETFD 2 /* set/clear close_on_exec */ #define F_GETFL 3 /* get file->f_flags */ #define F_SETFL 4 /* set file->f_flags */ #ifndef F_GETLK #define F_GETLK 5 #define F_SETLK 6 #define F_SETLKW 7 #endif #ifndef F_SETOWN #define F_SETOWN 8 /* for sockets. */ #define F_GETOWN 9 /* for sockets. */ #endif #ifndef F_SETSIG #define F_SETSIG 10 /* for sockets. */ #define F_GETSIG 11 /* for sockets. */ #endif

(6)F_SETFL

將文件狀態(tài)標(biāo)志設(shè)置為第 3 個參數(shù)的值(取為整型值)。可以更改的幾個標(biāo)志是:O_APPEND、O_NONBLOCK、O_SYNC、O_DSYNC、O_RSYNC、O_FSYNC和 O_ASYNC。 以 O_NONBLOCK 為例: //示例一 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int main (void) { //1.打開/創(chuàng)建一個文件 int fd = open ("a.txt", O_RDONLY | O_NONBLOCK); if (-1 == fd) perror("open"),exit(-1); int flags = fcntl (fd, F_GETFL, 0); printf ("flags = %d\n", flags); //將其設(shè)為非阻塞 flags &= ~O_NONBLOCK;fcntl (fd, F_SETFL, flags);int flags1 = fcntl (fd, F_GETFL, 0); printf ("flags1 = %d\n", flags1); close(fd); return 0; } 輸出結(jié)果: flags = 2048 flags1 = 0 //示例二 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int main (void) { //1.打開/創(chuàng)建一個文件 int fd = open ("a.txt", O_RDONLY); if (-1 == fd) perror("open"),exit(-1); int flags = fcntl (fd, F_GETFL, 0); printf ("flags = %d\n", flags); flags |= O_NONBLOCK;fcntl (fd, F_SETFL, flags);int flags1 = fcntl (fd, F_GETFL, 0); printf ("flags1 = %d\n", flags1); close(fd); return 0; } 輸出結(jié)果: flags = 0 flags1 = 2048

示例說明:

示例一:取消文件的某個flags,比如文件是非阻塞的,想設(shè)置成為阻塞:
flags = fcntl(fd,F_GETFL,0); flags &= ~O_NONBLOCK; fcntl(fd,F_SETFL,flags);示例二:增加文件的某個flags,比如文件是阻塞的,想設(shè)置成非阻塞:
flags = fcntl(fd,F_GETFL,0); flags |= O_NONBLOCK; fcntl(fd,F_SETFL,flags);

(7)F_GETOWN

獲取當(dāng)前接收 SIGIO 和 SIGURG 信號的進(jìn)程 ID 或進(jìn)程組 ID。(示例以后寫)

(8)F_SETOWN

設(shè)置接收 SIGIO 和 SIGURG 信號的進(jìn)程 ID 或進(jìn)程組 IF。正的 arg 指定一個進(jìn)程 ID,負(fù)的 arg 表示等于 arg 絕對值的一個進(jìn)程組 ID。

十、總結(jié)

文件I/O這一章講完,不過有幾處沒有搞懂和沒有講到的地方。 首先,進(jìn)程表、文件表、v節(jié)點表這部分沒有搞明白;原子操作沒有講到;函數(shù) sync、fsync和fdatasync沒有講;函數(shù) fcntl 文件鎖部分沒有講;函數(shù) ioctl沒有講;/dev/fd 沒有講。 這些在以后的總結(jié)中會涉及到,到時再詳細(xì)講吧。

總結(jié)

以上是生活随笔為你收集整理的UNIX再学习 -- 文件I/O的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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