it-swarm-vi.com

Chuyển Linux sang các yêu cầu nền tảng khác

Tôi biết rằng Linux có sẵn và đã được chuyển cho nhiều nền tảng khác nhau như X86, ARM, PowerPC, v.v.

Tuy nhiên, về mặt porting, những gì được yêu cầu chính xác?

Tôi hiểu rằng Linux là phần mềm được viết bằng C. Do đó, khi chuyển Linux ban đầu từ X86 sang ARM hoặc các loại khác, chẳng hạn, đó không chỉ là vấn đề biên dịch lại mã với trình biên dịch cho kiến trúc mục tiêu cụ thể?

Đặt trình điều khiển thiết bị cho các thiết bị ngoại vi khác nhau sang một bên, những gì khác sẽ cần phải được thực hiện khi chuyển Linux sang một kiến ​​trúc mới. Có trình biên dịch không chăm sóc tất cả mọi thứ cho chúng tôi?

28
Engineer999

Mặc dù hầu hết các mã trong nhân Linux được viết bằng C, vẫn có nhiều phần của mã đó rất đặc trưng cho nền tảng nơi nó đang chạy và cần phải tính đến điều đó.

Một ví dụ cụ thể về điều này là bộ nhớ ảo, hoạt động theo kiểu tương tự trên hầu hết các kiến ​​trúc (phân cấp các bảng trang) nhưng có các chi tiết cụ thể cho từng kiến ​​trúc (chẳng hạn như số cấp trong mỗi kiến ​​trúc và điều này đã tăng lên ngay cả trên x86 với giới thiệu các chip mới lớn hơn.) Mã hạt nhân Linux giới thiệu các macro để xử lý các hệ thống phân cấp có thể bị xóa bởi trình biên dịch trên các kiến ​​trúc có ít cấp bảng trang hơn (do đó mã được viết bằng C, nhưng có chi tiết về kiến ​​trúc Sự xem xét.)

Nhiều khu vực khác rất cụ thể cho từng kiến ​​trúc và cần được xử lý với mã Arch-cụ thể. Hầu hết trong số này liên quan đến mã trong ngôn ngữ hội mặc dù. Ví dụ là:

  • Chuyển ngữ cảnh: Chuyển đổi ngữ cảnh liên quan đến việc lưu giá trị của tất cả các thanh ghi cho quá trình được tắt và khôi phục các thanh ghi từ tập đã lưu của quy trình được lên lịch vào CPU. Ngay cả số lượng và bộ thanh ghi là rất cụ thể cho từng kiến ​​trúc. Mã này thường được triển khai trong hội, để cho phép truy cập đầy đủ vào các thanh ghi và cũng để đảm bảo nó chạy nhanh nhất có thể, vì hiệu suất chuyển đổi ngữ cảnh có thể rất quan trọng đối với hệ thống.

  • Gọi hệ thống: Cơ chế mà mã không gian người dùng có thể kích hoạt lệnh gọi hệ thống thường dành riêng cho kiến ​​trúc (và đôi khi ngay cả với mô hình CPU cụ thể, ví dụ Intel và AMD đã giới thiệu các hướng dẫn khác nhau cho CPU cũ hơn có thể thiếu các hướng dẫn đó, vì vậy chi tiết cho những hướng dẫn đó sẽ vẫn là duy nhất.)

  • Trình xử lý ngắt: Chi tiết về cách xử lý ngắt (ngắt phần cứng) thường dành riêng cho nền tảng và thường yêu cầu một số keo cấp độ hội để xử lý các quy ước gọi cụ thể được sử dụng cho nền tảng. Ngoài ra, các nguyên hàm để bật/tắt các ngắt thường là đặc thù của nền tảng và cũng yêu cầu mã hội.

  • Khởi tạo: Chi tiết về cách khởi tạo cũng sẽ thường bao gồm các chi tiết dành riêng cho nền tảng và thường yêu cầu một số mã hội để xử lý điểm nhập vào kernel. Trên các nền tảng có nhiều CPU (SMP), chi tiết về cách đưa các CPU khác trực tuyến cũng thường dành riêng cho nền tảng.

  • Khóa nguyên thủy: Thực hiện khóa nguyên thủy khóa (chẳng hạn như spinlocks) thường liên quan đến các chi tiết cụ thể của nền tảng, vì một số kiến ​​trúc cung cấp (hoặc thích) các hướng dẫn CPU khác nhau để thực hiện hiệu quả các lệnh đó. Một số sẽ thực hiện các hoạt động nguyên tử, một số sẽ cung cấp một cmpxchg có thể kiểm tra/cập nhật nguyên tử (nhưng không thành công nếu người viết khác vào trước), những người khác sẽ bao gồm một công cụ sửa đổi "khóa" theo hướng dẫn của CPU. Chúng thường sẽ liên quan đến việc viết mã hội.

Có thể có các khu vực khác cần mã nền tảng hoặc kiến ​​trúc cụ thể trong hạt nhân (hoặc cụ thể là trong nhân Linux.) Nhìn vào cây nguồn nhân, có các cây con đặc trưng kiến ​​trúc trong Arch/ và dưới include/Arch/ nơi bạn có thể tìm thấy nhiều ví dụ về điều này.

Một số thực sự đáng ngạc nhiên, chẳng hạn, bạn sẽ thấy rằng số lượng cuộc gọi hệ thống có sẵn trên mỗi kiến ​​trúc là khác biệt và một số cuộc gọi hệ thống sẽ tồn tại trong một số kiến ​​trúc chứ không phải các cuộc gọi khác. (Ngay cả trên x86, danh sách các tòa nhà cao tầng khác nhau giữa hạt nhân 32 bit và 64 bit.)

Nói tóm lại, có rất nhiều trường hợp một kernel cần phải biết rằng nó dành riêng cho một nền tảng. Nhân Linux cố gắng trừu tượng hóa hầu hết các thuật toán đó, vì vậy các thuật toán cấp cao hơn (như cách quản lý bộ nhớ và lập lịch hoạt động) có thể được thực hiện trong C và hoạt động giống nhau (hoặc hầu hết giống nhau) trên tất cả các kiến ​​trúc.

57
filbranden

Ngoài việc chuyển nhân Linux, bạn sẽ cần xác định giao diện nhị phân ứng dụng (ABI) cho "không gian người dùng" chương trình và cổng các lớp thấp nhất của ngăn xếp phần mềm không gian người dùng. Linux thường được sử dụng với các thành phần không gian người dùng cấp thấp từ dự án GNU, trong đó quan trọng nhất là:

  • Trình biên dịch, trình biên dịch và trình liên kết C: GCC GNU Binutils . Đối với kiến ​​trúc CPU hoàn toàn mới, bạn cần chuyển phần mềm này trước khi bắt đầu chuyển kernel, vì kernel tự nó là chương trình C và phải được biên dịch. Nếu đã có hỗ trợ "back end" cho CPU nền tảng của bạn, thì không phải với Linux là nhân hệ điều hành, bạn sẽ có ít việc phải làm hơn và bạn có thể thoát khỏi hầu hết công việc cho đến khi kernel hết và đang chạy.
  • Thư viện thời gian chạy C: " GNU libc ". Thư viện này bao gồm mã mà thực hiện các cuộc gọi hệ thống và mặt khác tương tác trực tiếp với kernel.
  • Thư viện "giao diện chức năng nước ngoài", libffi , là thành phần thiết yếu của nhiều trình thông dịch ngôn ngữ cấp cao và thực hiện một trong số ít các tác vụ còn lại mà yêu cầu một lượng nhỏ ngôn ngữ hội viết tay.

Nhiều phần mềm khác có các thành phần phụ thuộc vào nền tảng tùy chọn; chẳng hạn, trình duyệt Web sẽ nhanh hơn đáng kể nếu bạn viết các nguyên hàm mã hóa được tối ưu hóa bằng tay cho NSS OpenSSL cho kiến ​​trúc CPU mới của bạn và back-end biên dịch đúng lúc cho IonMonkeyV8 . Nhưng những điều này không cần thiết để đưa lên một nền tảng mới.

10
zwol

Bạn phải nói với kernel về phần cứng mà bạn đang chuyển đến. Công việc của kernel là giao tiếp trực tiếp với phần cứng, vì vậy để nó hoạt động chính xác, kernel cần biết về CPU, bộ dao động (đồng hồ) và bất kỳ thiết bị ngoại vi nào, như các loại cổng nối tiếp khác nhau (SPI, CAN, I2C, v.v.).

Vào thời xưa, bạn sẽ làm điều này bằng cách viết mã cụ thể của nền tảng mà trình điều khiển sau đó sẽ sử dụng để hoạt động. Ngày nay, điều này được thực hiện bằng cách viết Định nghĩa cây thiết bị .

1
RubberDuck