--- tags: sp --- # 檔案的輸入輸出 ## file - file hole - 值為0,但不會佔據實際空間 - 可用 lseek 製造 - 檔案指標 - 代表目前在對該位置做操作 - 改變檔案指標位置:read、write、lseek ## open & close file ### 代號 - 0: stdin - 1: stdout(有優化/有buf) - 2: stderr (無buf) ### open file headerfile: `#include <fcntl.h>` 用法: `int open(const char *pathname, int flags);` or `int open(const char *pathname, int flags, mode_t mode);` - 回傳值:file descriptor(可用的最小數字),-1為錯誤 - flags: `O_RDONLY` 讀、`O_WRONLY` 寫、`O_RDWR` 讀寫 (三者需擇一) `O_CREAT` 製造檔案 (選用) `O_APPEND` 資料加到檔案最後面 `O_TRUNC` 將檔案大小歸0,可以保證不會有舊資料 `O_CLOEXEC` 使用execve時自動關閉檔案 - mode: `S_IRWXU` 檔案擁有者可讀、寫、執行 `S_IRUSR` 檔案擁有者可讀 `S_IWUSR` 檔案擁有者可寫 `S_IXUSR` 檔案擁有者可執行 - ex : `open(fileName,O_RDONLY);` ### close file `int close(int fd)` - 回傳值:0為成功,-1為錯誤 - 可以讓作業系統釋放資源 - ex : `close(fileFd)` ## file IO header file: `#include <unistd.h>` ### read 用法: `ssize_t read(int fd, void *buf, size_t len)` - 從 fd 讀 len 個位元組到 buf - 回傳值:成功回傳讀到的位元組數(EOF為0),錯誤回傳-1 ### write 用法: `ssize_t write(int fd, const void *buf, size_t len);` - 從 buf 寫 len 個位元組到 fd - 回傳值:成功回傳寫入的位元組數,錯誤回傳-1 - 不支援file hole(會用0填滿) ### perror 用法: `void perror(const char *s);` - 印出字串 **s** 後還會印出os的詳細訊息(errno) > erron : 系統內的錯誤訊息代碼,發生錯誤時會把錯誤寫入 ### lseek 改變檔案指標位置 header file: `#include <unistd.h>` 用法: `off_t lseek(fd, offset, WHENCE)` - offset : 偏移量 - WHENCE : 從哪開始偏移,參數有: SEEK_SET(檔案最一開始), SEEK_CUR(現在位子), SEEK_END(檔案結尾)) - 回傳值:回傳現在位子(從檔案開始的偏移值)(錯誤:回傳-1,errno為1) - ex : `lseek(fd,0,SEEK_END);` 從後面算起0個 - 進階用法 `#define _GNU_SOURSE` `off_t lseek(fd, offset, WHENCE)` - WHENCE多增加 SEEK_DATA(下一個有資料的位子), SEED_HOLE(下一個hole的位子) - 為虛擬指標偏移,不影響os ## copy file ### method 1: 使用 read, write - hole會用0取代,檔案會變大 ### method 2: 使用 SEEK_DATA , SEED_HOLE - 可製造出 hole ## sync - `void sync(void);` 把全部資料(包含meta-data)寫回硬碟 - `int fsync(int fd);` 將fd代表的檔案(包含meta-data)寫回硬碟 - `int fdatasync(int fd);` 將fd代表的檔案(不包含meta-data)寫回硬碟(速度較快) > meta-data : ex : 修改日期、檔案大小等 ## lock ### flock 良心鎖 (advisory locking) 整個檔案全部上鎖,可多人同時讀 `#include<sys/file.h>` `int flock(int fd, int operation);` - operation: `LOCK_SH` (share) 可以多個人同時(共享鎖) `LOCK_EX` (exclusive) 只能一人(排他鎖) `LOCK_UN` (unlock) - 回傳值:0為成功,-1為錯誤 (錯誤程式碼存於errno) ### lockf 強制鎖 (mandatory locking) 可以對檔案的一部份上鎖,只能一人讀(只有排他鎖,無共享鎖) `#include<sys/file.h>` `int lockf(int fd, int cmd, off_t len);` - cmd: `F_LOCK` 加鎖 `F_ULOCK` 解鎖 `F_TEST` 測試是否被上鎖,沒被上鎖回傳0,被上鎖回傳-1 - len: 從當前位置開始要上鎖的長度(byte) - 回傳值:0為成功,-1為錯誤(錯誤程式碼存於errno) >使用強制鎖前需先下以下指令: `sudo mount -oremount.mand /` 啟動強制鎖 `chmod g+s filename` `chmod g-x filename`