C 語言打開一個文件時,緩衝區在內存的什麼位置?

C 打開一個文件時,會在內存中建立一個緩衝區與之對應。

我想問一下這個緩衝區在內存的什麼位置呢?

我們知道內存一般分為堆、棧、靜態存儲區等,這個緩衝區在什麼地方呢?

是不是堆、棧、靜態存儲區等都是對虛擬內存而言,而文件緩衝區就是直接載入到內存,和前面的沒有關係?


一般打開並讀取一個文件,傳統方法就是兩個系統調用,對吧:

int open (const char "*path", int "oflag", .../*,mode_t "mode" */);
ssize_t read(int fd, void *buf, size_t count);

這裡 read 有一個 buf 緩衝區,這個是由你的應用程序控制的,在你的應用程序虛擬內存地址空間中,究竟是 堆,還是棧,這個看你聲明 buf 時候是怎麼做的。

不過,內核中,也會有一個緩衝區,這個你的應用程序是看不見的,當你讀取時,內核會將數據放入自己的緩衝區,然後 copy 到用戶態你程序的緩衝區中。這個東西,在內核叫做 buffer cache,由IO 子系統管理,對於 Unix 系統來說,一般會預留最多 10% 作為 buffer cache 使用。

如果你使用的是 mmap 方法,則會有:

void * mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);

這一套過程與上面的 open/read 不同,是由內核分頁子系統管理的,說白了,就是用虛擬內存調頁的方式,將文件直接 map 到程序的地址空間中,這個 map 也是靠內核實現的,這東西叫做 page cache,你也知道虛擬內存限制少很多,可以 map 直到佔用全部內存。

傳統 read/write buffer cache 有個問題,就是一旦固定後,大小沒法調節,這樣分配多了就是浪費,分配少了就會造成很多的上下文切換做 copy 而且這個東西與分頁系統割裂。所以後來就出現了 Unified Buffer Cache,統一用 Page Cache 解決以上問題。

所以你指的緩衝區,那是在內核里的,不是棧,也不是堆,而是使用如 SLOB/SLAB/SLUB 分配器分配的 VMObjects


在用戶 空間的 棧 的下方, 堆的上方的 mmap區。

對於系統來說,應用程序的mmap區的 文件 可能在 操作系統的 pache cache中


sys_open並不會讀取文件,數據讀取是在sys_read時使用page cache讀取,屬於內核空間。

mmap是將內核空間里的page映射到進程空間。

至於mmap在進程空間里的地址,是屬於堆還是棧,我做了個測試

用程序映射了一個叫data的文件,分別列印了各類變數的地址,

mmap返回的這個指針不在堆里,也不在棧里,也不在靜態區。

stack : 0xbff58698
heap : 0x9939008
global : 0x80498d4
global static : 0x80498d8
static : 0x80498dc
mmap : 0xb7f0e000
003f5000-003f6000 r-xp 003f5000 00:00 0 [vdso]
004a3000-004bd000 r-xp 00000000 fd:00 1111383 /lib/ld-2.5.so
004bd000-004be000 r-xp 00019000 fd:00 1111383 /lib/ld-2.5.so
004be000-004bf000 rwxp 0001a000 fd:00 1111383 /lib/ld-2.5.so
004c5000-00604000 r-xp 00000000 fd:00 1111401 /lib/libc-2.5.so
00604000-00605000 --xp 0013f000 fd:00 1111401 /lib/libc-2.5.so
00605000-00607000 r-xp 0013f000 fd:00 1111401 /lib/libc-2.5.so
00607000-00608000 rwxp 00141000 fd:00 1111401 /lib/libc-2.5.so
00608000-0060b000 rwxp 00608000 00:00 0
08048000-08049000 r-xp 00000000 fd:02 507933 /zhangc/file/mmap/a.out
08049000-0804a000 rw-p 00000000 fd:02 507933 /zhangc/file/mmap/a.out
09939000-0995a000 rw-p 09939000 00:00 0 [heap]
b7ef6000-b7ef8000 rw-p b7ef6000 00:00 0
b7f0e000-b7f0f000 r--p 00000000 fd:02 507937 /zhangc/file/mmap/data
b7f0f000-b7f10000 rw-p b7f0f000 00:00 0
bff44000-bff59000 rw-p bffea000 00:00 0 [stack]

參考鏈接:

從文件 I/O 看 Linux 的虛擬文件系統

Linux 內核的文件 Cache 管理機制介紹


跟c語言沒太大關係,要看不同操作系統怎麼實現open的


推薦閱讀:

為何公鑰私鑰不可互相推導?
一個優秀的程序員應該學完哪些計算機理論的知識?
如何對集合中的數據進行壓縮?
谷歌從 Ingress 遊戲中搜集的地理數據有哪些用途,是否可能用于軍事?
該如何作一條已知曲線的等距曲線?

TAG:操作系統 | 演算法 | Linux | C編程語言 | 操作系統內核 |