2012-02-10 26 views
16
  1. Khi chương trình C được biên dịch và tệp đối tượng (ELF) được tạo. tệp đối tượng chứa các phần khác nhau như bss, dữ liệu, văn bản và các phân đoạn khác. Tôi hiểu rằng những phần này của ELF là một phần của không gian địa chỉ bộ nhớ ảo. Tôi có đúng không? Hãy sửa tôi nếu tôi sai.Các phân đoạn khác nhau như heap, stack, text liên quan đến bộ nhớ vật lý như thế nào?

  2. Ngoài ra, sẽ có bộ nhớ ảo và bảng trang được liên kết với chương trình được biên dịch. Bảng trang liên kết địa chỉ bộ nhớ ảo có trong ELF với địa chỉ bộ nhớ vật lý thực khi tải chương trình. Tôi hiểu có đúng không?

  3. Tôi đọc điều đó trong tệp ELF đã tạo, phần bss chỉ giữ tham chiếu của các biến toàn cục chưa được khởi tạo. Ở đây biến toàn cục chưa được khởi tạo có nghĩa là, các biến không được intialised trong quá trình khai báo?

  4. Ngoài ra, tôi đọc rằng các biến cục bộ sẽ được phân bổ không gian tại thời gian chạy (tức là trong ngăn xếp). Sau đó, chúng sẽ được tham chiếu như thế nào trong tệp đối tượng?

  5. Nếu trong chương trình, có một phần mã cụ thể có sẵn để cấp phát bộ nhớ động. Các biến này sẽ được tham chiếu như thế nào trong tệp đối tượng?

Tôi nhầm lẫn rằng các phân đoạn khác nhau của tệp đối tượng (như văn bản, rodata, dữ liệu, bss, ngăn xếp và đống) là một phần của bộ nhớ vật lý (RAM), nơi tất cả các chương trình được thực thi. Nhưng tôi cảm thấy rằng sự hiểu biết của tôi là sai. Các phân đoạn khác nhau này liên quan đến bộ nhớ vật lý như thế nào khi một quá trình hoặc một chương trình đang được thực hiện?

Trả lời

2

Tất cả các địa chỉ của các phần khác nhau (.text, .bss, .data, vv) mà bạn nhìn thấy khi bạn kiểm tra một ELF với lệnh kích thước:

$ size -A -x my_elf_binary 

là địa chỉ ảo. MMU với hệ điều hành thực hiện dịch từ các địa chỉ ảo đến địa chỉ vật lý RAM.

1

4. Nếu bạn xem mã lắp ráp được tạo bởi gcc, bạn có thể thấy các biến cục bộ bộ nhớ được cấp phát trong ngăn thông qua lệnh push hoặc thông qua thay đổi giá trị của thanh ghi ESP. Sau đó, chúng được bắt đầu với lệnh mov hoặc một cái gì đó tương tự.

3

Tôi không chắc chắn nếu 1, 2 và 3 là đúng nhưng tôi có thể giải thích 4 và 5.

: Họ được tham chiếu bởi bù đắp từ phía trên cùng của ngăn xếp. Khi thực hiện một hàm, phần đầu của ngăn xếp được tăng lên để phân bổ không gian cho các biến cục bộ. Trình biên dịch xác định thứ tự của các biến cục bộ trong ngăn xếp để trình biên dịch nows bù đắp các biến từ đỉnh của ngăn xếp.

Ngăn xếp trong bộ nhớ vật lý được đặt lộn ngược. Bắt đầu của stack thường có địa chỉ bộ nhớ cao nhất có sẵn. Khi các chương trình chạy và phân bổ không gian cho các biến cục bộ địa chỉ của phần trên cùng của các ngăn xếp ngăn xếp (và có khả năng dẫn đến tràn ngăn xếp - chồng chéo với các phân đoạn trên các địa chỉ thấp hơn :-))

: Sử dụng con trỏ - Địa chỉ biến phân bổ động được lưu trữ trong biến (cục bộ). Điều này tương ứng với việc sử dụng con trỏ trong C.

Tôi đã tìm thấy lời giải thích tốt đẹp ở đây: http://www.ualberta.ca/CNS/RESEARCH/LinuxClusters/mem.html

16

1. Đúng, file ELF đưa ra những địa điểm tuyệt đối hay tương đối trong không gian địa chỉ ảo của một quá trình mà hệ điều hành nên sao chép nội dung tập tin ELF vào. (Bss chỉ là một vị trí và kích thước, vì nó được cho là tất cả các số không, không cần phải thực sự có các số 0 trong tệp ELF). Lưu ý rằng các vị trí có thể là các vị trí tuyệt đối (như địa chỉ ảo 0x100000 hoặc các vị trí tương đối như 4096 byte sau khi kết thúc văn bản.)

2. Định nghĩa bộ nhớ ảo (được lưu giữ trong bảng trang và ánh xạ địa chỉ ảo đến vật lý) địa chỉ) không được liên kết với chương trình được biên dịch, nhưng với "quy trình" (hoặc "tác vụ" hoặc bất kỳ hệ điều hành nào của bạn gọi nó) đại diện cho một trường hợp đang chạy của chương trình đó. Ví dụ, một tệp ELF duy nhất có thể được nạp vào hai quy trình khác nhau, tại các địa chỉ ảo khác nhau (nếu tệp ELF có thể định vị lại).

3. Ngôn ngữ lập trình bạn đang sử dụng xác định trạng thái chưa được khởi tạo nào có trong bss và được khởi tạo rõ ràng. Lưu ý rằng bss không không chứa "tham chiếu" cho các biến này, nó bộ nhớ sao lưu các biến đó.

4. Biến ngăn xếp được tham chiếu hoàn toàn từ mã được tạo. Không có gì rõ ràng về chúng (hoặc thậm chí là ngăn xếp) trong tệp ELF.

5. Giống như tham chiếu ngăn xếp, tham chiếu đống được ẩn trong mã được tạo trong tệp ELF. (Tất cả chúng đều được lưu trữ trong bộ nhớ được tạo bằng cách thay đổi không gian địa chỉ ảo thông qua cuộc gọi đến sbrk hoặc tương đương của nó.)

Tệp ELF giải thích cho hệ điều hành cách thiết lập không gian địa chỉ ảo cho một phiên bản chương trình. Các phần khác nhau mô tả các nhu cầu khác nhau. Ví dụ: ".rodata" nói rằng tôi muốn lưu trữ dữ liệu chỉ đọc (trái ngược với mã thực thi). Phần ".text" có nghĩa là mã thực thi. "Bss" là một khu vực được sử dụng để lưu trữ trạng thái cần được zeroed bởi hệ điều hành. Không gian địa chỉ ảo có nghĩa là chương trình có thể (tùy chọn) dựa vào những thứ mà nó mong đợi khi nó khởi động. (Ví dụ, nếu nó yêu cầu các .bss ở địa chỉ 0x4000, thì hệ điều hành sẽ từ chối khởi động nó, hoặc nó sẽ ở đó.)

Lưu ý rằng các địa chỉ ảo này được ánh xạ tới địa chỉ vật lý bởi các bảng trang do hệ điều hành quản lý. Ví dụ về tệp ELF không cần biết bất kỳ chi tiết nào liên quan đến các trang vật lý nào được sử dụng.

2

Nếu bạn muốn biết những điều này, hãy tìm hiểu về hệ điều hành, với mã nguồn (www.kernel.org) nếu có thể.
Bạn cần nhận ra rằng hạt nhân HĐH thực sự đang chạy CPU và quản lý tài nguyên bộ nhớ. Và mã C chỉ là một kịch bản trọng lượng nhẹ để điều khiển hệ điều hành và chỉ chạy thao tác đơn giản với các thanh ghi.

  1. Bộ nhớ ảo và bộ nhớ vật lý về TLB của CPU cho phép người dùng xử lý bộ nhớ liền kề hầu như thông qua sức mạnh của phần cứng TLB (sử dụng bảng trang). Vì vậy, bộ nhớ vật lý thực tế, ánh xạ tới bộ nhớ ảo liền kề có thể được phân tán đến bất cứ đâu trên RAM. Chương trình biên dịch không biết về công cụ TLB này và công cụ địa chỉ bộ nhớ vật lý. Chúng được quản lý trong không gian hạt nhân OS.

  2. BSS là một phần mà hệ điều hành chuẩn bị không điền địa chỉ bộ nhớ, vì chúng không được khởi tạo trong mã nguồn c/C++, do đó được trình biên dịch/liên kết đánh dấu là bss. Ngăn xếp là một cái gì đó được chuẩn bị chỉ một lượng nhỏ bộ nhớ lúc đầu bởi hệ điều hành, và mỗi lần gọi hàm đã được thực hiện, địa chỉ sẽ được đẩy xuống, để có nhiều không gian hơn để đặt các biến cục bộ và bật lên khi bạn muốn trở về từ hàm. Bộ nhớ vật lý mới sẽ được cấp phát cho địa chỉ ảo khi bộ nhớ nhỏ đầu tiên đầy và đạt tới đáy và lỗi ngoại lệ sẽ xảy ra, và hạt nhân OS sẽ chuẩn bị bộ nhớ vật lý mới và quá trình người dùng có thể tiếp tục làm việc .

  3. Không có phép thuật. Trong mã đối tượng, mọi hoạt động được thực hiện đối với con trỏ được trả về từ malloc được xử lý dưới dạng giá trị bù trừ cho giá trị đăng ký được trả về từ cuộc gọi hàm malloc.

Thực ra malloc đang làm những điều khá phức tạp. Có nhiều triển khai khác nhau (jemalloc/ptmalloc/dlmalloc/googlemalloc/...) để cải thiện phân bổ động, nhưng thực ra chúng đều nhận vùng bộ nhớ mới từ hệ điều hành bằng sbrk hoặc mmap (/ dev/zero), được gọi là bộ nhớ ẩn danh .

2

Chỉ cần làm một người đàn ông trên lệnh đọc để tìm ra địa chỉ bắt đầu của các phân đoạn khác nhau trong chương trình của bạn.

Về câu hỏi đầu tiên bạn hoàn toàn đúng. Vì hầu hết các hệ thống ngày nay sử dụng ràng buộc thời gian chạy, nó chỉ là trong quá trình thực thi mà các địa chỉ vật lý thực tế được biết đến. Hơn nữa, nó là trình biên dịch và bộ nạp phân chia chương trình thành các phân đoạn khác nhau sau khi liên kết các thư viện khác nhau trong thời gian biên dịch và tải. Do đó, các địa chỉ ảo.

Đến câu hỏi thứ hai, đó là thời gian chạy do ràng buộc thời gian chạy. Câu hỏi thứ ba là đúng. Tất cả các biến toàn cục chưa được khởi tạo và biến tĩnh đi vào BSS. Cũng lưu ý trường hợp đặc biệt: chúng đi vào BSS ngay cả khi chúng được khởi tạo đến 0.

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