Linux系統呼叫之I/O操作
阿新 • • 發佈:2019-02-06
一、檔案描述符
在 Linux 的世界裡,一切裝置皆檔案。我們可以系統呼叫中 I/O 的函式(I:input,輸入;O:output,輸出),對檔案進行相應的操作( open()、close()、write() 、read() 等)。
開啟現存檔案或新建檔案時,系統(核心)會返回一個檔案描述符,檔案描述符用來指定已開啟的檔案。這個檔案描述符相當於這個已開啟檔案的標號,檔案描述符是非負整數,是檔案的標識,操作這個檔案描述符相當於操作這個描述符所指定的檔案。
程式執行起來後(每個程序)都有一張檔案描述符的表,標準輸入、標準輸出、標準錯誤輸出裝置檔案被開啟,對應的檔案描述符 0、1、2 記錄在表中。程式執行起來後這三個檔案描述符是預設開啟的:
#define STDIN_FILENO 0 //標準輸入的檔案描述符
#define STDOUT_FILENO 1 //標準輸出的檔案描述符
#define STDERR_FILENO 2 //標準錯誤的檔案描述符
上面3個常量定義在/usr/include/unistd.h中。
在程式執行起來後開啟其他檔案時,系統會返回檔案描述符表中最小可用的檔案描述符,並將此檔案描述符記錄在表中。Linux 中一個程序最多隻能開啟 NR_OPEN_DEFAULT (即1024)個檔案,故當檔案不再使用時應及時呼叫 close() 函式關閉檔案。
二、常用 I/0 函式
需要的標頭檔案:
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <unistd.h>
int open(const char *pathname, int flags, mode_t mode);
功能:
開啟檔案,如果檔案不存在則建立。
引數:
pathname: 檔案的路徑及檔名。
返回值:flags: 開啟檔案的行為標誌,如,以只讀方式(O_RDONLY,第一個為字母不是零)開啟,以讀寫或新建新檔案的方式(O_RDWR|O_CREAT
)開啟。
mode: 這個引數,只有在檔案不存在時有效,指新建檔案時指定檔案的許可權(檔案許可權詳情,請點此連結)。
成功:成功返回開啟的檔案描述符
失敗:-1int close(int fd);
功能:
關閉已開啟的檔案
引數:
fd: 檔案描述符,open()的返回值
返回值:
成功:0失敗:-1
ssize_t write(int fd, const void *addr, size_t count);
功能:
把指定數目的資料寫到檔案(fd)
引數:
fd: 檔案描述符addr: 資料首地址count: 寫入資料的長度(位元組),一般情況下,資料有多少,就往檔案裡寫多少,不能多也不能少
返回值:
成功:實際寫入資料的位元組個數失敗:-1
ssize_t read(int fd, void *addr, size_t count);
功能:
把指定數目的資料讀到記憶體(緩衝區)
引數:
fd: 檔案描述符addr: 記憶體首地址count: 讀取的位元組個數
返回值:
成功:實際讀取到的位元組個數失敗:-1
三、實戰篇
接下來,我們使用以上 4 個系統呼叫 I/O 函式寫一個程式,能實現像系統命令 cp 的功能:
例項程式碼如下:
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- int main(int argc, char *argv[])
- {
- if((argc == 3) && (strcmp(argv[1], argv[2]) != 0))
- {// 保證有 3 個引數,而且原始檔和目的檔名字不能一樣
- int fd_src, fd_dest, len;
- //只讀方式開啟原始檔
- fd_src = open(argv[1], O_RDONLY);
- if(fd_src < 0)
- {
- perror("open argv[1]");
- return -1;
- }
- // 新建目的檔案
- fd_dest = open(argv[2], O_WRONLY|O_CREAT, 0755);
- if(fd_dest < 0)
- {
- close(fd_src);
- perror("open argv[2]");
- return -1;
- }
- do
- {
- char buf[1024] = {0};
- // 從原始檔讀取資料
- len = read(fd_src, buf, sizeof(buf));
- // 把資料寫到目的檔案,注意最後一個引數,有多少寫多少
- write(fd_dest, buf, len);
- }while(len > 0);
- // 關閉已開啟的檔案
- close(fd_src);
- close(fd_dest);
- }
- return 0;
- }
執行結果: