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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux 系统应用编程——文件I/O

發布時間:2023/12/9 linux 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux 系统应用编程——文件I/O 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?Linux操作系統是基于文件概念的。文件是以字符序列構成的信息載體。根據這一點,可以把I/O設備當做文件來處理,因此,在磁盤上的普通文件進行交互所用的統一系統調用可以直接用于I/O設備。這樣大大簡化了系統對于不同設備的處理,提高了效率。Linux中的文件主要分為6種:普通文件、目錄文件、符號鏈接文件、管道文件、套接字文件和設備文件。

?????? 那么,內核如何區分和引用特定的文件呢?這里用到了一個重要的概念——文件描述符。對于Linux而言,所有的設備和文件的操作都是通過文件描述符來進行的。文件描述符是一個非負的整數,它是一個索引值,并指向在內核中每個進程打開文件的記錄表。當打開一個現存文件或創建一個新文件時,內核就向進程返回一個文件描述符;讀寫文件時,需要把文件描述符作為參數傳遞給相應的函數。

?????? 通常,一個進程啟動時,都會打開3個流:標準輸入、標準輸出和標準錯誤。這3個流分別對應文件描述符0、1? 和 2(對應的宏分別是STDIN_FILENO、STDOUT_FILENO和STDERR_FILENO)。

????? 基于文件描述符的I/O操作雖然不鞥直接移植到類Linux以外的系統上去(如Windows),但它往往是實現某些I/O操作的唯一途徑,如Linux中底層文件操作函數、多路I/O、TCP/IP套接字編程接口等。同時,他們也很好地兼容POSIX標準,因此,可以很方便地移植到任何POSIX平臺上。基于文件描述符的I/O操作是Linux中最常用的操作之一。

????? 文件I/O相關函數:open() 、read() 、write() 、lseek() 和close() 。這些函數的特點是不帶緩沖,直接對文件(包括設備)進行讀寫操作。這些函數不是ANSI C的組成部分,而是POSIX相關標準來定義。

1、文件打開與和關閉

???????open()函數用于創建或打開文件,在打開或創建文件時可以指定文件打開方式及文件的訪問權限。

??????? 函數原型如下:

[cpp]?view plaincopy
  • #include?<sys/stat.h>??
  • #include?<fcntl.h>??
  • ??
  • int?open(const?char?*pathname,int?flags,int?perms);??
  • 1)pathname: 被打開的文件名(可包括路徑名)

    2)flags(文件打開方式,這里介紹幾個常用的)

    O_RDONLY???只讀

    O_WRONLY??只寫

    O_RDWR?????? 可讀可寫

    這三者必有其一

    O_CREAT??? 如果文件不存在,就創建一個新文件,并用第三個參數為其設置權限;

    O_TRUNC????若文件已經存在,那么會刪除文件中的全部原有數據,并且設置文件大小為0;

    O_APPEND? 以添加方式打開文件,在寫文件時,文件讀寫文職自動指向文件的末尾,即將寫入的數據添加到文件的末尾;

    3)perms 新建文件的存取權限

    ????? close()函數用于關閉一個被打開的文件。當一個進程終止時,所有打開的文件都有內核自動關閉。很多程序都利用這一特性而不顯示地關閉一個文件。

    函數原型:

    [cpp]?view plaincopy
  • #include?<unistd.h>??
  • ??
  • int?close(int?fd);??
  • ?

    2、文件讀寫

    ???????read()函數從文件中讀取數據存放到緩沖區中,并返回實際讀取的字節數。若返回0,則表示沒有數據可讀,即已達到文件尾。讀操作從文件的當前讀寫位置開始讀取數據,當前讀寫位置自動往后移動。

    函數原型:

    [cpp]?view plaincopy
  • #include?<unistd.h>??
  • ??
  • ssize_t?read(int?fd,?void?*buf,size_t?count);??
  • 函數傳入值:

    fd? 文件描述符;

    buf 指定存儲器讀取數據的緩沖區;

    count? 指定讀出的字節數;

    函數返回值:

    成功:讀到的字節數;

    0:已到達文件尾;

    -1:出錯;

    在讀到普通文件時,若讀到要求的字節數之前已到達問價你的尾部,則返回的字節數會小于指定讀出的字節數;

    ????????write()函數將數據寫入文件中,并返回實際寫入的字節數。寫操作從文件的當前讀寫位置開始寫入。對磁盤文件進行寫操作時,若磁盤已滿,write()函數返回失敗;

    函數原型:

    [cpp]?view plaincopy
  • #include?<unistd.h>??
  • ??
  • ssize_t?write(int?fd,void??*buf?,size_t?count);??
  • 函數傳入值:

    fd? 文件描述符

    buf? 指定存儲器寫入數據的緩沖區

    count? 指定讀出的字節數

    函數返回值:

    成功:已寫的字節數

    -1:出錯

    下面寫個簡單小程序,實現copy程序,完成文件的復制,代碼如下:

    [cpp]?view plaincopy
  • #include?<stdio.h>??
  • #include?<unistd.h>??
  • #include?<sys/types.h>??
  • #include?<fcntl.h>??
  • #include?<sys/stat.h>??
  • #define?maxsize?256??
  • ??
  • int?main(int?argc,?char?*argv[])??
  • {??
  • ????int?fd1,fd2;??
  • ????int?byte;??
  • ????char?buffer[maxsize];??
  • ??
  • ????if(argc?!=?3)??
  • ????{??
  • ????????printf("command?error!\n");??
  • ????????return?-1;??
  • ????}??
  • ??
  • ????if((fd1?=?open(argv[1],O_RDONLY))?==?-1)??
  • ????{??
  • ????????perror("open?fails");??
  • ????????return?-1;??
  • ????}??
  • ??
  • ????if((fd2?=?open(argv[2],O_WRONLY?|?O_CREAT?|?O_TRUNC?,0664))?==?-1)//如果文件不存在,則創建,若存在,則覆蓋;??
  • ????{??
  • ????????perror("open?fails");??
  • ????????return?-1;??
  • ????}??
  • ??
  • ????while(1)??
  • ????{??
  • ????????if((byte?=?read(fd1,buffer,maxsize))?>?0)??
  • ????????????write(fd2,buffer,byte);??
  • ??
  • ????????if(byte?==?0)??
  • ????????????break;?//如果讀不到數據,則返回??
  • ????}??
  • ??
  • ????close(fd1);??
  • ????close(fd2);??
  • ??
  • ????return?0;??
  • }??
  • 執行結果如下:

    [cpp]?view plaincopy
  • fs@ubuntu:~/qiang/fileIO/open$?ls?-l??
  • total?16??
  • -rwxrwxr-x?1?fs?fs?7388?Jan??4?16:18?cp??
  • -rw-rw-r--?1?fs?fs??625?Jan??4?16:18?cp.c??
  • -rw-rw-r--?1?fs?fs??526?Jan??4?16:01?file1.c??
  • fs@ubuntu:~/qiang/fileIO/open$?./cp?file1.c?file2.c??
  • fs@ubuntu:~/qiang/fileIO/open$?ls?-l??
  • total?20??
  • -rwxrwxr-x?1?fs?fs?7388?Jan??4?16:18?cp??
  • -rw-rw-r--?1?fs?fs??625?Jan??4?16:18?cp.c??
  • -rw-rw-r--?1?fs?fs??526?Jan??4?16:01?file1.c??
  • -rw-rw-r--?1?fs?fs??526?Jan??4?16:19?file2.c??
  • fs@ubuntu:~/qiang/fileIO/open$???
  • 我們可以看到,原來file2.c并不存在,執行完程序后,file2.c存在,且大小和file1.c相同;

    ?

    3、文件定位

    ?????? lseek()函數對文件當前讀寫位置進行定位。它只能對可定位(可隨機訪問)文件操作。管道、套接字和大部分字符設備文件不支持此類操作;

    函數原型:

    [cpp]?view plaincopy
  • #include?<unistd.h>??
  • #include?<sys/types.h>??
  • ??
  • off_t?lseek(int?fd?,off_t?offset,int?whence);??
  • 函數傳入值:

    fd? 文件描述符

    offset?? 相對于基準點whence 的偏移量。以字節為單位,正數表示向前移動,負數表示向后移動

    whence 當前位置的基點

    SEEK_SET:文件的起始位置

    SEEK_CUR:文件當前讀寫位置

    SEEK_END:文件的結束位置

    函數的返回值:

    成功:文件當前讀寫位置

    -1:出錯

    ? ??? 我們可以通過lseek函數實現一個小功能:查看文件的大小,代碼如下:

    [cpp]?view plaincopy
  • #include?<stdio.h>??
  • #include?<unistd.h>??
  • #include?<fcntl.h>??
  • #include?<sys/stat.h>??
  • #include?<sys/types.h>??
  • ??
  • int?main(int?argc,?const?char?*argv[])??
  • {??
  • ????int?fd;??
  • ????int?length;??
  • ??
  • ????if(argc?!=?2)??
  • ????{??
  • ????????printf("command?error!\n");??
  • ????????return?-1;??
  • ????}??
  • ??
  • ????if((fd?=?open(argv[1],O_RDONLY))?==?-1)??
  • ????{??
  • ????????perror("open?fails");??
  • ????????return?-1;??
  • ????}??
  • ??
  • ????length?=?lseek(fd,0,SEEK_END);??
  • ??????
  • ????printf("The?length?of?%s?is?%d?bytes!\n",argv[1],length);??
  • ??
  • ????return?0;??
  • }??
  • 執行結果如下:

    [cpp]?view plaincopy
  • fs@ubuntu:~/qiang/fileIO/lseek$?ls?-l??
  • total?12??
  • -rwxrwxr-x?1?fs?fs?7308?Jan??4?16:47?lseek??
  • -rw-rw-r--?1?fs?fs??424?Jan??4?16:46?lseek.c??
  • fs@ubuntu:~/qiang/fileIO/lseek$?./lseek?lseek.c??
  • The?length?of?lseek.c?is?424?bytes!??
  • fs@ubuntu:~/qiang/fileIO/lseek$???
  • 我們可以看到,得到了lseek.c正確大小!

    總結

    以上是生活随笔為你收集整理的Linux 系统应用编程——文件I/O的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。