IO có đệm và không đệm


83

Tôi được biết rằng theo mặc định I / O trong các chương trình được lưu vào bộ đệm, tức là chúng được phân phát từ bộ lưu trữ tạm thời đến chương trình yêu cầu. Tôi hiểu rằng bộ đệm cải thiện hiệu suất IO (có thể bằng cách giảm các lệnh gọi hệ thống). Tôi đã thấy các ví dụ về vô hiệu hóa bộ đệm, như setvbuftrong C. Sự khác biệt giữa hai chế độ là gì và khi nào thì nên sử dụng chế độ này so với chế độ kia?

Câu trả lời:


123

Bạn muốn đầu ra không có bộ đệm bất cứ khi nào bạn muốn đảm bảo rằng đầu ra đã được ghi trước khi tiếp tục. Một ví dụ là lỗi tiêu chuẩn trong thư viện thời gian chạy C - điều này thường được bỏ đệm theo mặc định. Vì lỗi là (hy vọng) không thường xuyên, bạn muốn biết về chúng ngay lập tức. Mặt khác, đầu ra tiêu chuẩn được lưu vào bộ đệm đơn giản vì người ta cho rằng sẽ có nhiều dữ liệu hơn đi qua nó.

Một ví dụ khác là thư viện ghi nhật ký. Nếu thông báo nhật ký của bạn được giữ trong bộ đệm trong quy trình của bạn và quy trình của bạn kết xuất lõi, thì rất có khả năng đầu ra sẽ không bao giờ được ghi.

Ngoài ra, không chỉ các lệnh gọi hệ thống được giảm thiểu mà còn cả I / O đĩa. Giả sử một chương trình đọc một tệp một byte tại một thời điểm. Với đầu vào không có bộ đệm, bạn sẽ đi ra đĩa (tương đối rất chậm) cho mỗi byte mặc dù nó có thể phải đọc toàn bộ khối (bản thân phần cứng đĩa có thể có bộ đệm nhưng bạn vẫn đi ra bộ điều khiển đĩa sẽ chậm hơn so với truy cập trong bộ nhớ).

Bằng cách lưu vào bộ đệm, toàn bộ khối được đọc vào bộ đệm cùng một lúc sau đó các byte riêng lẻ được chuyển đến bạn từ vùng đệm (trong bộ nhớ, cực kỳ nhanh).

Hãy nhớ rằng bộ đệm có thể có nhiều dạng, chẳng hạn như trong ví dụ sau:

+-------------------+-------------------+
| Process A         | Process B         |
+-------------------+-------------------+
| C runtime library | C runtime library | C RTL buffers
+-------------------+-------------------+
|               OS caches               | Operating system buffers
+---------------------------------------+
|      Disk controller hardware cache   | Disk hardware buffers
+---------------------------------------+
|                   Disk                |
+---------------------------------------+

Biểu đồ thật tuyệt vời. Một điều đáng nói là FILEbộ đệm nội bộ của một đối tượng (một luồng) hoàn toàn khác với một fgetstham số bộ đệm bắt buộc. Điều này chỉ làm tôi bối rối trong nhiều giờ trước khi tôi viết một số mã để tìm ra nó. QAQ
Rick

35

Bạn muốn đầu ra không có bộ đệm khi bạn đã có một chuỗi byte lớn sẵn sàng để ghi vào đĩa và muốn tránh một bản sao thừa vào bộ đệm thứ hai ở giữa.

Các luồng đầu ra có bộ đệm sẽ tích lũy các kết quả ghi vào một bộ đệm trung gian, chỉ gửi nó đến hệ thống tệp OS khi đã tích lũy đủ dữ liệu (hoặc flush()được yêu cầu). Điều này làm giảm số lượng các cuộc gọi hệ thống tệp. Vì các lệnh gọi hệ thống tệp có thể tốn kém trên hầu hết các nền tảng (so với ngắn hạn memcpy), đầu ra được đệm là một chiến thắng thực sự khi thực hiện một số lượng lớn các lần ghi nhỏ. Đầu ra không có bộ đệm thường tốt hơn khi bạn đã có bộ đệm lớn để gửi - việc sao chép vào bộ đệm trung gian sẽ không làm giảm số lượng lệnh gọi HĐH hơn nữa và giới thiệu thêm công việc.

Đầu ra không có bộ đệm không liên quan gì đến việc đảm bảo dữ liệu của bạn đến được đĩa; chức năng đó được cung cấp bởi flush()và hoạt động trên cả luồng có bộ đệm và không có bộ đệm. Việc ghi IO không có bộ đệm không đảm bảo dữ liệu đã vào đĩa vật lý - hệ thống tệp OS có quyền lưu giữ bản sao dữ liệu của bạn vô thời hạn, không bao giờ ghi nó vào đĩa, nếu nó muốn. Nó chỉ được yêu cầu để cam kết nó vào đĩa khi bạn gọi flush(). (Lưu ý rằng close()sẽ gọi flush()thay mặt bạn).


Gọi điện có flush()đảm bảo nó được ghi vào đĩa không? Tôi nghĩ rằng chỉ chuyển nó cùng với bộ đệm của đĩa.
jrdioko

2
Bạn cần O_SYNCphải đảm bảo để đảm bảo viết.
moshbear

Không có bộ đệm IO ks về việc được ghi vào đĩa. Do đó, thuật ngữ unbuffered (không có bộ đệm trung gian nhưng được ghi trực tiếp vào đĩa) cho winapi, bạn gọi CreateFile với FILE_FLAG_NO_BUFFERING và FILE_FLAG_WRITE_THROUGH để đảm bảo dữ liệu đi trực tiếp ổn định sau mỗi lần ghi. Đối với một số hệ điều hành khác idont biết.
Martin Kosicky
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.