1. 程式人生 > >Linux系統程式設計——系統呼叫之 I/O 操作(檔案操作)

Linux系統程式設計——系統呼叫之 I/O 操作(檔案操作)

一、檔案描述符

在 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: 這個引數,只有在檔案不存在時有效,指新建檔案時指定檔案的許可權(檔案許可權詳情,請點此連結)。

返回值:

成功:成功返回開啟的檔案描述符
失敗:-1

int 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;
}

執行結果:


相關推薦

no