Làm cách nào tôi có thể dự trữ một khối bộ nhớ từ nhân Linux?


25

Tôi có một thiết bị cần một khối bộ nhớ chỉ dành riêng cho nó mà không cần hệ điều hành can thiệp. Có cách nào để nói với BIOS hoặc HĐH rằng một khối bộ nhớ được bảo lưu và không được sử dụng nó?

Tôi đang sử dụng thiết bị này trên máy openSUSE.

Câu trả lời:


23

Những gì bạn đang yêu cầu được gọi là DMA. Bạn cần phải viết một trình điều khiển để dự trữ bộ nhớ này.

Vâng, tôi nhận ra rằng bạn nói rằng bạn không muốn HĐH can thiệp và trình điều khiển trở thành một phần của HĐH, nhưng không có sự bảo lưu của trình điều khiển, hạt nhân tin rằng tất cả bộ nhớ thuộc về nó. (Trừ khi bạn bảo hạt nhân bỏ qua khối bộ nhớ, theo câu trả lời của Aaron, nghĩa là vậy.)

Chương 15 (PDF) của " Trình điều khiển thiết bị Linux, 3 / e " của Rubini, Corbet và Kroah-Hartmann bao gồm DMA và các chủ đề liên quan.

Nếu bạn muốn có phiên bản HTML này, tôi đã tìm thấy phiên bản thứ hai của chương ở nơi khác trực tuyến. Coi chừng rằng phiên bản thứ 2 đã hơn một thập kỷ, xuất hiện khi kernel 2.4 mới. Đã có rất nhiều công việc trên hệ thống con quản lý bộ nhớ của kernel kể từ những ngày đó, vì vậy nó có thể không còn áp dụng tốt nữa.


Với DMA tôi có thể chọn địa chỉ vật lý nào để sử dụng không? Hạt nhân sẽ cho tôi một khối bộ nhớ liền kề? Có đảm bảo luôn luôn có sẵn?
Nathan Fellman

1
Các câu hỏi của bạn được trả lời bắt đầu từ trang 438 của PDF mà tôi đã chỉ cho bạn.
Warren Young

24

Nếu bạn muốn HĐH hoàn toàn bỏ qua nó, bạn cần tạo một lỗ nhớ bằng cách sử dụng " memmap." Xem tài liệu tham khảo này . Ví dụ: nếu bạn muốn 512M ở hàng rào 2GB, bạn có thể đặt " memmap=512M$2G" trên dòng lệnh kernel.

Bạn sẽ cần kiểm tra dmesgđể tìm một lỗ tiếp giáp để đánh cắp để bạn không dậm chân trên bất kỳ thiết bị nào; đó là cụ thể cho bo mạch chủ + thẻ của bạn.

Đây không phải là cách được đề xuất để thực hiện - hãy xem câu trả lời của Warren Young để biết cách thực hiện đúng (trình điều khiển kernel + DMA). Tôi đang trả lời chính xác câu hỏi bạn đã hỏi. Nếu bạn dự định làm điều này cho người dùng cuối, họ sẽ ghét bạn nếu bạn làm điều này với họ ... hãy tin tôi, đó là lý do duy nhất tôi biết câu trả lời này.


Chỉnh sửa: Nếu bạn đang sử dụng grub2 w / grubby (ví dụ: CentOS 7), bạn cần đảm bảo thoát khỏi $ . Nên có một \trước $. Thí dụ:

$ sudo -v
$ sudo grubby --update-kernel=ALL --args=memmap='128M\\$0x57EF0000'
$ sudo grubby --info $(sudo grubby --default-kernel) | grep memmap
args="ro crashkernel=auto ... memmap=128M\$0x57EF0000"

1
Trong khi câu trả lời của bạn trả lời trực tiếp câu hỏi của tôi, câu trả lời của Warren dường như là cách tốt hơn để giải quyết nó. :-)
Nathan Fellman

1
@WarrenYoung Tôi không biết bạn phải làm gì với nó. Tôi sẽ đoán " uint8_t *ptr = 0x8000000" với ví dụ của tôi? Hoặc điều đó có thể segfault ... Huh, tôi thực sự không biết. Một lần nữa, tôi biết câu trả lời vì tôi là người dùng cuối của thẻ PCI được thiết kế kém, nơi tôi phải phân bổ thủ công bộ đệm dưới vạch 4G và sau đó cho tài xế biết chỗ đó ở đâu; nó có thể không thể từ người dùng.
Aaron D. Marasco

2
Chỉ vì nụ cười, tôi nhìn sâu hơn một chút vào điều này, và có vẻ như bạn cần MMAP_FIXED | MMAP_ANON. Không có thiết bị DMA tùy chỉnh ở đây để chơi, tôi không thể nói nếu nó thực sự làm những gì OP muốn, nhưng hộp CentOS của tôi đã vui vẻ cho tôi một khối 8 MB ở 512 MB khi tôi nói memmap=8M$512Mtrong GRUB. Nó thậm chí không yêu cầu quyền truy cập root, vì tôi đã sợ nó có thể. Nhưng ngay cả khi điều này làm đúng, tôi vẫn nghĩ rằng có lẽ bạn sẽ cần một trình điều khiển để xử lý các ngắt và như vậy.
Warren Young

3
@ AaronD.Maraco: Không, mmap()các trang không có giá trị trước khi mã người dùng được nhìn thấy chúng. Nó được thực hiện để bảo mật, do đó dữ liệu không bị rò rỉ từ quá trình này sang quá trình tiếp theo. Một lý do khác để sử dụng trình điều khiển, vì bạn có thể cần phải bảo toàn nội dung của bộ đệm DMA tại thời điểm tải trình điều khiển. Ồ, nhân tiện, mmap()cuộc gọi được định vị tùy ý thành công ngay cả khi không có memmaptùy chọn khởi động kernel, ít nhất là không có ai đang sử dụng bộ nhớ ở nơi bạn hỏi. Tùy chọn khởi động chắc chắn làm tăng cơ hội thành công, nhưng nó không thực sự cần thiết.
Warren Young

1
@ AaronD.Maraco hmm, được thôi. hấp dẫn. cảm ơn vì liên kết đó, nó rất tốt
Woodrow Barlow

5

Để dự trữ một khối bộ nhớ từ kernel trong Linux dựa trên ARM, bạn cũng có thể sử dụng một reserved-memorynút trong tệp cây (dts) của thiết bị. Trong tài liệu kernel (xem tại đây ), có một ví dụ:

memory {
    reg = <0x40000000 0x40000000>;
};

reserved-memory {
    #address-cells = <1>;
    #size-cells = <1>;
    ranges;

    /* global autoconfigured region for contiguous allocations */
    linux,cma {
        compatible = "shared-dma-pool";
        reusable;
        size = <0x4000000>;
        alignment = <0x2000>;
        linux,cma-default;
    };

    display_reserved: framebuffer@78000000 {
        reg = <0x78000000 0x800000>;
    };

    multimedia_reserved: multimedia@77000000 {
        compatible = "acme,multimedia-memory";
        reg = <0x77000000 0x4000000>;
    };
};

0

Đầu tiên nhập lệnh này, để kiểm tra cài đặt hiện tại của bạn:

sysctl vm.min_free_kbytes

Để thay đổi giá trị đặt, chỉnh sửa /etc/sysctl.conf. Tìm dòng:

vm.min_free_kbytes=12888

Nếu nó không tồn tại, hãy tạo nó (cùng với giá trị mong muốn của bạn). Các giá trị sau được chấp nhận:

8192
12288
16384
20480

8M là cực kỳ bảo thủ; Nó có thể ngồi thoải mái 16M. Khi bạn thay đổi giá trị, hãy chạy cái này và không cần khởi động lại:

sudo sysctl -p

2
Xin đừng để trống bài viết của bạn; hoặc xóa nó hoặc gắn cờ cho người điều hành để xóa cho bạn.
jasonwryan
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.