Try   HackMD

檔案的輸入輸出

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