Sử dụng dấu phẩy động trong nhân Linux


83

Tôi đang đọc "Phát triển nhân Linux" của Robert Love, và tôi đã xem qua đoạn văn sau:

Không (Dễ dàng) Sử dụng Dấu phẩy động

Khi một quy trình không gian người dùng sử dụng các lệnh dấu phẩy động, hạt nhân quản lý quá trình chuyển đổi từ chế độ số nguyên sang chế độ dấu phẩy động. Những gì hạt nhân phải làm khi sử dụng các lệnh dấu phẩy động thay đổi theo kiến ​​trúc, nhưng hạt nhân thường bắt một cái bẫy và sau đó bắt đầu chuyển đổi từ chế độ số nguyên sang chế độ dấu chấm động.

Không giống như user-space, kernel không có sự hỗ trợ liền mạch cho dấu phẩy động vì nó không thể dễ dàng tự bẫy. Việc sử dụng dấu phẩy động bên trong hạt nhân yêu cầu phải lưu và khôi phục thủ công các thanh ghi dấu chấm động, trong số các công việc có thể có khác. Câu trả lời ngắn gọn là: Đừng làm điều đó! Ngoại trừ một số trường hợp hiếm hoi, không có phép toán dấu phẩy động nào trong nhân.

Tôi chưa bao giờ nghe nói về các chế độ "số nguyên" và "dấu phẩy động". Chính xác thì chúng là gì và tại sao chúng lại cần thiết? Sự khác biệt này có tồn tại trên các kiến ​​trúc phần cứng chính thống (chẳng hạn như x86) hay nó dành riêng cho một số môi trường kỳ lạ hơn? Chính xác thì việc chuyển đổi từ chế độ số nguyên sang chế độ dấu phẩy động đòi hỏi điều gì, cả từ quan điểm của quá trình và hạt nhân?



2
Cuốn sách làm rối vấn đề một chút bằng cách nói về một "chế độ". Các lệnh số nguyên luôn có sẵn, nhưng FPU có thể bị vô hiệu hóa toàn bộ hoặc một phần. Không có chức năng hữu ích nào bao gồm hoàn toàn các hoạt động FP, ví dụ, tất cả các lệnh điều khiển được coi là "số nguyên". Xem bên dưới để biết thêm.
DigitalRoss 15/12/12

@DigitalRoss: Tôi đồng ý về thuật ngữ. Cảm ơn câu trả lời BTW, nó đã làm cho mọi thứ trở nên rõ ràng.
NPE

Sẽ rất thú vị nếu biết mong muốn thực hiện các hoạt động dấu chấm động trong nhân bắt nguồn từ đâu. Thật hấp dẫn khi nói "thiết kế kém" theo nghĩa là cố gắng làm một điều gì đó trong nhân mà nên được thực hiện bên ngoài nó, nhưng có lẽ có những điều mà nhân thực sự nên làm khi tận dụng FPU sẽ là một giải pháp sáng tạo?
Chris Stratton

2
Vì không ai đề cập đến nó, nếu bạn sử dụng FP (hoặc SIMD) bên trong hạt nhân, bạn cần gọi kernel_fpu_begin()/ kernel_fpu_end()trước / sau mã của mình để đảm bảo trạng thái FPU không gian người dùng không bị hỏng. Đây là những gì mdmã của Linux thực hiện cho RAID5 / RAID6.
Peter Cordes

Câu trả lời:


86

Bởi vì...

  • nhiều chương trình không sử dụng dấu phẩy động hoặc không sử dụng nó trên bất kỳ khoảng thời gian nhất định nào;
  • lưu các sổ đăng ký FPU và trạng thái FPU khác mất nhiều thời gian; vì thế

... một nhân hệ điều hành có thể chỉ cần tắt FPU. Presto, không có trạng thái để lưu và khôi phục, và do đó chuyển đổi ngữ cảnh nhanh hơn. (Đây là ý nghĩa của chế độ , nó chỉ có nghĩa là FPU đã được bật.)

Nếu một chương trình cố gắng thực hiện FPU op, chương trình sẽ bẫy vào hạt nhân, hạt nhân sẽ bật FPU lên, khôi phục mọi trạng thái đã lưu có thể đã tồn tại, sau đó quay lại để thực thi lại FPU op.

Tại thời điểm chuyển đổi ngữ cảnh, nó biết thực sự đi qua logic lưu trạng thái. (Và sau đó nó có thể tắt FPU một lần nữa.)

Nhân tiện, tôi tin rằng lời giải thích của cuốn sách về lý do hạt nhân (và không chỉ Linux) tránh các hoạt động FPU là ... không hoàn toàn chính xác. 1

Kernel có thể mắc kẹt vào chính nó và làm như vậy cho nhiều thứ. (Bộ hẹn giờ, lỗi trang, ngắt thiết bị, các lỗi khác.) Lý do thực sự là hạt nhân không đặc biệt cần các hoạt động FPU và cũng cần chạy trên các kiến ​​trúc không có FPU. Do đó, nó chỉ đơn giản là tránh sự phức tạp và thời gian chạy cần thiết để quản lý ngữ cảnh FPU của riêng nó bằng cách không thực hiện các hoạt động mà luôn có các giải pháp phần mềm khác.

Thật thú vị khi lưu ý tần suất trạng thái FPU sẽ phải được lưu nếu hạt nhân muốn sử dụng FP . . . mọi cuộc gọi hệ thống, mọi ngắt, mọi chuyển đổi giữa các luồng nhân. Thậm chí nếu có một nhu cầu cho FP hạt nhân thường xuyên, 2 nó có lẽ sẽ nhanh hơn để làm điều đó trong phần mềm.


1. Đó là, sai chết.
2. Có một vài trường hợp tôi biết về nơi mà phần mềm hạt nhân chứa một triển khai số học dấu phẩy động . Một số kiến ​​trúc thực hiện các hoạt động FPU truyền thống trong phần cứng nhưng để lại một số hoạt động IEEE FP phức tạp cho phần mềm. (Hãy nghĩ: số học không bình thường.) Khi một số trường hợp góc IEEE kỳ quặc xảy ra, chúng mắc bẫy phần mềm có chứa mô phỏng đúng về cơ bản của các hoạt động có thể mắc bẫy.


16

Với một số thiết kế nhân, các thanh ghi dấu phẩy động không được lưu khi tác vụ "hạt nhân" hoặc "hệ thống" được chuyển tác vụ. (Điều này là do các thanh ghi FP lớn và mất cả thời gian và không gian để lưu.) Vì vậy, nếu bạn cố gắng sử dụng FP, các giá trị sẽ bị "poof" một cách ngẫu nhiên.

Ngoài ra, một số lược đồ dấu phẩy động phần cứng dựa vào hạt nhân để xử lý các tình huống "kỳ quặc" (ví dụ: chia số 0) thông qua một bẫy và cơ chế bẫy bắt buộc có thể ở "cấp" cao hơn tác vụ nhân hiện đang chạy.

Vì những lý do này (và một vài lý do khác), một số lược đồ FP phần cứng sẽ mắc kẹt khi bạn sử dụng lệnh FP lần đầu tiên trong một tác vụ. Nếu bạn được phép sử dụng FP thì cờ dấu chấm động sẽ được bật trong nhiệm vụ, nếu không, bạn sẽ bị đội xử bắn.


Trong Linux, hãy sử dụng kernel_fpu_begin()/ kernel_fpu_end()trước / sau mã của bạn để kích hoạt lưu / khôi phục trạng thái FPU không gian người dùng (và tôi đoán là trạng thái FPU trong hạt nhân của bạn chống lại quyền sử dụng trước).
Peter Cordes
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.