2015-12-07 19 views
6

Tôi đã bắt đầu hành trình của mình thông qua phát triển hệ điều hành. Mọi người thường hét rằng sử dụng nhị phân thô thay vì ELF (hoặc định dạng có cấu trúc khác) là một lỗi phổ biến cho các ứng dụng trong hệ điều hành tùy chỉnh. Tôi có thể thứ hai là vì các lợi ích bổ sung mà ELF cung cấp (những nơi lưu trữ các biến thể như bảng biểu tượng, .debug và .line). Tuy nhiên, chúng ta hãy suy nghĩ về bản thân kernel nhị phân trong một phút. Nó có nên được cấu trúc (như ELF) và nếu có, tại sao? Nếu không viết một bộ nạp ELF và ép nó ngay sau khi bộ nạp stage1 có vẻ như là một sự lãng phí.Tôi có nên tạo ELF hạt nhân hệ điều hành của riêng mình hoặc nhị phân thô không?

AFAIK Linux kernel là một tệp ELF nhưng tôi không biết lý do tại sao.

+0

Nó có thể là câu hỏi hay, nhưng câu trả lời có thể có trên nó có vẻ là chủ yếu dựa vào ý kiến, đó là không thích hợp cho Stack Overflow. Theo quan điểm của tôi, có kích thước và thời gian khởi động tối thiểu cho hạt nhân là tốt, nhưng giao dịch tính năng này với chi phí phát triển, bảo trì, vv chỉ đáng giá khi ** hiệu suất rất quan trọng **. Nếu đó là trường hợp của bạn, thì bạn được tự do sử dụng các phương thức * any * để giảm kích thước và thời gian khởi động của hạt nhân. – Tsyvarev

+0

@Tsyvarev, bởi chi phí cho việc phát triển vv bạn có ý nghĩa dễ gỡ rối khi thông tin về dòng mã được lưu giữ trong thời gian chạy? –

+1

Không chỉ thông tin gỡ rối có thể được lưu trữ trong các phần ELF bổ sung. Ví dụ: hạt nhân Linux sử dụng các phần bổ sung cho danh sách cửa hàng các biểu tượng, được xuất cho các mô-đun hạt nhân. Ngoài ra, hạt nhân Linux có khái niệm về '.init' mã/dữ liệu phần, được nạp vào bộ nhớ, nhưng giảm sau khi khởi tạo đã được hoàn thành, do đó làm giảm việc sử dụng bộ nhớ. – Tsyvarev

Trả lời

10

Tôi đã tranh luận xem tôi có nên đi sâu vào một câu hỏi rộng dẫn đến câu trả lời có ý kiến ​​hay không. Tôi thường bỏ phiếu để đóng một câu hỏi như thế này, nhưng trong trường hợp này tôi sẽ cung cấp một phản ứng có thể có lợi cho người khác. Nếu bạn hỏi Tại sao? Tôi đang làm điều đó cho câu hỏi này - lịch sử đã được hiển thị trên Stackoverflow rằng câu hỏi này thường được hỏi gián tiếp như là một phần của câu hỏi phát triển hệ điều hành cụ thể hơn.


Một số ưu điểm của ELF cho hạt nhân?

  • thông tin gỡ lỗi có thể được nhúng trong đối tượng
  • Một ELF bộ nạp có thể thiết lập hình ảnh trong bộ nhớ, không ra phần BSS tự động, vv
  • uninitialized hoặc không có dữ liệu toàn cầu khởi doesn' t chiếm phòng bên trong hình ảnh.
  • Trình tải khởi động tương thích Multiboot (như GRUB) có thể tải các tệp thi hành ELF được thiết kế phù hợp
  • Có thể được thiết kế để có thể định vị lại.

Nhược điểm?

  • tiêu đề ELF được đặt vào đầu thực thi mà có thể ảnh hưởng môi trường mục tiêu dự định thực thi sẽ chạy trong (như Bootloader)
  • Đối với chương trình nhỏ các tiêu đề ELF thể quá lớn đối với một số mục đích sử dụng (bootloaders)
  • Yêu cầu mã (bộ nạp ELF tối thiểu) để khởi động một tệp thực thi vào bộ nhớ và bắt đầu thực thi nó.

Tại sao chúng ta không sử dụng ELF cho một hình ảnh boot sector cuối cùng (MBR)?

Lý do chính là định dạng ELF đặt thông tin tiêu đề trước mã. BIOS kế thừa (không phải EFI) sẽ không hiểu và bắt đầu thực hiện thông tin tiêu đề dưới dạng mã.


Bạn có thể sử dụng hình ảnh ELF để gỡ lỗi bộ tải khởi động 16 bit không?

Tùy thuộc vào môi trường và trình gỡ lỗi. Với điều khiển từ xa GDB gỡ lỗi trong QEMU điều này là rất có thể. Bạn có thể tạo một 16-bit chế độ thực thi trong một lắp ráp như NASM/GAS vv như một đối tượng ELF (với Dwarf thông tin debug), liên kết nó với một thực thi ELF cuối cùng và sau đó sử dụng một chương trình như objcopy để loại bỏ các tiêu đề ELF để tạo ra nhị phân phẳng cuối cùng.

Tại sao lại tạo ra các đối tượng ELF cho bộ nạp khởi động nếu bạn tách nó xuống dạng nhị phân phẳng?

Mặc dù một số nhị phân lột xuống sẽ chạy trong môi trường mục tiêu, một môi trường với khả năng gỡ lỗi từ xa như QEMU có thể sử dụng một số nhị phân ELF địa phương để giải quyết tên biến, nhãn, hằng, và cho phép nguồn gốc để được điều hướng (không chỉ lắp ráp).

Bạn có thể cung cấp ví dụ về kỹ thuật này để gỡ lỗi 16 bit không?

Có, loại sự cố này đã xuất hiện trước đó. Tôi đã cung cấp câu trả lời cho biết cách thực hiện điều này với các dịch vụ gỡ lỗi từ xa của GDB và trình gỡ lỗi từ xa trong QEMU. Một ví dụ như vậy có thể được tìm thấy trong số này StackOverflow answer. Ví dụ này là trình tải khởi động 16 bit mẫu có thể được gỡ lỗi với GDB. Gỡ lỗi 16 bit có vấn đề với GDB vì nó không có sự hiểu biết về phân đoạn: cặp bù đắp trong mã 16 bit. Một liên kết được cung cấp cho tập lệnh giúp liên quan, cùng với ví dụ QEMU cách sử dụng.


Có lợi thế nào với ELF khi được sử dụng với trình tải Multiboot không?

Có! Một lợi thế lớn cho bộ tải khởi động tương thích Multiboot như GRUB là nó hiểu được hình ảnh ELF. Nếu bạn đang viết kernel mode được bảo vệ, và bạn sử dụng một thực thi tương thích Multiboot được xây dựng đúng cho kernel của bạn - bạn có thể lưu trên drudgery (trên hệ thống x86) thiết lập môi trường chế độ được bảo vệ, A20 Gate cho phép, lấy bản đồ bộ nhớ và khởi tạo chế độ chế độ video khởi động.

QEMU có thể khởi chạy hạt nhân ELF tương thích Multiboot trực tiếp không?

Có, với dòng lệnh thích hợp sử dụng tùy chọn -kernel, điều đó là có thể. OS Dev Wiki có một ví dụ.

Bạn có thể gỡ lỗi chế độ được bảo vệ 32 bit bằng cách sử dụng các tệp nhị phân ELF có thông tin gỡ lỗi không?

Có, đây là đơn giản hơn làm việc đó cho 16-bit Bootloader chạy trong chế độ thực. Tôi cung cấp một ví dụ về kỹ thuật này trong StackOverflow answer này. Mặc dù kỹ thuật này là dành cho QEMU sử dụng một hình ảnh ISO, bạn có thể lựa chọn tải lên QEMU với kernel multiboot của bạn trực tiếp bằng cách sử dụng tùy chọn -kernel.


Tại sao các phiên bản Linux hiện đại sử dụng định dạng ELF cho hạt nhân?

Trong những ngày cổ xưa về phát triển Linux, Linux có bộ nạp khởi động riêng, thiết lập chế độ bảo vệ, bật cổng A20 vv. Quá trình này khác nhau giữa các kiến ​​trúc. Một điểm đến nơi các nhà phát triển hạt nhân Linux đã chọn để rời khỏi công việc đó cho đến bộ nạp khởi động của bên thứ ba.

Trên hệ thống máy tính để bàn hiện đại, bạn sẽ tìm thấy GRUB được sử dụng làm bộ tải Muliboot; ELILO có thể được sử dụng; trên một số hệ thống nhúng U-Boot trở thành bộ nạp khởi động được lựa chọn. Đặc tả Multiboot phát sinh từ sự cần thiết phải khởi động một hạt nhân Linux, nhưng làm nó độc lập với hệ điều hành. Nhiều ví dụ về hạt nhân đồ chơi trên internet được mã hóa để được sử dụng như các tệp thi hành ELF để chúng có thể tận dụng những gì mà bộ tải khởi động tương thích Multiboot cung cấp.

Thông tin thêm về các đặc điểm kỹ thuật Multiboot có thể được tìm thấy trong GRUB Documentation

+0

Một lời giải thích tuyệt vời và đầy đủ, cảm ơn bạn, thưa bạn! –

1

a.out có thể là sự thỏa hiệp tốt hơn giữa nhị phân thô/căn hộ và ELF. Trong a.out bạn có thể tách mã khỏi dữ liệu từ dữ liệu chưa được thực hiện giống như trong ELF và bạn có thể định vị lại (và ký hiệu, nếu bạn quan tâm), không phải trong số đó bạn nhận được trong một nhị phân thô/thuần mà không tái phát minh một phần rõ ràng. Tuy nhiên, a.out là đơn giản hơn nhiều so với ELF, gần như đơn giản như nguyên/căn hộ. Rất dễ dàng để phân tích cú pháp và tải (trừ khi bạn đang thực hiện nó trong mã lắp ráp 16 bit như tôi đã làm trong trình biên dịch DPMI của trình biên dịch của tôi :).

Các vấn đề liên quan