Điều này không đúng với hầu hết các OS OS. Các loại vùng nhớ được biểu thị khá điển hình, nhưng không có lý do tại sao chúng phải theo thứ tự cụ thể và có thể có nhiều hơn một loại nhất định.
Dưới Linux, bạn có thể nhìn vào không gian địa chỉ của một quá trình với cat /proc/$pid/maps
nơi $pid
là quá trình ID, ví dụ như cat /proc/$$/maps
nhìn vào vỏ bạn đang chạy cat
từ, hoặc cat /proc/self/maps
để nhìn vào cat
ánh xạ riêng của quá trình. Lệnh pmap
tạo đầu ra đẹp hơn một chút.
08048000-08054000 r-xp 00000000 08:01 828061 /bin/cat
08054000-08055000 r--p 0000b000 08:01 828061 /bin/cat
08055000-08056000 rw-p 0000c000 08:01 828061 /bin/cat
08c7f000-08ca0000 rw-p 00000000 00:00 0 [heap]
b755a000-b7599000 r--p 00000000 08:01 273200 /usr/lib/locale/en_US.utf8/LC_CTYPE
b7599000-b759a000 rw-p 00000000 00:00 0
b759a000-b76ed000 r-xp 00000000 08:01 269273 /lib/tls/i686/cmov/libc-2.11.1.so
b76ed000-b76ee000 ---p 00153000 08:01 269273 /lib/tls/i686/cmov/libc-2.11.1.so
b76ee000-b76f0000 r--p 00153000 08:01 269273 /lib/tls/i686/cmov/libc-2.11.1.so
b76f0000-b76f1000 rw-p 00155000 08:01 269273 /lib/tls/i686/cmov/libc-2.11.1.so
b76f1000-b76f4000 rw-p 00000000 00:00 0
b770b000-b7712000 r--s 00000000 08:01 271618 /usr/lib/gconv/gconv-modules.cache
b7712000-b7714000 rw-p 00000000 00:00 0
b7714000-b7715000 r-xp 00000000 00:00 0 [vdso]
b7715000-b7730000 r-xp 00000000 08:01 263049 /lib/ld-2.11.1.so
b7730000-b7731000 r--p 0001a000 08:01 263049 /lib/ld-2.11.1.so
b7731000-b7732000 rw-p 0001b000 08:01 263049 /lib/ld-2.11.1.so
bfbec000-bfc01000 rw-p 00000000 00:00 0 [stack]
Bạn có thể xem mã và dữ liệu đọc (văn bản và BSS) từ tệp thực thi, sau đó là heap, sau đó là tệp ánh xạ bộ nhớ, sau đó thêm một chút dữ liệu đọc, sau đó mã, dữ liệu chỉ đọc và đọc ghi dữ liệu từ thư viện dùng chung (lại văn bản và BSS), dữ liệu đọc-ghi nhiều hơn, thư viện chia sẻ khác (chính xác hơn là trình liên kết động) và cuối cùng là ngăn xếp của luồng duy nhất.
Mã hạt nhân sử dụng phạm vi địa chỉ riêng của nó. Trên nhiều nền tảng, Linux sử dụng phần trên của không gian địa chỉ cho kernel, thường là phần trên 1GB. Lý tưởng nhất, không gian này sẽ đủ để ánh xạ mã kernel, dữ liệu kernel và bộ nhớ hệ thống (RAM) và mọi thiết bị ánh xạ bộ nhớ. Trên các PC 32 bit thông thường hiện nay, điều này là không thể, điều này đòi hỏi các mâu thuẫn chỉ dành cho các tin tặc kernel.
Trong khi mã hạt nhân đang xử lý một cuộc gọi hệ thống, lý tưởng nhất là khi không có các mâu thuẫn nói trên), bộ nhớ của quy trình được ánh xạ tại cùng một địa chỉ. Điều này cho phép các quá trình truyền dữ liệu đến kernel và kernel có thể đọc trực tiếp từ con trỏ. Tuy nhiên, đó không phải là một lợi ích lớn vì các con trỏ cần phải được xác nhận hợp lệ (để quá trình không thể lừa kernel đọc từ bộ nhớ mà quá trình không được phép truy cập).
Các vùng bộ nhớ trong không gian nhân Linux khá phức tạp. Có một số nhóm bộ nhớ khác nhau và sự khác biệt chính không phải là bộ nhớ đến từ đâu mà là nó được chia sẻ với ai. Nếu bạn tò mò về chúng, hãy bắt đầu với LDD3 .
where.c
trên Ubuntu 11.04 bằng cách sử dụnggcc where.c -o where
; báo cáo "chính tại 0x80483c4". Đã thửreadelf -S where
, và nó báo cáo, nói "[13] .text PROGBITS 08048 310 ..." trông như thế nào phải không? Mặc dù tôi cũng nhận được "ac ở 0xbfb035a0" và "cục bộ tại 0xbfb0353c", và phạm vi địa chỉ đó (0xbf ...) dường như không được báo cáo bởireadelf -S
.