Ai đó có thể cho tôi biết quá trình nào của hệ điều hành tải tệp ELF (định dạng thực thi và liên kết) vào RAM không?
Ai đó có thể cho tôi biết quá trình nào của hệ điều hành tải tệp ELF (định dạng thực thi và liên kết) vào RAM không?
Câu trả lời:
Một người dùng thường gặp ba loại tệp ELF Tệp .o, tệp thực thi thông thường và thư viện dùng chung. Mặc dù tất cả các tệp này phục vụ các mục đích khác nhau, các tệp cấu trúc bên trong của chúng khá giống nhau.
Một khái niệm phổ biến trong số tất cả các loại tệp ELF khác nhau (và cả a.out và nhiều định dạng tệp thực thi khác) là khái niệm về một phần. Một phần là một tập hợp thông tin của một loại tương tự. Mỗi phần đại diện cho một phần của tập tin. Ví dụ, mã thực thi luôn được đặt trong một phần được gọi là .text ; tất cả các biến dữ liệu do người dùng khởi tạo được đặt trong một phần được gọi là .data ; và dữ liệu chưa được khởi tạo được đặt trong một phần được gọi là .bss .
Trên thực tế, người ta có thể tạo ra một định dạng tệp thực thi trong đó mọi thứ được xáo trộn với nhau (như MS DOS). Nhưng chia thực thi thành các phần có lợi thế quan trọng. Ví dụ, một khi bạn đã tải các phần thực thi của một tệp thực thi vào bộ nhớ, các vị trí bộ nhớ này không cần phải thay đổi. Trên các kiến trúc máy hiện đại, trình quản lý bộ nhớ có thể đánh dấu các phần của bộ nhớ chỉ đọc, sao cho mọi nỗ lực sửa đổi vị trí bộ nhớ chỉ đọc đều dẫn đến việc chương trình bị chết và đổ lõi. Do đó, thay vì chỉ nói rằng chúng tôi không mong đợi một vị trí bộ nhớ cụ thể thay đổi, chúng tôi có thể chỉ định rằng mọi nỗ lực sửa đổi vị trí bộ nhớ chỉ đọc là một lỗi nghiêm trọng cho thấy lỗi trong ứng dụng. Điều đó đang được nói, thông thường, bạn không thể đặt riêng trạng thái chỉ đọc cho mỗi byte của bộ nhớ, thay vào đó bạn có thể đặt riêng các phần bảo vệ của các vùng của bộ nhớ được gọi là các trang.
Vì chúng tôi muốn tất cả các phần có thể thực thi của một bộ nhớ thực thi trong bộ nhớ chỉ đọc và tất cả các vị trí bộ nhớ có thể sửa đổi (như các biến) trong bộ nhớ có thể ghi, hóa ra là hiệu quả nhất để nhóm tất cả các phần có thể thực thi của một phần thực thi thành một phần của bộ nhớ ( phần .text ) và tất cả các vùng dữ liệu có thể sửa đổi cùng nhau vào một vùng nhớ khác (từ đó được gọi là phần .data ).
Một phân biệt nữa được thực hiện giữa các biến dữ liệu mà người dùng đã khởi tạo và biến dữ liệu mà người dùng chưa khởi tạo. Nếu người dùng không chỉ định giá trị ban đầu của một biến, sẽ không có cảm giác lãng phí không gian trong tệp thực thi để lưu trữ giá trị. Do đó, các biến khởi tạo được nhóm vào phần .data và các biến chưa được khởi tạo được nhóm vào phần .bss, điều này đặc biệt vì nó không chiếm dung lượng trong tệp. Nó chỉ cho biết cần bao nhiêu dung lượng cho các biến chưa được khởi tạo.
Khi bạn yêu cầu kernel tải và chạy một tệp thực thi, nó sẽ bắt đầu bằng cách nhìn vào tiêu đề hình ảnh để tìm manh mối về cách tải hình ảnh. Nó định vị phần .text trong tệp thực thi, tải nó vào các phần bộ nhớ thích hợp và đánh dấu các trang này là chỉ đọc. Sau đó, nó định vị phần .data trong tệp thực thi và tải nó vào không gian địa chỉ của người dùng, lần này là trong bộ nhớ đọc-ghi. Cuối cùng, nó tìm thấy vị trí và kích thước của phần .bss từ tiêu đề hình ảnh và thêm các trang bộ nhớ phù hợp vào không gian địa chỉ của người dùng. Mặc dù người dùng chưa chỉ định các giá trị ban đầu của các biến được đặt trong .bss, theo quy ước, hạt nhân sẽ khởi tạo tất cả bộ nhớ này về 0.
Vì vậy, bạn thấy, nó thực sự là hạt nhân phát hành các lệnh để tải thực thi trong bộ nhớ. Phần văn bản là kết quả của bất kỳ cuộc gọi như vậy được tải trong bộ nhớ chỉ đọc và phần dữ liệu được tải trong bộ nhớ đọc ghi.
Nó phụ thuộc vào hệ điều hành.
Ví dụ, trên GNU Hurd, tệp thực thi được tải bởi máy chủ exec .
Trên một hệ điều hành nguyên khối điển hình hơn, điều này được thực hiện bởi:
kernel ánh xạ tệp thực thi và trình liên kết động trong bộ nhớ;
trình liên kết động mmaps các đối tượng chia sẻ trong bộ nhớ.
Bản thân hạt nhân Linux được lưu trữ dưới dạng tệp ELF: tệp này được tải bởi bộ tải khởi động (chẳng hạn như GRUB).
ld-linux.so
, đó là một quá trình người dùng.