Linux文件操作的主要介面API及相關細節

来源:http://www.cnblogs.com/CYP01/archive/2016/11/21/6086804.html
-Advertisement-
Play Games

操作系統API: 1、API是一些函數,這些函數是由linux系統提供支持的,由應用層程式來使用,應用層程式通過調用API來調用操作系統中的各種功能,來幹活 文件操作的一般步驟: 1、在linux系統中要操作一個文件,一般是先open打開一個文件,得到一個文件描述符,然後對文件進行讀寫操作(或其他操 ...


操作系統API:

1、API是一些函數,這些函數是由linux系統提供支持的,由應用層程式來使用,應用層程式通過調用API來調用操作系統中的各種功能,來幹活

文件操作的一般步驟:

1、在linux系統中要操作一個文件,一般是先open打開一個文件,得到一個文件描述符,然後對文件進行讀寫操作(或其他操作),最後close關閉文件即可

2、文件平時是存在塊設備中的文件系統中的,我們把這種文件叫靜態文件。當我們去open打開一個文件時,linux內核做的操作包括:內核在進程中建立了一個打開文件的數據結構,記錄下我們打開的這個文件;內核在記憶體中申請一段記憶體,並且將靜態文件的內容從塊設備中讀取到記憶體中特定地址管理存放(叫動態文件)。打開文件後,以後對這個文件的讀寫操作,都是針對記憶體中這一份動態文件的,而並不是針對靜態文件的。當我們對動態文件進行讀寫後,此時記憶體中的動態文件和塊設備中的靜態文件就不同步了,當我們close關閉動態文件時,close內部內核將記憶體中的動態文件的內容去更新(同步)塊設備中的靜態文件。

3、為什麼要這麼設計?

以為塊設備本身有讀寫限制(回憶NnadFlash、SD等塊設備的讀寫特征),本身對塊設備進行操作非常不靈活。而記憶體可以按位元組為單位來操作,而且可以隨機操作(記憶體就叫RAM,random),很靈活。所以內核設計文件操作時就這麼設計了

 

文件描述符:

1、文件描述符其實實質是一個數字,這個數字在一個進程中表示一個特定的含義,當我們open打開一個文件時,操作系統在記憶體中構建了一些數據結構來表示這個動態文件,然後返回給應用程式一個數字作為文件描述符,這個數字就和我們記憶體中維護這個動態文件的這些數據結構掛鉤綁定上了,以後我們應用程式如果要操作這一個動態文件,只需要用這個文件描述符進行區分。

2、文件描述符的作用域就是當前進程,出了當前進程這個文件描述符就沒有意義了

 

實時查man手冊

(1)當我們寫應用程式時,很多API原型都不可能記得,所以要實時查詢,用man手冊

(2)man 1 xx查linux shell命令,man 2 xxx查API, man 3 xxx查庫函數

 

讀取文件內容

ssize_t read(int fd, void *buf, size_t count);

fd表示要讀取哪個文件,fd一般由前面的open返回得到

buf是應用程式自己提供的一段記憶體緩衝區,用來存儲讀出的內容

count是我們要讀取的位元組數

返回值ssize_t類型是linux內核用typedef重定義的一個類型(其實就是int),返回值表示成功讀取的位元組數。

 

exit、_exit、_Exit退出進程

(1)當我們程式在前面步驟操作失敗導致後面的操作都沒有可能進行下去時,應該在前面的錯誤監測中結束整個程式,不應該繼續讓程式運行下去了。

(2)我們如何退出程式?

第一種;在main用return,一般原則是程式正常終止return 0,如果程式異常終止則return -1。

第一種:正式終止進程(程式)應該使用exit或者_exit或者_Exit之一

open函數的flag詳解:

讀寫許可權:O_RDONLY O_WRONLY O_RDWR

O_RDONLY就表示以只讀方式打開,

O_WRONLY表示以只寫方式打開,

O_RDWR表示以可讀可寫方式打開

當我們附帶了許可權後,打開的文件就只能按照這種許可權來操作

 

打開存在並有內容的文件時:O_APPEND、O_TRUNC

O_APPEND屬性去打開文件時,如果這個文件中本來是有內容的,則新寫入的內容會接續到原來內容的後面;

O_TRUNC屬性去打開文件時,如果這個文件中本來是有內容的,則原來的內容會被丟棄

 

 1 fd = open("a.txt", O_RDWR | O_APPEND | O_TRUNC);
 2     if (-1 == fd)        // 有時候也寫成: (fd < 0)
 3     {
 4         printf("文件打開錯誤\n");
 5         // return -1;
 6         _exit(-1);
 7     }
 8     else
 9     {
10         printf("文件打開成功,fd = %d.\n", fd);
11     } 

 

打開不存在的文件時:O_CREAT、O_EXCL

open中加入O_CREAT後,不管原來這個文件存在與否都能打開成功,如果原來這個文件不存在則創建一個空的新文件,如果原來這個文件存在則會重新創建這個文件,原來的內容會被消除掉;

O_EXCL標誌和O_CREAT標誌結合使用時,則沒有文件時創建文件,有這個文件時會報錯提醒我們;

open函數在使用O_CREAT標誌去創建文件時,可以使用第三個參數mode來指定要創建的文件的許可權。mode使用4個數字來指定許可權的,其中後面三個很重要,對應我們要創建的這個文件的許可權標誌。譬如一般創建一個可讀可寫不可執行的文件就用0666

 

 1     fd = open("a.txt", O_RDWR | O_CREAT | O_EXCL, 0666);
 2     if (-1 == fd)        // 有時候也寫成: (fd < 0)
 3     {
 4         perror("文件打開錯誤");
 5         _exit(-1);
 6     }
 7     else
 8     {
 9         printf("文件打開成功,fd = %d.\n", fd);
10     }

 

O_NONBLOCK

(1)阻塞與非阻塞。如果一個函數是阻塞式的,則我們調用這個函數時當前進程有可能被卡住(阻塞住,實質是這個函數內部要完成的事情條件不具備,當前沒法做,要等待條件成熟),函數被阻塞住了就不能立刻返回;如果一個函數是非阻塞式的那麼我們調用這個函數後一定會立即返回,但是函數有沒有完成任務不一定。

(2)阻塞和非阻塞是兩種不同的設計思路,並沒有好壞。總的來說,阻塞式的結果有保障但是時間沒保障;非阻塞式的時間有保障但是結果沒保障。

(3)操作系統提供的API和由API封裝而成的庫函數,有很多本身就是被設計為阻塞式或者非阻塞式的,所以我們應用程度調用這些函數的時候心裡得非常清楚。

(4)我們打開一個文件預設就是阻塞式的,如果你希望以非阻塞的方式打開文件,則flag中要加O_NONBLOCK標誌。

(5)只用於設備文件,而不用於普通文件。

errno和perror

(1)errno就是error number,意思就是錯誤號碼。linux系統中對各種常見錯誤做了個編號,當函數執行錯誤時,函數會返回一個特定的errno編號來告訴我們這個函數到底哪裡錯了。

(2)linux系統提供了一個函數perror(意思print error),perror函數內部會讀取errno並且將這個不好認的數字直接給轉成對應的錯誤信息字元串,然後print列印出來。

 

read和write的count

(1)count和返回值的關係:count參數表示我們想要寫或者讀的位元組數,返回值表示實際完成的要寫或者讀的位元組數。實現的有可能等於想要讀寫的,也有可能小於(說明沒完成任務)

(2)count再和阻塞非阻塞結合起來,就會更加複雜。如果一個函數是阻塞式的,則我們要讀取30個,結果暫時只有20個時就會被阻塞住,等待剩餘的10個可以讀。

(3)有時候我們寫正式程式時,我們要讀取或者寫入的是一個很龐大的文件(譬如文件有2MB),我們不可能把count設置為2*1024*1024,而應該去把count設置為一個合適的數字(譬如2048、4096),然後通過多次讀取來實現全部讀完。

 

 1 ret = write(fd, writebuf, strlen(writebuf));
 2     if (ret < 0)
 3     {
 4         //printf("write失敗.\n");
 5         perror("write失敗");
 6         _exit(-1);
 7     }
 8     else
 9     {
10         printf("write成功,寫入了%d個字元\n", ret);
11     }

 

文件IO效率和標準IO

(1)文件IO就指的是open、close、write、read等API函數構成的一套用來讀寫文件的體系,這套體系可以很好的完成文件讀寫,但是效率並不是最高的。

(2)應用層C語言庫函數提供了一些用來做文件讀寫的函數列表,叫標準IO。標準IO由一系列的C庫函數構成(fopen、fclose、fwrite、fread),這些標準IO函數其實是由文件IO封裝而來的(fopen內部其實調用的還是open,fwrite內部還是通過write來完成文件寫入的)。標準IO加了封裝之後主要是為了在應用層添加一個緩衝機制,這樣我們通過fwrite寫入的內容不是直接進入內核中的buf,而是先進入應用層標準IO庫自己維護的buf中,然後標準IO庫自己根據操作系統單次write的最佳count來選擇好的時機來完成write到內核中的buf(內核中的buf再根據硬碟的特性來選擇好的實際去最終寫入硬碟中)。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 同步發佈:http://www.yuanrengu.com/index.php/mysqlsolvetimestamp.html 在使用mysql時,如果資料庫中的欄位類型是timestamp,預設為0000-00-00,會發生異常:Value ‘0000-00-00 00:00:00’ can n ...
  • DBMS_NETWORK_ACL_ADMIN學習 轉載 http://blog.sina.com.cn/s/blog_4f925fc30102e2se.html 標簽: oracle it 分類: 資料庫 http://docs.oracle.com/cd/B28359_01/appdev.111/ ...
  • 一、資料庫的簡介 什麼是資料庫? 數據的倉庫,如:在atm的實例中我們創建一個db目錄稱之為資料庫 什麼是 MySQL、Oracle、SQLite、Access、MS SQL Server等 ? 他們是資料庫軟體,主要功能為兩部分:1、講數據保存到記憶體或者文件。2、接受特定的命令對數據進行操作 什麼 ...
  • 使用PlateSpin複製出來的一資料庫伺服器(Oracle 10g)在啟動資料庫實例時遇到“ORA-00600: internal error code, arguments: [4194].....”錯誤,實例在啟動後,會自然Down掉。具體情況如下所示: Successfully online... ...
  • Windows環境配置MySQL集群 一、Cluster環境搭建 1、mysql Cluster(MySQL Cluster 7.5.4)文件下載地址:http://dev.mysql.com/downloads/cluster/ 2、準備三台伺服器(虛擬機,本人使用的是Windows Server ...
  • 1. 索引(Index) 索引是快速的定位和查找數據。索引分為: 聚集索引:唯一,預設主鍵,一般選取比較連貫的欄位,聚集索引是物理排序。 非聚集索引: 並沒有把數據物理排序,只是多了一個索引頁(包括索引項+存儲位置row number) a. 新建“非聚集索引” b. 選擇“專業”創建非聚集性索引。 ...
  • Hey,大家好!我是CrazyCatJack。今天我來說幾個在嵌入式開發中常用的C語言技巧吧。也許你曾經用過,也許你只是見到過但是沒有深入理解。那麼今天好好補充下吧^_^ 1.指向函數的指針 指針不光能指向變數、字元串、數組,還能夠指向函數。在C語言中允許將函數的入口地址賦值給指針。這樣就可以通過指 ...
  • 轉自:http://www.cnblogs.com/phoebus0501/archive/2010/12/14/1906144.html 1.確保RHEL5中已經安裝了yum [root@lvs-master ~]# rpm -qa |grep yumyum-metadata-parser-1.1 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...