Tôi có một chương trình mẫu nhỏ chỉ đơn giản là fopen
s tệp và sử dụng fgets
để đọc. Sử dụng strace
, tôi nhận thấy rằng lệnh gọi đầu tiên tới fgets
chạy một cuộc gọi hệ thống mmap
và sau đó đọc các cuộc gọi hệ thống được sử dụng để thực sự đọc nội dung của tệp. trên fclose
, tệp là munmap
ed. Nếu tôi thay vì mở đọc tập tin với mở/đọc trực tiếp, điều này rõ ràng là không xảy ra. Tôi tò mò về mục đích của mmap
này là gì và mục đích của nó là gì.Tại sao fopen/fgets sử dụng cả mmap và đọc các cuộc gọi hệ thống để truy cập dữ liệu?
Trên hệ thống dựa trên Linux 2.6.31 của tôi, khi có nhu cầu bộ nhớ ảo nặng, các đôi khi một vài giây sẽ bị treo trong một vài giây và có vẻ như không cần thiết.
Đoạn mã ví dụ:
#include <stdlib.h>
#include <stdio.h>
int main()
{
FILE *f;
if (NULL == (f=fopen("foo.txt","r")))
{
printf ("Fail to open\n");
}
char buf[256];
fgets(buf,256,f);
fclose(f);
}
Và đây là sản phẩm có liên quan strace khi mã trên được điều hành:
open("foo.txt", O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=9, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb8039000
read(3, "foo\nbar\n\n"..., 4096) = 9
close(3) = 0
munmap(0xb8039000, 4096) = 0
Thú vị. Vì vậy, từ điều này tôi thu thập rằng tất cả các hoạt động đọc trên FILE * không thực sự đọc vào bộ đệm được cung cấp, nhưng vào một bộ đệm bổ sung được phân bổ trên đống và sau đó sao chép vào bộ đệm của tôi. Ngoài ra, hiện malloc luôn luôn dẫn đến một cuộc gọi đến mmap? Tôi luôn nghĩ rằng heap được quản lý cục bộ trong không gian người dùng và các cuộc gọi hệ thống chỉ được thực hiện nếu thêm bộ nhớ cần thiết để được thêm vào không gian địa chỉ tiến trình. Tôi cũng luôn nghĩ rằng sbrk/brk đã được sử dụng cho việc này, chứ không phải là mmap. – bdk
@bdk: Có, các chức năng tập tin từ thư viện chuẩn (không phải các cuộc gọi hệ thống) đều giữ bộ đệm của riêng chúng để khi bạn gọi 'fgets (buf, 1, f)' liên tục trong một vòng lặp, nó không dẫn đến hàng trăm cuộc gọi hệ thống 'đọc'. 'malloc' dẫn đến' mmap' khi nó không có nhiều không gian hơn trong vùng người dùng - ví dụ, 'malloc (8)' đầu tiên có thể dẫn đến 'mmap (4096)', và hậu quả là 'malloc (8) ''s sẽ trả về con trỏ tới vùng đã được cấp phát cho đến khi nó bị cạn kiệt. –
Cảm ơn! Giải thích nó. Mỗi khi tôi sử dụng strace để cố gắng theo dõi một cái gì đó xuống tôi kết thúc học một cái gì đó mới. – bdk