Đây là một bài viết cũ, tuy nhiên, tôi vẫn sẽ tự do đưa ra những suy nghĩ của tôi ở đây.
Bắt đầu từ bên dưới, trước tiên Linux sẽ chia bộ nhớ thành các trang (thường là 4K trên mỗi trang trên hệ thống x86_64). Sau đó, bộ nhớ ảo được tạo, có ánh xạ được thực hiện với bộ nhớ vật lý bằng MMU (Bộ quản lý bộ nhớ).
Các quy trình được phân bổ bộ nhớ từ vùng bộ nhớ ảo, vì vậy xin lưu ý, khi bạn xem / Proc / meminfo, bạn sẽ thấy VMalloc * là chi tiết bộ nhớ ảo.
Hãy nói rằng bạn có một quy trình yêu cầu bộ nhớ (giả sử 300MB - trình duyệt web). Quá trình sẽ được phân bổ 300 MB từ bộ nhớ ảo, tuy nhiên, không cần thiết nó được ánh xạ bộ nhớ (được ánh xạ tới bộ nhớ vật lý). Có khái niệm "Sao chép ghi" để quản lý bộ nhớ, theo đó, nếu các quy trình của bạn thực sự sử dụng bộ nhớ được phân bổ từ bộ nhớ ảo (nghĩa là nó ghi vào bộ nhớ), chỉ sau đó nó được ánh xạ vào bộ nhớ vật lý. Điều này hỗ trợ kernel hoạt động tốt trong môi trường nhiều quá trình một cách hiệu quả.
Bộ nhớ cache là gì?
Rất nhiều bộ nhớ được sử dụng bởi các quy trình được chia sẻ. Hãy nói rằng thư viện glibc được sử dụng bởi hầu hết các quy trình. Điểm lưu giữ nhiều bản sao của glibc trong bộ nhớ là gì, khi mọi quá trình có thể truy cập cùng một vị trí bộ nhớ và thực hiện công việc. Các tài nguyên được sử dụng thường xuyên như vậy được giữ trong bộ đệm để khi xử lý yêu cầu, chúng có thể được tham chiếu đến cùng một vị trí bộ nhớ. Điều này giúp tăng tốc quá trình, vì đọc lại glibc (v.v.) từ đĩa sẽ tốn thời gian.
Ở trên là cho các thư viện chia sẻ mỗi lần nói, tương tự cũng đúng với việc đọc tệp. Nếu bạn đọc một tệp lớn (giả sử 100-200MB) lần đầu tiên, sẽ mất rất nhiều thời gian. Tuy nhiên, khi bạn cố gắng và làm lại đọc tương tự, nó sẽ nhanh hơn. Dữ liệu được lưu trong bộ nhớ và việc đọc lại không được thực hiện cho tất cả các khối.
Bộ đệm là gì?
Liên quan đến bộ đệm, khi một tiến trình thực hiện I / O, nó dựa vào bộ đệm của kernel để ghi dữ liệu vào đĩa. Các quy trình, yêu cầu kernel để thực hiện công việc. Vì vậy, thay mặt cho quá trình, kernel ghi dữ liệu vào "bộ đệm" của nó và báo cho quá trình rằng việc ghi được thực hiện. Theo cách không đồng bộ, kernel sẽ tiếp tục đồng bộ dữ liệu này trong bộ đệm vào đĩa. Theo cách này, các quy trình dựa vào kernel để chọn thời gian chính xác để đồng bộ dữ liệu vào đĩa và các quy trình có thể tiếp tục hoạt động trước. Hãy nhớ rằng, đây là I / O chung mà các quy trình thông thường đang làm. Tuy nhiên, các quy trình chuyên biệt, cần xác nhận rằng I / O thực sự được thực hiện trên đĩa có thể sử dụng cơ chế khác để thực hiện I / O trên đĩa. Một số tiện ích mã nguồn mở là libaio. Ngoài ra, có nhiều cách để gọi đồng bộ hóa rõ ràng với FD được mở trong ngữ cảnh quy trình của bạn,
Lỗi trang sau đó là gì?
Hãy xem xét một ví dụ, khi bạn bắt đầu một quá trình (giả sử trình duyệt web), có nhị phân khoảng 300MB. Tuy nhiên, 300 MB hoàn chỉnh của nhị phân trình duyệt web không bắt đầu hoạt động ngay lập tức. Quá trình tiếp tục chuyển từ các chức năng sang chức năng trong mã của nó. Như đã nói trước đó, Bộ nhớ ảo sẽ được tiêu thụ 300 MB, tuy nhiên, không phải tất cả là bộ nhớ được ánh xạ vào bộ nhớ vật lý (RSS - bộ nhớ lưu trú sẽ ít hơn, xem đầu ra hàng đầu). Khi thực thi mã đạt đến một điểm, trong đó bộ nhớ không thực sự được ánh xạ vật lý, lỗi trang sẽ là vấn đề. Kernel sẽ ánh xạ bộ nhớ này thành vật lý, liên kết trang bộ nhớ với quy trình của bạn. Một lỗi trang như vậy được gọi là "Lỗi trang nhỏ". Nói một cách tương tự, khi một quá trình đang thực hiện, các lỗi trang I / O chính được đưa ra.
Khi nào và tại sao hoán đổi xảy ra?
Tình huống 1:
Nội tuyến với các chi tiết ở trên, hãy xem xét một kịch bản khi lượng bộ nhớ tốt trở thành ánh xạ bộ nhớ. Và bây giờ một quá trình bắt đầu, đòi hỏi bộ nhớ. Như đã thảo luận ở trên, kernel sẽ có một số ánh xạ bộ nhớ. Tuy nhiên, không có đủ RAM vật lý để ánh xạ bộ nhớ. Bây giờ, kernel trước tiên sẽ xem xét bộ đệm, nó sẽ có một số trang bộ nhớ cũ không được sử dụng. Nó sẽ chuyển các trang đó lên một phân vùng riêng (được gọi là SWAP), giải phóng một số trang và ánh xạ các trang được giải phóng theo yêu cầu mới sắp tới. Vì đĩa ghi chậm hơn nhiều so với RAM trạng thái rắn, quá trình này mất rất nhiều thời gian và do đó sẽ thấy chậm lại.
Tình huống 2:
Hãy nói rằng bạn thấy rất nhiều bộ nhớ trống có sẵn trong hệ thống. Thậm chí sau đó bạn thấy rằng có rất nhiều trao đổi xảy ra. Có thể có một vấn đề có thể xảy ra của sự phân mảnh bộ nhớ. Hãy xem xét một quy trình, đòi hỏi 50 MB bộ nhớ liền kề từ kernel. (ghi nhớ tiếp giáp). Rõ ràng, hạt nhân sẽ phân bổ các trang ngẫu nhiên cho các quy trình khác nhau và giải phóng một số trong số chúng. Tuy nhiên, khi chúng ta đòi hỏi bộ nhớ liền kề, nó sẽ phải tìm kiếm một đoạn dữ liệu đáp ứng nhu cầu của các quy trình. Nếu nó không thể có được bộ nhớ như vậy, nó sẽ phải thực hiện trao đổi ra khỏi một số trang bộ nhớ cũ và sau đó phân bổ các trang tiếp giáp. Ngay cả trong những trường hợp như vậy, SWAP sẽ xảy ra. Bắt đầu Kernel ver 2.6 trở lên, các vấn đề phân mảnh như vậy đã giảm đáng kể. Tuy nhiên, nếu hệ thống chạy trong một thời gian dài, những vấn đề như vậy vẫn có thể xảy ra.
Xem ví dụ này ( đầu ra vmstat )
2016-10-29 03:55:32 procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------
2016-10-29 03:55:32 r b swpd free buff cache si so bi bo in cs us sy id wa st
2016-10-30 03:56:04 19 23 2914752 4692144 3344908 12162628 1660 1 8803 12701 4336 37487 14 7 40 38 0
2016-10-30 03:56:34 3 20 2889296 4977580 3345316 12026752 2109 2 8445 14665 4656 36294 12 7 46 34 0
2016-10-30 03:57:04 1 11 3418868 4939716 3347804 11536356 586 4744 2547 9535 3086 24450 6 3 59 33 0 <<<-----
2016-10-30 03:57:34 3 19 3456252 5449884 3348400 11489728 3291 13371 6407 17957 2997 22556 6 4 66 24 0
2016-10-30 03:58:04 7 6 4194500 5663580 3349552 10857424 2407 12240 3824 14560 2295 18237 4 2 65 29 0
2016-10-30 03:58:34 2 16 4203036 5986864 3348908 10838492 4601 16639 7219 18808 2575 21563 6 4 60 31 0
2016-10-30 03:59:04 3 14 4205652 6059196 3348760 10821448 6624 1597 9431 4357 1750 20471 6 2 60 31 0
2016-10-30 03:59:34 2 24 4206968 6053160 3348876 10777216 5221 2067 10106 7377 1731 19161 3 3 62 32 0
2016-10-30 04:00:04 0 13 4205172 6005084 3348932 10785896 6236 1609 10330 6264 1739 20348 4 2 67 26 0
2016-10-30 04:00:34 4 11 4206420 5996396 3348976 10770220 6554 1253 10382 4896 1964 42981 10 5 58 27 0
2016-10-30 04:01:04 6 4 4177176 5878852 3348988 10825840 8682 765 10126 2716 1731 32949 8 4 69 19 0
@ 2016-10-30 03:57:04, chúng tôi thấy rằng vẫn còn lượng RAM miễn phí tốt. Tuy nhiên, thậm chí sau đó trao đổi đã xảy ra. Chúng tôi đã kiểm tra cây quy trình tại thời điểm này và chúng tôi không thấy bất kỳ quá trình nào sắp tới sẽ đòi hỏi dung lượng bộ nhớ cao như vậy (nhiều hơn bộ nhớ trống). Sự nghi ngờ rõ ràng là Tình huống 2 được mô tả ở trên. Chúng tôi đã kiểm tra nhật ký Buddyinfo và zoneinfo ở trên (Sử dụng echo m> / Proc / sysrq-trigger để kiểm tra những điều này, đầu ra đi vào syslog).
Đối với một hệ thống bình thường của chúng ta, việc so sánh thông tin khu vực thực hiện điều này. Và đồ thị cho bộ nhớ cache / free / low mem cũng được đề cập dưới đây
Nhìn vào thông tin, rõ ràng có sự phân mảnh bộ nhớ trong nút 0 & nút 1 bình thường (Nút đó là máy dựa trên NUMA, do đó có nhiều nút (xem numactl để kiểm tra thông tin cho hệ thống của bạn)).
Phân mảnh bộ nhớ cũng là một lý do tại sao việc sử dụng trao đổi có thể tăng ngay cả khi có bộ nhớ trống.