Linux中無緩衝檔案I/O API

來源:互聯網
上載者:User

1.什麼是無緩衝I/O
 我們首先要知道Linux作業系統提供給我們的使用者程式調用的介面,除了使用庫函數,還可以直接使用系統調用。而今天我要介紹的相關函數就是直接調用了核心的系統調用,所以說它是無緩衝的,它跟標準的I/O函數相對應。

2.開啟或者建立檔案的函數:open()
 
要操作相關檔案,就必須獲得該檔案的控制代碼,專業點叫檔案描述符。它是進程在開啟一個檔案或者建立一個檔案時,核心返回給該進程的一個唯一的非負的整數,且一定是當前可以的描述符中最小的一個數。進程獲得這個檔案描述符後,就可以根據它來告訴read()或者write相關函數具體來操作哪個檔案了。

    Tips:通常系統對一個進程可開啟的檔案描述符數量有一個預設值,可以使用命令ulimit -f查看,也可以使用ulimit命令重新設定該值。

 通常,系統有3個已經預設的檔案描述符,即0代表標準輸入,1表示標準輸出,2表示標準錯誤,在unistd.h標頭檔中,把他們定義為常量,分別是STDIN_FILENO、STDOUT_FILENO、STDERR_FILENO。

   open()函數為我們提供了該檔案描述符:

#include<fcntl.h>
int open( const char * pathname,int flags, mode_t mode);

pathname:即是我們要開啟或者建立檔案的名字,可以是相對路徑,也可以是絕對路徑。

flags:重點介紹一下,它的取值比較多,在<fcntl.h>標頭檔中定義了很多常量:

  O_RDONLY:即以唯讀方式開啟該檔案。
  O_WRONLY:即以唯寫的方式開啟該檔案。
  O_RDWR:即以讀、寫的方式開啟該檔案。
以上這三個常量,flags必選選擇其一,且只能選擇其一。還有幾個可選常量可以跟這三個之一組合使用,以達到不同的效果:
  O_CREAT:若欲開啟的檔案不存在則自動建立該檔案.
  O_TRUNC :若檔案存在並且以可寫的方式開啟時,此旗標會令檔案長度清為0,而原來存於該檔案的資料也會消失。
  O_APPEND :當讀寫檔案時會從檔案尾開始移動,也就是所寫入的資料會以附加的方式加入到檔案後面。
  O_EXCL 如果O_CREAT 也被設定,此指令會去檢查檔案是否存在。檔案若不存在則建立該檔案,否則將導致開啟檔案錯誤。

比如,我們可以使用open("./filename" ,O_WRONLY|O_CREAT,mode),以寫方式開啟filename,如果filenam不存在則建立它。
再如,open("./filename" ,O_WRONLY|TRUNC),就會將原來filename中的內容清除掉,從新寫入新的值。
還如,open("./filename" ,O_WRONLY|O_CREAT|O_EXCL),可以測試filename是否存在,存在則報錯,不存在則建立filename.
當然flags還有幾個其他的常量取值,就不一一介紹了,可以自己去查手冊。

  mode:僅當建立一個新檔案需要指定該參數,該參數的意思是說檔案以一個什麼樣的許可權建立。

  open()調用成功後將返迴文件描述符,出錯則返回-1。

系統還提供一個專門用來建立檔案的函數create():


#include<fcntl.h>
int creat(const char * pathname, mode_tmode);

其相當於open("pathname",O_WRONLY|O_CREAT|O_TRUNC,mode)。該函數有個不好之處是,只能以寫的方式開啟檔案。有了open(),我們可以這樣定義:

open("pathname",O_RDWR|O_CREAT|O_TRUNC,mode)

3.讀函數read(),寫函數write()

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

read()函數從fd中將指定大小count的位元組讀入buf中(注意,也可能讀少於count的位元組數,如到達了檔案尾部,或者是特殊的檔案)。成功返回讀到的位元組數,遇到結尾則返回0,失敗返回-1。

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

write函數向fd中當前位移量後面寫入count大小位元組的buf內容。如果成功返回寫入的位元組數大小,如果失敗則返回-1.

4.設定檔案位移量的函數lseek()

 每個開啟的檔案都有一個“當前檔案位移量”,在read(),write()的時候就可以根據該位置開始讀寫。使用lseek()則改變該位置。

#include<unistd.h>
off_t lseek(int fildes,off_t offset ,int whence);

offset即指要相對whence便宜多少位元組。whence不同的值使offset的意思不一樣:

SEEK_CUR:將位移量設定為當前位移量加offset個位元組。
SEEK_SET:將位移量設定為檔案起始處位移offset個位元組。
SEEK_END:將位移量設定為檔案末尾加offset個位元組。

有個小技巧,如果要獲得該檔案當前檔案位移量,怎麼辦呢?可以這樣:currPos = lseek(fd,0,SEEK_CUR);

注意:當前檔案位移量不一定是非負的值,也可能是負值。所以判斷lseek是否失敗一定要測試其結果是否為-1,而不是小於0。

如果設定位移量大於檔案長度時,檔案中將形成“空洞”,這種“空洞”並不佔有磁碟的空間,它讀取出來表現是0。

5.一個copy程式

 

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

#define BUFFER 4096

int main(int argc,char *argv[])
{
int n;
char buf[BUFFER];
int fd1 = open(argv[1],O_RDONLY);
int fd2 = open(argv[2],O_WRONLY);
while( (n=read(fd1,buf,BUFFER))>0 )
{
if( (write(fd2,buf,n))!=n )
{
printf("error\n");
exit(1);
}
}
close(fd1);
close(fd2);
exit(0);
}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.