前言
上一篇文章,主要講了文件描述符的基本知識(shí).這篇,我將會(huì)結(jié)合代碼,對(duì)上一節(jié)的 open,close函數(shù)進(jìn)行詳細(xì)的講解.
代碼 Git 地址 SuzhenProjects/ApueProject
常用函數(shù)復(fù)習(xí)
-
open打開(kāi)或者創(chuàng)建一個(gè)用來(lái)讀/寫(xiě)的文件 -
read讀取用戶指定的 Input -
write寫(xiě)入到指定的 Output -
lseek重新定位讀寫(xiě)游標(biāo)的位置 -
close刪除(關(guān)閉)一個(gè)文件描述符
Tips: 通過(guò) man 2 <Command> 可以查詢(xún)你系統(tǒng)的這些 API 檔案
Open 函數(shù) int open(const char *path, int oflag, ...);
-
path文件的路徑,如果文件不存在,則返回錯(cuò)誤 -
oflag打開(kāi)文件/目錄,所使用的用戶自定義選項(xiàng)-
O_RDONLY只讀 -
O_WRONLY只寫(xiě) -
O_RDWR讀/寫(xiě) -
O_NONBLOCK打開(kāi)文件時(shí)/讀取數(shù)據(jù)時(shí),不要阻塞調(diào)用 -
O_APPEND追加模式,write的內(nèi)容被追加到文檔的末尾 -
O_CREAT如果文件不存在,open會(huì)創(chuàng)建文件 -
O_TRUNC截?cái)辔募?使文件長(zhǎng)度為0 -
O_EXCL存在O_CREAT模式時(shí),如果文件存在,會(huì)返回錯(cuò)誤 -
O_SHLOCK自動(dòng)獲取flock的共享鎖 -
O_EXLOCK自動(dòng)獲取flock的獨(dú)占鎖 -
O_NOFOLLOW打開(kāi)文件的鏈接時(shí), 會(huì)失敗 -
O_SYMLINK運(yùn)行打開(kāi)文件的鏈接 -
O_EVTONLY用來(lái)監(jiān)視文件是否有改動(dòng) -
O_CLOEXEC標(biāo)記為close-on-exec
-
- 擴(kuò)展參數(shù)
- 可以傳入文件的權(quán)限標(biāo)志 如
0755,0666
- 可以傳入文件的權(quán)限標(biāo)志 如
- 返回值 成功會(huì)返回一個(gè)正整數(shù),其余均為失敗,需要檢查
errno
Close 函數(shù) int close(int fildes);
-
fildes文件描述符 - 返回值 成功會(huì)返回0,其余均為失敗,需要檢查
errno
Tips: 通過(guò)
strerror可以將errno轉(zhuǎn)換成可讀的字符串
實(shí)戰(zhàn) C++
一般我們使用
open打開(kāi)一個(gè)文件或者目錄后,必須使用close進(jìn)行釋放,否則會(huì)出現(xiàn)資源泄露.
(這就是很多語(yǔ)言?xún)?nèi)的Stream類(lèi)打開(kāi)后沒(méi)有關(guān)閉,會(huì)導(dǎo)致各種問(wèn)題的原因之一),所以我們一定要記住Open/Close 總是成對(duì)的使用
#include <unistd.h>
#include <fcntl.h>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cerrno>
int main(int argc, char **argv) {
constexpr char TargetFile[]{"NewFile.txt"};
int filefd = ::open(TargetFile, O_RDWR | O_CREAT, 0666);
if (filefd < 0) {
printf("open failed ! err :%s\n", strerror(errno));
return 1;
}
printf("open success , fd = %d\n", filefd);
::close(filefd);
return EXIT_SUCCESS;
}
實(shí)戰(zhàn) Golang
相比
C++版本調(diào)用的繁瑣,Golang提供了更加人性化的os.OpenFile函數(shù),該函數(shù)有兩個(gè)返回值.成功時(shí),返回一個(gè)文件指針,錯(cuò)誤設(shè)置為nil,失敗時(shí),文件指針為nil,此時(shí)要讀取錯(cuò)誤信息,并通知用戶.
package main
import (
"os"
"fmt"
)
const (
NewFile = "NewFile.txt"
)
func main() {
fptr, err := os.OpenFile(NewFile, os.O_RDWR|os.O_CREATE, 0666)
if err != nil{
fmt.Println(err.Error())
return
}
fptr.Close()
}
總結(jié)
C++版本的看懂后,Golang 版本是不是也一目了然了,每行發(fā)生了什么事情,心中都有數(shù)了.我們可以做一個(gè)類(lèi)推,Python 的open,close也一定是這個(gè)原理.這些語(yǔ)言封裝了更好的異常處理,方便程序員去處理 open,close 發(fā)生的問(wèn)題.最重要的一點(diǎn)是 open 和close必須成對(duì)的被使用!!!