Khi hệ thống Linux của tôi gần phân trang (nghĩa là trong trường hợp của tôi, ram 16 GB gần đầy, hoán đổi 16 GB hoàn toàn trống) nếu một quy trình mới X cố gắng phân bổ một số bộ nhớ mà hệ thống khóa hoàn toàn. Đó là, cho đến khi một số lượng trang không tương xứng, (ghi tổng kích thước và tỷ lệ yêu cầu phân bổ bộ nhớ của X) đã được hoán đổi. Lưu ý rằng không chỉ gui trở nên hoàn toàn không phản hồi mà ngay cả các dịch vụ cơ bản như sshd cũng bị chặn hoàn toàn.
Đây là hai đoạn mã (thừa nhận thô thiển) mà tôi sử dụng để kích hoạt hành vi này theo cách "khoa học" hơn. Số đầu tiên nhận được hai số x, y từ dòng lệnh và tiến hành phân bổ và khởi tạo nhiều khối y byte cho đến khi hơn x tổng số byte được phân bổ. Và sau đó chỉ ngủ vô thời hạn. Điều này sẽ được sử dụng để đưa hệ thống trên bờ vực phân trang.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char** argv) {
long int max = -1;
int mb = 0;
long int size = 0;
long int total = 0;
char* buffer;
if(argc > 1)
{
max = atol(argv[1]);
size = atol(argv[2]);
}
printf("Max: %lu bytes\n", max);
while((buffer=malloc(size)) != NULL && total < max) {
memset(buffer, 0, size);
mb++;
total=mb*size;
printf("Allocated %lu bytes\n", total);
}
sleep(3000000);
return 0;
}
Đoạn mã thứ hai thực hiện chính xác những gì mã đầu tiên thực hiện ngoại trừ việc nó có sleep(1);
quyền sau printf
(Tôi sẽ không lặp lại toàn bộ mã). Cái này sẽ được sử dụng khi hệ thống đang ở trạng thái phân trang để khiến nó hoán đổi các trang theo cách "nhẹ nhàng" tức là bằng cách từ từ yêu cầu phân bổ các đoạn bộ nhớ mới (để hệ thống chắc chắn có thể hoán đổi các trang và theo kịp với các yêu cầu mới).
Vì vậy, với hai đoạn mã được biên dịch, hãy gọi exeater fasteater và Sloweater tương ứng, hãy làm điều này:
1) bắt đầu gui yêu thích của bạn (tất nhiên không cần thiết lắm)
2) bắt đầu một số mem / trao đổi mét (ví dụ watch -n 1 free
)
3) bắt đầu nhiều trường hợp trong fasteater x y
đó x là thứ tự của gigabyte và y là thứ tự của megabyte. Làm điều đó cho đến khi bạn gần như lấp đầy ram.
4) bắt đầu một thể hiện của sloweater x y
, một lần nữa trong đó x là thứ tự của gigabyte và y là thứ tự của megabyte.
Sau bước 4) điều gì sẽ xảy ra (và nó luôn xảy ra với hệ thống của tôi) là ngay sau khi hết ram, hệ thống sẽ khóa hoàn toàn. gui bị khóa sshd bị khóa vv NHƯNG, không phải là mãi mãi! Sau khi bộ xử lý chậm hoàn thành các yêu cầu phân bổ, hệ thống sẽ hoạt động trở lại (sau vài phút khóa, không phải vài giây ...) với tình huống này:
a) ram đã đầy
b) hoán đổi cũng gần đầy (hãy nhớ rằng lúc đầu nó trống rỗng)
c) không có sự can thiệp của kẻ giết người.
Và lưu ý rằng phân vùng trao đổi là trên một ổ SSD. Vì vậy, hệ thống dường như không thể chuyển dần các trang từ ram sang hoán đổi (có lẽ là từ các thiết bị nhanh đang ngủ) để tạo không gian cho các yêu cầu chậm (và chỉ vài megabyte) của bộ làm chậm.
Bây giờ, ai đó sửa tôi nếu tôi sai, nhưng điều này dường như không phải là cách một hệ thống hiện đại nên hành xử trong cài đặt này. Nó dường như hoạt động giống như các hệ thống cũ (waaaaay trở lại) khi không có hỗ trợ phân trang và hệ thống bộ nhớ ảo chỉ thay đổi toàn bộ không gian bộ nhớ của một số tiến trình thay vì vài trang.
Ai đó cũng có thể kiểm tra điều này? Và có lẽ ai đó cũng có hệ thống BSD.
CẬP NHẬT 1
Tôi đã làm theo lời khuyên từ Mark Plotnick bên dưới trong các bình luận và tôi đã bắt đầu vmstat 1 >out
trước khi tiến hành thử nghiệm phân trang. Bạn có thể thấy kết quả bên dưới (Tôi đã cắt toàn bộ phần ban đầu trong đó ram được lấp đầy mà không có sự tham gia trao đổi):
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 6144 160792 8 272868 0 0 0 0 281 1839 1 0 99 0 0
0 0 6144 177844 8 246096 0 0 0 0 425 2300 1 1 99 0 0
0 0 6144 168528 8 246112 0 0 16 0 293 1939 1 0 99 0 0
0 0 6144 158320 8 246116 0 0 0 0 261 1245 0 0 100 0 0
2 0 10752 161624 8 229024 0 4820 17148 4820 845 3656 1 2 97 0 0
2 0 10752 157300 8 228096 0 0 88348 0 2114 8902 0 5 94 1 0
0 0 10752 176108 8 200052 0 0 108312 0 2466 9772 1 5 91 3 0
0 0 10752 170040 8 196780 0 0 17380 0 507 1895 0 1 99 0 0
0 10 10752 160436 8 191244 0 0 346872 20 4184 17274 1 9 64 26 0
0 29 12033856 152888 8 116696 5992 15916880 1074132 15925816 819374 2473643 0 94 0 6 0
3 21 12031552 295644 8 136536 1188 0 11348 0 1362 3913 0 1 10 89 0
0 11 12030528 394072 8 151000 2016 0 17304 0 907 2867 0 1 13 86 0
0 11 12030016 485252 8 158528 708 0 7472 0 566 1680 0 1 23 77 0
0 11 12029248 605820 8 159608 900 0 2024 0 371 1289 0 0 31 69 0
0 11 12028992 725344 8 160472 1076 0 1204 0 387 1381 0 1 33 66 0
0 12 12028480 842276 8 162056 724 0 3112 0 357 1142 0 1 38 61 0
0 13 12027968 937828 8 162652 776 0 1312 0 363 1191 0 1 31 68 0
0 9 12027456 1085672 8 163260 656 0 1520 0 439 1497 0 0 30 69 0
0 10 12027200 1207624 8 163684 728 0 992 0 411 1268 0 0 42 58 0
0 9 12026688 1331492 8 164740 600 0 1732 0 392 1203 0 0 36 64 0
0 9 12026432 1458312 8 166020 628 0 1644 0 366 1176 0 0 33 66 0
Như bạn có thể thấy, ngay khi hoán đổi được tham gia, có một sự hoán đổi khổng lồ là 15916880 Kbyte cùng một lúc, theo tôi đoán, kéo dài trong toàn bộ thời gian hệ thống đóng băng. Và tất cả những điều này rõ ràng là do một quá trình (trình làm chậm) chỉ yêu cầu 10MB mỗi giây.
CẬP NHẬT 2: Tôi đã cài đặt nhanh FreeBSD và lặp lại sơ đồ phân bổ tương tự được sử dụng với Linux ... và nó vẫn mượt mà như mong muốn. FreeBSD hoán đổi các trang dần dần trong khi bộ làm chậm phân bổ tất cả các bộ nhớ 10 MB của nó. Không một cú huých nào cả ... WTF đang diễn ra ở đây?!
CẬP NHẬT 3: Tôi đã gửi một lỗi với kernel bugtracker. Có vẻ như đang được chú ý nên ... ngón tay đan chéo ...
vmstat 1>somefile
trực tiếp từ hệ thống và sau đó xem những gì nó báo cáo sau khi hệ thống hoạt động trở lại. Tôi sẽ thử xem.
swappiness
là 60 mặc định (không thay đổi nó mang lại kết quả tốt hơn). Hạt nhân được sử dụng với lần vmstat
chạy là 4.14,35 nhưng tôi đã thử 4.15, 4.16 và thậm chí tôi đã quay lại loạt 4.0 (!): Luôn luôn là hành vi tương tự. Và không phải là tôi đang sử dụng một số phân phối kỳ lạ, nó chỉ là debian. Tôi không sử dụng hình ảnh hạt nhân từ debian (không phải hình ảnh của tôi có cấu hình bất thường) nhưng tôi đã thử một trong những ... hành vi tương tự.