學習筆記之文件與I/O

本文是學習linux C一站式學習的筆記

在unix中,所有的I/O設備,如網絡磁盤和終端都被模型化爲文件,而所以輸人和輸出都被當成對相應文件的讀和寫來執行,大多數unix文件I/O只需用到5個函數:open,read,write,lseek以及close。相對於ANSI C而言,這些函數被稱爲不帶緩存的I/O,不帶緩存指每個read和write都調用內核中的一個系統調用。

一、I/O函數介紹

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags, mode_t mode);//返回值:成功返回新分配的文件描述符,出錯返回-1並設置errno
ssize_t read(int fd, void *buf, size_t count);//返回值:成功返回讀取的字節數,出錯返回-1並設置errno,如果在調read之前已到達文件末尾,則這次read返回0
ssize_t write(int fd, const void *buf, size_t count);//返回值:成功返回寫入的字節數,出錯返回-1並設置errno
off_t lseek(int fd, off_t offset, int whence);
int close(int fd);//返回值:成功返回0,出錯返回-1並設置errno
1)open函數可以打開或創建一個文件

參數介紹:pathname:要打開或創建的文件名,和fopen一樣,pathname既可以是相對路徑也可以是絕對路徑;
    flag:有一系列常數值可供選擇,可以同時選擇多個常數用按位或運算符連接起來;

必選項:以下三個常數中必須指定一個,且僅允許指定一個。

O_RDONLY 只讀打開
O_WRONLY 只寫打開
O_RDWR 可讀可寫打開

以下可選項可以同時指定0個或多個,和必選項按位或起來作爲flags參數。可選項有很多。

O_APPEND 表示追加。如果文件已有內容,這次打開文件所寫的數據附加到文件的末尾而不覆蓋原來的內容。
O_CREAT 若此文件不存在則創建它。使用此選項時需要提供第三個參數mode,表示該文件的訪問權限。

             O_TRUNC 如果文件已存在,並且以只寫或可讀可寫方式打開,則將其長度截斷(Truncate)爲0字節。

             O_NONBLOCK 對於設備文件,以O_NONBLOCK方式打開可以做非阻塞I/O(Nonblock I/O)

               mode:指明文件權限,每個進程都有一個umask,它是通過調用umask函數來設置的,當進程通過帶某個mode參數的open函數來創建一個新文件時,文件的訪問權限被設置爲mode&~umask,可以用八進制數表示,比如0644表示-rw-r--r--

2)read和write函數

read函數參數count是請求讀取的字節數,讀上來的數據保存在緩衝區buf中,同時文件的當前讀寫位置向後移。注意這個讀寫位置和使用C標準I/O庫時的讀寫位置有可能不同,這個讀寫位置是記在內核中的,而使用C標準I/O庫時的讀寫位置是用戶空間I/O緩衝區中的位置。write的返回值通常等於請求寫的字節數count,而向終端設備或網絡寫則不一定。

3)lseek參數offset和whence的含義和fseek函數完全相同。只不過第一個參數換成了文件描述符。和fseek一樣,偏移量允許超過文件末尾,這種情況下對該文件的下一次寫操作將延長文件,中間空洞的部分讀出來都是0。lseek成功時返回當前偏移量失敗時返回-1。

二,fcntl函數

可以用fcntl函數改變一個已打開的文件的屬性,可以重新設置讀、寫、追加、非阻塞等標誌(這些標誌稱爲File Status Flag),而不必重新open文件。

#include <unistd.h>
#include <fcntl.h>

int fcntl(int fd, int cmd);
int fcntl(int fd, int cmd, long arg);
int fcntl(int fd, int cmd, struct flock *lock);
fcntl函數有五種功能:
• 複製一個現存的描述符(c m d=F _ D U P F D) 。
• 獲得/設置文件描述符標記(c m d = F _ G E T F D或F _ S E T F D) 。
• 獲得/設置文件狀態標誌(c m d = F _ G E T F L或F _ S E T F L) 。
• 獲得/設置異步I / O有權(c m d = F _ G E TO W N或F _ S E TO W N) 。
• 獲得/設置記錄鎖(c m d = F _ G E T L K , F _ S E T L K或F _ S E T L K W) 。
實例:

#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
	char buf[10];
	int n;
	int flags;
	flags = fcntl(STDIN_FILENO, F_GETFL);//獲取文件狀態標識
	flags |= O_NONBLOCK;//改變標識
	if (fcntl(STDIN_FILENO, F_SETFL, flags) == -1) {//設置標識
		perror("fcntl");
		exit(1);
	}
        ....
	return 0;
}
三、ioctl

可以通過fcntl設置的都是當前進程如何訪問設備或文件的訪問控制屬性,例如讀、寫、追加、非阻塞、加鎖等,但並不設置文件或設備本身的屬性,例如文件的讀寫權限、串口波特率等。ioctl用於向設備發控制和配置命令,有些命令也需要讀寫一些數據,但這些數據是不能用read/write讀寫的。

#include <sys/ioctl.h>
int ioctl(int d, int request, ...);
d是某個設備的文件描述符。request是ioctl的命令,可變參數取決於request,通常是一個指向變量或結構體的指針。若出錯則返回-1,若成功則返回其他值,返回值也是取決於request。

四、unix  基本I/O模型

1,阻塞I/O:最流行的I/O模型是阻塞I/O(blocking I/O)模型。缺省情況下,所有套接口都是阻塞的。

2,非阻塞I/O:進程把一個套接口設置成非阻塞是在通知內核:當所請求的I/O操作非得把本進程投入睡眠才能完成時,不要把本進程投入睡眠,而是返回一個錯誤。

3,I/O複用(select和poll):我們就可以調用select或poll,阻塞在這兩個系統調用中的某一個之上,而不是阻塞在真正的I/O系統調用上。

4,信號驅動I/O(SIGIO):我們也可以用信號,讓內核在描述字就緒時發送SIGIO信號通知我們

5,異步I/O(POSIX的aio_系列函數):異步I/O(asynchronous I/O)由POSIX規範定義。一般的說,這些函數的工作機制是:告知內核啓動某個操作,並讓內核在整個操作(包括將數據從內核拷貝到我們自己的緩衝區)完成後通知我們。這種模型和信號驅動模型的主要區別在於:信號驅動I/O是由內核通知我們何時可以啓動一個I/O操作,而異步I/O模型是由內核通知我們I/O操作何時完成。


部分內容摘自:http://his9932.blog.51cto.com/2915040/632667

參考資料:http://blog.sina.com.cn/s/blog_5f4344bf0100cklt.html

                     http://www.2beanet.com/linux/ch28.html



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章