Linux 系統 IO之 open close 函數
文章目錄
1. open 函數族
1.1 頭文件包含
使用 Linux IO open 函數需要包含如下頭文件:
#include <sys/types.h>
//因爲形參用到了 mode_t 文件類型(文件創建模式),所以需要包含
#include <sys/stat.h>
#include fcntl.h>
Q:
額,記不住怎麼辦?
A:
使用命令 man 2 open
查看其幫助手冊,在幫助手冊中有所有需要包含的頭文件。
Q:
爲什麼是 man 2
,此處 2
是什麼意思?
A:
使用 man
命令可以查找常用的命令與系統調用的使用文檔,man
共有 9 個章節,其中第 2 章是系統調用(內核提供的函數)
,我們此處要查找的 open
函數正是 系統調用函數
因此精確查找時需要指定章節。如果不指定章節,man
命令會返回第一個找個的 open
該 open
可能不是第 2 章的 open
。
1.2 函數原型
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
int creat(const char *pathname, mode_t mode);
int openat(int dirfd, const char *pathname, int flags);
int openat(int dirfd, const char *pathname, int flags, mode_t mode);
1.3 函數功能
open
與 openat
函數均用來打開文件,如果文件不存在,則可以設置 O_CREAT
flag 新建文件。
creat
函數僅可以用來創建文件,該函數完全可以由 open
函數替代:
open(pathname, O_WRONLY | O_CREAT | O_TRUNC, mode);
open
與 openat
之間的區別是什麼?
- 如果
openat
函數的pathname
參數是絕對路徑,則參數dirfd
無效,此時openat
完全等同於open
。 - 如果
openat
與open
函數中pathname
路徑名都是相對路徑:
open
函數相對於程序所在目錄openat
函數則是相對於 文件描述符 dirfd 引用的目錄
- 如果
openat
函數pathname
是相對路徑,且dirfd
是特殊值AT_FDCWD
那麼此時pathname
相對於程序所在目錄
1.4 函數返回值
open
、creat
、openat
三個函數,如果執行成功,返回值爲成功打開/創建的文件描述符;如果失敗,系統會根據錯誤類型設置errno,並且此時函數返回值爲 -1。
1.5 形參解釋
const char *pathname
:是一個字符串常量,用於指定要打開/創建文件的路徑,此路徑可以是絕對路徑亦可以是相對路徑。int flag
:用於指定文件的讀寫權限於追加方式等。O_RDONLY
、O_WRONLY
orO_RDWD
三個讀寫權限必須選擇一個,分別表示:只讀
、只寫
、讀寫
。- 下列選項爲一些常用的配合上述讀寫權限的標誌,選擇多個使用 ** | ** 連接
選項 | 說明 |
---|---|
O_APPEND | 追加模式,寫至打開文件的尾部 |
O_CREAT | 若打開文件不存在,創建一個新文件 |
O_TRUNC | 截斷模式,可寫模式打開後該文件被清空重頭寫 |
O_NOCTTY | 如果文件爲終端,那麼終端不可以調用open系統調用的那個進程的控制終端 |
O_EXCL | 如果與 O_CREAT同時使用且文件存在,則返回錯誤消息 |
… | … |
mode_t mode
:指定文件的權限,如0777
,此時需要注意系統的umask
變量。例如我的 Ubuntu ,umask = 0002,此時0777
要與0002
的反碼進行與操作纔是最終的權限。int dirfd
:此處需要設計打開目錄相關的操作
,該參數用於指定,當前openat
函數所要相對的路徑。- 包含頭文件
#include <dirent.h>
DIR* dir = opendir("目錄名")
int dir_fd = dirfd(dir)
- 包含頭文件
1.6 案例程序
1.6.1 open 函數打開一個文件,若該文件不存在則新建
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h> // fclose
#include <stdlib.h> //exit
#include <stdio.h> //perror
int main()
{
int fd;
// 光標在 open 身上,2 shift + k 即可跳至幫助文檔
// 打開文件,若該文件不存在則創建新文件
fd = open("annNote", O_RDWR | O_CREAT, 0777);
if(fd == -1){
perror("create file");
exit(1);
}
// 關閉文件
int ret = close(fd);
if( ret == -1){
perror("close file");
exit(1);
}
return 0;
}
1.6.2 openat 函數根據相對路徑打開一個文件,若不存在則新建
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h> // fclose
#include <stdlib.h> // exit
#include <stdio.h> // perror
#include <dirent.h> // opendir closedir dirfd
int main()
{
// 指定相對路徑
DIR* dir = opendir("/home/annjeff");
int dir_fd = dirfd(dir);
int fd;
// 光標在 open 身上,2 shift + k 即可跳至幫助文檔
// 打開文件,若該文件不存在則創建新文件
fd = openat(dir_fd, "annNote.txt", O_RDWR | O_CREAT, 0777);
if(fd == -1){
perror("create file");
exit(1);
}
// 關閉文件
int ret = close(fd);
closedir(dir);
if( ret == -1){
perror("close file");
exit(1);
}
return 0;
}
2. close 函數
2.1 頭文件包含
#include <unistd.h>
2.2 函數原型
int close(int fd);
2.3 函數功能
close
函數用於關閉一個已經打開的文件描述符。
2.4 函數返回值
- 成功關閉已打開文件描述符,則返回0
- 關閉失敗,則按錯誤設置全局變量errno,返回 -1
2.4 形參解釋
int fd
:形參很簡單,即要關閉的已打開的文件描述符。