Tôi quan tâm đến sự khác biệt giữa Highmem và Lowmem:
- Tại sao có sự khác biệt như vậy?
- Chúng ta đạt được gì khi làm như vậy?
- Mỗi tính năng có những tính năng gì?
Tôi quan tâm đến sự khác biệt giữa Highmem và Lowmem:
Câu trả lời:
Trên kiến trúc 32 bit, phạm vi không gian địa chỉ để xử lý RAM là:
0x00000000 - 0xffffffff
hoặc 4'294'967'295
(4 GB).
Hạt nhân linux chia ra 3/1 (cũng có thể là 2/2 hoặc 1/3 1 ) vào không gian người dùng (bộ nhớ cao) và không gian nhân (bộ nhớ thấp) tương ứng.
Phạm vi không gian người dùng:
0x00000000 - 0xbfffffff
Mỗi quá trình người dùng mới được sinh ra sẽ có một địa chỉ (phạm vi) trong khu vực này. Các quy trình người dùng thường không đáng tin cậy và do đó bị cấm truy cập vào không gian kernel. Hơn nữa, chúng được coi là không khẩn cấp, như một quy tắc chung, kernel cố gắng trì hoãn việc phân bổ bộ nhớ cho các quá trình đó.
Phạm vi không gian kernel:
0xc0000000 - 0xffffffff
Một tiến trình kernel có địa chỉ (phạm vi) ở đây. Hạt nhân có thể truy cập trực tiếp 1 GB địa chỉ này (tốt, không phải là 1 GB đầy đủ, có 128 MB dành riêng cho truy cập bộ nhớ cao).
Các quy trình sinh ra trong không gian kernel được tin cậy, khẩn cấp và không có lỗi, yêu cầu bộ nhớ được xử lý ngay lập tức.
Mọi tiến trình kernel cũng có thể truy cập phạm vi không gian người dùng nếu muốn. Và để đạt được điều này, kernel ánh xạ một địa chỉ từ không gian người dùng (bộ nhớ cao) sang không gian kernel của nó (bộ nhớ thấp), 128 MB được đề cập ở trên được dành riêng cho việc này.
1 Việc phân chia là 3/1, 2/2 hay 1/3 được kiểm soát bởi CONFIG_VMSPLIT_...
tùy chọn; bạn có thể kiểm tra /boot/config*
xem tùy chọn nào đã được chọn cho kernel của bạn.
Tham chiếu đầu tiên để chuyển sang là Trình điều khiển thiết bị Linux (có sẵn cả trực tuyến và ở dạng sách), đặc biệt là chương 15 có một phần về chủ đề này.
Trong một thế giới lý tưởng, mọi thành phần hệ thống sẽ có thể ánh xạ tất cả bộ nhớ mà nó cần truy cập. Và đây là trường hợp đối với các quy trình trên Linux và hầu hết các hệ điều hành: quy trình 32 bit chỉ có thể truy cập ít hơn 2 ^ 32 byte bộ nhớ ảo (thực tế là khoảng 3 GB trên kiến trúc 32 bit điển hình của Linux). Hạt nhân gặp khó khăn, cần có khả năng ánh xạ bộ nhớ đầy đủ của quá trình mà hệ thống gọi nó đang thực thi, cộng với toàn bộ bộ nhớ vật lý, cộng với bất kỳ thiết bị phần cứng được ánh xạ bộ nhớ nào khác.
Vì vậy, khi kernel 32 bit cần ánh xạ hơn 4GB bộ nhớ, nó phải được biên dịch với sự hỗ trợ bộ nhớ cao. Bộ nhớ cao là bộ nhớ không được ánh xạ vĩnh viễn trong không gian địa chỉ của kernel. (Bộ nhớ thấp thì ngược lại: nó luôn được ánh xạ, do đó bạn có thể truy cập nó trong kernel chỉ bằng cách hủy bỏ một con trỏ.)
Khi bạn truy cập bộ nhớ cao từ mã kernel, bạn cần gọi kmap
trước, để lấy con trỏ từ cấu trúc dữ liệu trang ( struct page
). Gọi kmap
hoạt động cho dù trang ở bộ nhớ cao hay thấp. Ngoài ra còn kmap_atomic
có các ràng buộc bổ sung nhưng hiệu quả hơn trên các máy đa bộ xử lý vì nó sử dụng khóa hạt mịn hơn. Con trỏ thu được thông qua kmap
là một tài nguyên: nó sử dụng không gian địa chỉ. Khi bạn đã hoàn thành với nó, bạn phải gọi kunmap
(hoặc kunmap_atomic
) để giải phóng tài nguyên đó; sau đó con trỏ không còn hợp lệ và nội dung của trang không thể được truy cập cho đến khi bạn gọi kmap
lại.
Điều này có liên quan đến nhân Linux; Tôi không chắc làm thế nào bất kỳ nhân Unix nào xử lý việc này.
Bộ nhớ cao là phân đoạn bộ nhớ mà các chương trình không gian người dùng có thể xử lý. Nó không thể chạm vào Bộ nhớ thấp.
Bộ nhớ thấp là phân đoạn bộ nhớ mà nhân Linux có thể xử lý trực tiếp. Nếu hạt nhân phải truy cập vào Bộ nhớ cao, trước tiên nó phải ánh xạ nó vào không gian địa chỉ của chính nó.
Có một bản vá được giới thiệu gần đây cho phép bạn kiểm soát vị trí của phân khúc. Sự cân bằng là bạn có thể lấy bộ nhớ địa chỉ ra khỏi không gian người dùng để kernel có thể có nhiều bộ nhớ hơn mà nó không phải ánh xạ trước khi sử dụng.
Tài nguyên bổ sung:
HIGHMEM là một phạm vi không gian bộ nhớ của kernel, nhưng nó không phải là bộ nhớ bạn truy cập mà là nơi bạn đặt những gì bạn muốn truy cập.
Bản đồ bộ nhớ ảo 32 bit điển hình của Linux giống như:
0x00000000-0xbfffffff: quy trình người dùng (3GB)
0xc0000000-0xffffffff: dung lượng kernel (1GB)
(Vectơ dành riêng cho CPU và bất cứ điều gì được bỏ qua ở đây).
Linux chia không gian kernel 1GB thành 2 phần, LOWMEM và HIGHMEM. Sự phân chia khác nhau từ cài đặt để cài đặt.
Nếu cài đặt chọn, giả sử, 512MB-512MB cho các mem thấp và CAO, thì 512MB LOWMEM (0xc0000000-0xdfffffff) được ánh xạ tĩnh tại thời điểm khởi động kernel; thường là rất nhiều byte đầu tiên của bộ nhớ vật lý được sử dụng cho điều này để các địa chỉ ảo và vật lý trong phạm vi này có độ lệch không đổi là 0xc0000000.
Mặt khác, 512 MB sau (HIGHMEM) không có ánh xạ tĩnh (mặc dù bạn có thể để các trang được ánh xạ bán vĩnh viễn ở đó, nhưng bạn phải làm như vậy rõ ràng trong mã trình điều khiển của mình). Thay vào đó, các trang tạm thời được ánh xạ và không được ánh xạ ở đây để các địa chỉ ảo và vật lý trong phạm vi này không có ánh xạ nhất quán. Các ứng dụng điển hình của HIGHMEM bao gồm bộ đệm dữ liệu một lần.
Nhiều người đã nói rằng bộ nhớ thấp là dành cho hệ điều hành. Điều này thường đúng nhưng không phải như vậy. Bộ nhớ cao và bộ nhớ thấp chỉ là hai phần của không gian bộ nhớ, nhưng trong hệ thống Linux, bộ nhớ thấp chỉ dành cho kernel và bộ nhớ cao cho các tiến trình của người dùng.
Theo "Cuốn sách khủng long (khái niệm hệ điều hành)", chúng ta có thể đặt hệ điều hành ở bộ nhớ thấp hoặc bộ nhớ cao. Yếu tố chính ảnh hưởng đến quyết định này là vị trí của vectơ ngắt. Do vectơ ngắt thường ở bộ nhớ thấp, nên các lập trình viên thường đặt hệ điều hành vào bộ nhớ thấp.