轉自:https://www.cnblogs.com/Jimmy1988/p/7479856.html
用戶態和內核態
程序代碼的依賴和調用關系如下圖所示:
- Lib:標準ASCI C函數,幾乎所有的平臺都支持該庫函數,因此依賴該庫的程序可移植性好;
- System Function:系統調用函數,與系統內核進行交互,不同平臺具備不同的函數接口,因此可移植性較差
區分用戶態和內核態主要是由于系統資源的有限性,不能無限制的隨意分配給用戶使用,必須由系統進行統一管理
- User mode:不能直接對系統資源進行訪問,如果要操作系統資源,必須轉化為內核態
- Kernel mode:管理系統資源,可直接對系統資源進行控制和訪問
內核為用戶提供了統一的API供其使用,不同的系統的API接口不同,為了便于代碼的移植,出臺了POSIX標準,類Unix系統(Unix、Linux、BSD、SunOS等)均支持該標準。
文件流與文件描述符
-
問題:
由上圖我們可看到,每執行一次系統調用,都要涉及到CPU狀態的切換,即從用戶態切換到內核態,即從用戶空間切換到內核空間,實現上下文切換的過程,會消耗相當一部分的CPU資源,因此頻繁的磁盤訪問對程序的執行效率將造成很大影響。 -
解決方案:
為了解決以上的難題,采用了緩沖區
的概念,當對磁盤文件進行操作時,可一次性從磁盤文件中讀出大量的數據暫放到緩沖區中,以后對這部分數據的訪問就不需要再進行系統調用了;當對文件行操作后,可將處理后的數據暫存到輸出緩沖區,待文件緩沖區滿后,一次性寫入到磁盤。
以上,數據的輸入輸出就像是水在流動一樣,因此我們采用了流
的概念。
-
文件流?:
簡單來說就是建立在面向對象基礎上的一種抽象的處理數據的工具。在流中,定義了一些處理數據的基本操作,如讀取數據,寫入數據等,程序員是對流進行所有操作的,而不用關心流的另一頭數據的真正流向;
文件流用結構體表示:struct FILE
.
FILE的結構體又是怎么樣的呢?我們可以進行查找一下:[niesh@niesh ~]$ vim /usr/include/stdio.h
我們看到了?stdio.h
的文件中有一行:
__BEGIN_NAMESPACE_STD/* The opaque type of streams. This is the definition used elsewhere. */typedef struct _IO_FILE FILE; __END_NAMESPACE_STD
顯然,FILE
?是?_IO_FILE
的類型替換,那么我們找一下?_IO_FILE
在哪里呢?
[niesh@niesh ~]$ grep -rn "\<_IO_FILE\>" /usr/include/
/usr/include/c++/4.8.2/streambuf:178: * This is based on _IO_FILE, just reordered to be more consistent, /usr/include/libio.h:145:struct _IO_jump_t; struct _IO_FILE; /usr/include/libio.h:163: struct _IO_FILE *_sbuf; /usr/include/libio.h:246:struct _IO_FILE { //此處正解 /usr/include/libio.h:267: struct _IO_FILE *_chain; /usr/include/libio.h:291: struct _IO_FILE _file; /usr/include/libio.h:299: struct _IO_FILE *_freeres_list; /usr/include/libio.h:316:typedef struct _IO_FILE _IO_FILE; /usr/include/libio.h:325:#define _IO_stdin ((_IO_FILE*)(&_IO_2_1_stdin_)) /usr/include/libio.h:326:#define _IO_stdout ((_IO_FILE*)(&_IO_2_1_stdout_)) /usr/include/libio.h:327:#define _IO_stderr ((_IO_FILE*)(&_IO_2_1_stderr_)) /usr/include/libio.h:329:extern _IO_FILE *_IO_stdin attribute_hidden; /usr/include/libio.h:330:extern _IO_FILE *_IO_stdout attribute_hidden; /usr/include/libio.h:331:extern _IO_FILE *_IO_stderr attribute_hidden; /usr/include/libio.h:391:extern int __underflow (_IO_FILE *); /usr/include/libio.h:392:extern int __uflow (_IO_FILE *); /usr/include/libio.h:393:extern int __overflow (_IO_FILE *, int); /usr/include/libio.h:395:extern _IO_wint_t __wunderflow (_IO_FILE *); /usr/include/libio.h:396:extern _IO_wint_t __wuflow (_IO_FILE *); /usr/include/libio.h:397:extern _IO_wint_t __woverflow (_IO_FILE *, _IO_wint_t); /usr/include/libio.h:435:extern int _IO_getc (_IO_FILE *__fp); /usr/include/libio.h:436:extern int _IO_putc (int __c, _IO_FILE *__fp); /usr/include/libio.h:437:extern int _IO_feof (_IO_FILE *__fp) __THROW; /usr/include/libio.h:438:extern int _IO_ferror (_IO_FILE *__fp) __THROW; /usr/include/libio.h:440:extern int _IO_peekc_locked (_IO_FILE *__fp); /usr/include/libio.h:446:extern void _IO_flockfile (_IO_FILE *) __THROW; /usr/include/libio.h:447:extern void _IO_funlockfile (_IO_FILE *) __THROW; /usr/include/libio.h:448:extern int _IO_ftrylockfile (_IO_FILE *) __THROW; /usr/include/libio.h:465:extern int _IO_vfscanf (_IO_FILE * __restrict, const char * __restrict, /usr/include/libio.h:467:extern int _IO_vfprintf (_IO_FILE *__restrict, const char *__restrict, /usr/include/libio.h:469:extern _IO_ssize_t _IO_padn (_IO_FILE *, int, _IO_ssize_t); /usr/include/libio.h:470:extern _IO_size_t _IO_sgetn (_IO_FILE *, void *, _IO_size_t); /usr/include/libio.h: