Linux下對文件操作有兩種方式:系統調用(system call)和庫函數調用(Library functions)
fork完後:
(1)有兩個返回值,子進程返回0,父進程返回子進程的id
(2)父子進程誰先運行不確定,由調度系統說了算,但是期望子進程先退出,並且父進程在子進程退出時讀取子進程的狀態
(3)代碼區域: 打印與循環的關係,例如父子進程各自++,第一次打印2個,第二次由2變4,一共打印6次
Fopen(標準C庫函數提供)——返回值是FILE*
FILE* stdin: 輸入 輸入設備:鍵盤 默認打開文件的描述符:0
FILE* stdout: 輸出 輸出設備:顯示器 默認打開文件的描述符:1
FILE* stderror: 錯誤 輸入設備:顯示器 默認打開文件的描述符:2
open(系統調用提供)——返回值new file descriptor(fd)、-1、error
fwrite(有緩衝區):由C語言提供緩衝區,默認爲行緩衝,遇到換行符就刷新,但是當重定向到文件時,變成全緩衝,就不刷新,直到緩衝區寫滿。fork前:暫存在於父進程緩衝區中不刷新,fork後:父進程複製到子進程,此時將緩衝區也複製過去。當進程終止時再刷新緩衝區
write(無緩衝區)
1。系統調用
系統調用提供的函數如open, close, read, write, ioctl等,需包含頭文件unistd.h。以write爲例:其函數原型爲 size_t write(int fd, const void *buf, size_t nbytes),其操作對象爲文件描述符或文件句柄fd(file descriptor),要想寫一個文件,必須先以可寫權限用open系統調用打開一個文件,獲得所打開文件的fd,例如 fd=open(/"/dev/video/", O_RDWR)。fd是一個整型值,每新打開一個文件,所獲得的fd爲當前最大fd加1。Linux系統默認分配了3個文件描述符值:0- standard input,1-standard output,2-standard error。系統調用通常用於底層文件訪問(low-level file access),例如在驅動程序中對設備文件的直接訪問。系統調用是操作系統相關的,因此一般沒有跨操作系統的可移植性
系統調用發生在內核空間,因此如果在用戶空間的一般應用程序中使用系統調用來進行文件操作,會有用戶空間到內核空間切換的開銷。事實上,即使在用戶空間使用庫函數來對文件進行操作,因爲文件總是存在於存儲介質上,因此不管是讀寫操作,都是對硬件(存儲器)的操作,都必然會引起系統調用。也就是說,庫函數對文件的操作實際上是通過系統調用來實現的。例如C庫函數fwrite()就是通過write()系統調用來實現的。這樣的話,使用庫函數也有系統調用的開銷,爲什麼不直接使用系統調用呢?這是因爲,讀寫文件通常是大量的數據(這種大量是相對於底層驅動的系統調用所實現的數據操作單位而言),這時,使用庫函數就可以大大減少系統調用的次數。這一結果又緣於緩衝區技術。在用戶空間和內核空間,對文件操作都使用了緩衝區,例如用 fwrite寫文件,都是先將內容寫到用戶空間緩衝區,當用戶空間緩衝區滿或者寫操作結束時,纔將用戶緩衝區的內容寫到內核緩衝區,同樣的道理,當內核緩衝區滿或寫結束時纔將內核緩衝區內容寫到文件對應的硬件媒介。
2。庫函數調用
標準C庫函數提供的文件操作函數如fopen, fread, fwrite, fclose, fflush, fseek等,需包含頭文件stdio.h。以fwrite爲例,其函數原型爲size_t fwrite(const void *buffer, size_t size, size_t item_num, FILE *pf),其操作對象爲文件指針FILE *pf,要想寫一個文件,必須先以可寫權限用fopen函數打開一個文件,獲得所打開文件的FILE結構指針pf,例如pf=fopen(/ "~/proj/filename/", /"w/")。實際上,由於庫函數對文件的操作最終是通過系統調用實現的,因此,每打開一個文件所獲得的FILE結構指針都有一個內核空間的文件描述符 fd與之對應。同樣有相應的預定義的FILE指針:stdin-standard input,stdout-standard output,stderr-standard error。庫函數調用通常用於應用程序中對一般文件的訪問。庫函數調用是系統無關的,因此可移植性好。由於庫函數調用是基於C庫的,因此也就不可能用於內核空間的驅動程序中對設備的操作。