2014-10-09 17 views
7

Tôi đang xem xét bố cục bộ nhớ của một quy trình nhất định. Tôi nhận thấy rằng vị trí bộ nhớ bắt đầu của mỗi quá trình không phải là 0. Trên website này, TEXT bắt đầu tại 0x08048000. Một lý do có thể là để phân biệt địa chỉ với con trỏ NULL. Tôi chỉ tự hỏi liệu có lý do nào khác tốt không? Cảm ơn.vị trí bắt đầu bộ nhớ trong C

+0

Tại sao là 0x00400000 địa chỉ cơ sở mặc định cho một thực thi? http://blogs.msdn.com/b/oldnewthing/archive/2014/10/03/10562176.aspx – auselen

Trả lời

0

A bộ tải tải nhị phân trong phân đoạn vào bộ nhớ: văn bản (hằng số), dữ liệu, mã. Không cần phải bắt đầu từ 0, và khi C có vấn đề từ các lỗi truy cập xung quanh null, như trong a[i] thậm chí còn nguy hiểm. Điều này cho phép (trên một số bộ xử lý) để chặn các lỗi phân đoạn.

Nó sẽ là thời gian chạy C giới thiệu một không gian địa chỉ tuyến tính từ 0. Đó có thể là tưởng tượng trong đó C là ngôn ngữ triển khai của hệ điều hành. Nhưng phục vụ không có mục đích; để có heap bắt đầu từ 0. Mô hình bộ nhớ là một trong các phân đoạn. Một đoạn mã có thể được bảo vệ chống lại sửa đổi bởi một số bộ vi xử lý.

Và trong phân đoạn phân đoạn xảy ra trong khối bộ nhớ được quản lý trong thời gian chạy C.

Tôi có thể thêm, vật lý 0 trở lên thường được chính hệ điều hành sử dụng.

2

Tôi nghĩ rằng đây tóm nó lên:

Mỗi tiến trình có thiết lập riêng của bảng trang, nhưng có một nhược điểm. Khi địa chỉ ảo được bật, chúng sẽ áp dụng cho tất cả phần mềm đang chạy trong máy, bao gồm cả hạt nhân. Vì vậy, một phần của không gian địa chỉ ảo phải được dành riêng cho hạt nhân.

Vì vậy, trong khi quá trình nhận được không gian địa chỉ của chính nó. Nếu không phân bổ một khối cho hạt nhân, nó sẽ không thể địa chỉ mã hạt nhân và dữ liệu.

Đây luôn là khối bộ nhớ đầu tiên nó xuất hiện và bao gồm địa chỉ 0. Không gian chế độ người dùng bắt đầu vượt quá điều này, và đó là nơi cả ngăn xếp và vùng lưu trữ.

Phân biệt từ NULL con trỏ

Ngay cả khi không gian chế độ người dùng bắt đầu tại địa chỉ 0, sẽ không có bất kỳ dữ liệu phân bổ cho các địa chỉ 0 như đó sẽ là trong ngăn xếp hoặc đống mà bản thân nó không bắt đầu ở đầu khu vực người dùng. Do đó, NULL (với giá trị 0) có thể được sử dụng và không phải là lý do cho bố cục này.

Tuy nhiên, một lợi ích liên quan đến NULL và khối đầu tiên là bộ nhớ hạt nhân là bất kỳ nỗ lực nào để đọc/ghi vào NULL sẽ ném một lỗi phân đoạn.

+0

Tuy nhiên, những gì chính xác nằm trong phạm vi '0 .. 0x08048000'? –

3

Con trỏ rỗng không thực sự phải bằng 0. Nó được đảm bảo trong tiêu chuẩn C khi giá trị 0 được đưa ra trong ngữ cảnh của con trỏ được trình biên dịch coi là NULL.

Nhưng 0 mà bạn sử dụng trong mã nguồn chỉ là đường cú pháp không có liên quan đến địa chỉ thực tế mà giá trị con trỏ null là "trỏ" tới.

Để biết thêm chi tiết xem:

Một ứng dụng trên hệ điều hành của bạn có không gian của nó độc đáo địa chỉ, mà họ coi như một khối liên tục của bộ nhớ (bộ nhớ không phải là vật lý liên tục, nó chỉ là "ấn tượng" mà hệ điều hành cung cấp cho mọi chương trình).

Đối với hầu hết các phần, không gian bộ nhớ ảo của mỗi quá trình được đặt ra một cách tương tự và dự đoán được (đây là cách bố trí bộ nhớ trong một quá trình Linux, chế độ 32-bit):

Memory layout in a Linux process (hình ảnh từ Anatomy of a Program in Memory)

Nhìn vào đoạn văn bản (cơ sở mặc định .tiếp theo trên x86 là 0x08048000, được chọn bởi tập lệnh trình liên kết mặc định để gắn kết tĩnh).

Tại sao phép thuật 0x08048000? Có khả năng vì Linux mượn địa chỉ đó từ System V i386 ABI.

... và tại sao Hệ thống V sử dụng 0x08048000?

Giá trị được chọn để phù hợp với ngăn xếp bên dưới phần .tiếp theo, giảm dần. Các byte 0x48000 có thể được ánh xạ bởi cùng một trang bảng đã được yêu cầu bởi phần .text (do đó tiết kiệm một bảng trang trong hầu hết các trường hợp), trong khi 0x08000000 còn lại sẽ cho phép nhiều phòng cho các ứng dụng xếp chồng.

Có điều gì dưới 0x08048000 không? Có thể không có gì (chỉ 128M), nhưng you can pretty much map anything you desire there, using the mmap() system call.

Xem thêm:

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