Câu hỏi của tôi là liệu mã trong các thư viện đó sẽ phân bổ bộ nhớ trong cùng một vùng với ứng dụng chính hay chúng có sử dụng đống của riêng mình không?
Nếu thư viện sử dụng cùng một malloc/free
làm ứng dụng (ví dụ: glibc
) - thì có, chương trình và tất cả thư viện sẽ sử dụng một vùng.
Nếu thư viện sử dụng trực tiếp mmap
, nó có thể cấp phát bộ nhớ không phải là bộ nhớ được chương trình sử dụng.
Ví dụ: một số chức năng trong tệp .so gọi malloc, nó có sử dụng trình quản lý heap giống như ứng dụng hoặc ứng dụng khác không?
Nếu hàm từ .so gọi malloc, malloc này giống như malloc được gọi từ chương trình. Bạn có thể thấy biểu tượng ràng buộc đăng nhập trong Linux/glibc (> 2.1) với
LD_DEBUG=bindings ./your_program
Vâng, một số trường hợp cán bộ quản lý heap (với cấu hình mặc định) không thể cùng tồn tại mà không biết về nhau (vấn đề là với giữ kích thước heap được phân bổ brk được đồng bộ giữa các cá thể). Nhưng có một cấu hình có thể xảy ra khi một số trường hợp có thể cùng tồn tại.
Hầu hết các triển khai malloc cổ điển (ptmalloc *, dlmalloc, v.v ...) đều có thể sử dụng hai phương pháp lấy bộ nhớ từ hệ thống: brk
và mmap
. Brk là đống cổ điển, tuyến tính và có thể phát triển hoặc co lại. Mmap cho phép nhận nhiều bộ nhớ ở bất cứ đâu; và bạn có thể trả lại bộ nhớ này về hệ thống (miễn phí) theo bất kỳ thứ tự nào.
Khi malloc được xây dựng, phương pháp brk có thể bị tắt. Sau đó, malloc sẽ mô phỏng heap tuyến tính bằng cách sử dụng chỉ mmap
s hoặc thậm chí sẽ vô hiệu hóa đống tuyến tính cổ điển và tất cả các phân bổ sẽ được thực hiện từ các mảnh vỡ mmaped không liên tục.
Vì vậy, một số thư viện có thể có trình quản lý bộ nhớ riêng, ví dụ: malloc
được biên dịch với brk
bị vô hiệu hóa hoặc với trình quản lý bộ nhớ không phải là malloc. Người quản lý này phải có tên chức năng khác với malloc
và free
, ví dụ: malloc1
và free1
hoặc không được hiển thị/xuất tên này thành liên kết động.
Ngoài ra, điều gì về dữ liệu chung trong những kỷ niệm được chia sẻ đó. Nó nói dối ở đâu?Tôi biết cho các ứng dụng nó nằm trong phân đoạn bss và dữ liệu, nhưng không biết nó được cho những tập tin đối tượng được chia sẻ.
Bạn nên nghĩ cả về chương trình và .so cũng giống như tệp ELF. Mỗi tập tin ELF có "tiêu đề chương trình" (readelf -l elf_file
). Cách thức dữ liệu được nạp từ ELF vào bộ nhớ phụ thuộc vào loại tiêu đề chương trình. Nếu loại là "LOAD
", phần tương ứng của tệp sẽ là riêng tư mmap
ed (Sic!) Vào bộ nhớ. Thông thường, có 2 phân đoạn LOAD; đầu tiên cho mã với R + X (đọc + thực hiện) cờ và thứ hai là cho dữ liệu với R + W (đọc + viết) cờ. Cả hai phần .bss
và .data
(dữ liệu chung) được đặt trong phân đoạn LOAD với cờ được bật ghi.
Cả thư viện có thể thực thi và được chia sẻ đều có phân đoạn LOAD. Một số phân đoạn có memory_size> file_size. Nó có nghĩa là phân đoạn sẽ được mở rộng trong bộ nhớ; Phần đầu của nó sẽ được lấp đầy với các dữ liệu từ file ELF, và phần thứ hai của kích thước (memory_size-FILE_SIZESEPARATOR) sẽ được lấp đầy với zero (ví *bss
phần), sử dụng mmap(/dev/zero)
và memset(0)
Khi Kernel hoặc tải mối liên kết động ELF tập tin vào bộ nhớ, họ sẽ không nghĩ về việc chia sẻ. Ví dụ, bạn muốn bắt đầu cùng một chương trình hai lần. Quá trình đầu tiên sẽ tải phần chỉ đọc của tập tin ELF với mmap; quá trình thứ hai sẽ làm cùng một mmap (nếu aslr đang hoạt động - mmap thứ hai sẽ được vào địa chỉ ảo khác nhau). Đó là nhiệm vụ của bộ đệm trang (hệ thống con VFS) để giữ một bản sao dữ liệu trong bộ nhớ vật lý (với COPY-on-WRITE aka COW); và mmap sẽ chỉ thiết lập ánh xạ từ địa chỉ ảo trong mỗi quá trình vào một vị trí thực. Nếu bất kỳ quá trình nào sẽ thay đổi trang bộ nhớ; nó sẽ được sao chép vào ghi vào bộ nhớ vật lý riêng tư duy nhất.
tải code đang trong glibc/elf/dl-load.c
(_dl_map_object_from_fd
) cho ld.so và linux-kernel/fs/binfmt_elf.c
cho bộ nạp ELF kernel của (elf_map
, load_elf_binary
). Thực hiện tìm kiếm PT_LOAD
.
Vì vậy, dữ liệu toàn cầu và dữ liệu bss luôn được tạo riêng tư trong mỗi quá trình và chúng được bảo vệ bằng COW.
Heap và ngăn xếp được phân bổ trong thời gian chạy với brk + mmap (heap) và hệ điều hành hạt nhân tự động trong quá trình giống như brk (cho ngăn xếp của chủ đề chính). Ngăn xếp của chuỗi bổ sung được phân bổ với mmap
trong pthread_create
.
Bạn có hỏi liệu các phần của thư viện được chia sẻ có được tổng hợp với các phần thực thi ban đầu có liên kết động không? –
Các thư viện BSS và Phân đoạn dữ liệu được chia sẻ sẽ phần nào tách biệt phần còn lại của phân đoạn BSS và Dữ liệu của ứng dụng, nhưng đó là tất cả được xử lý bởi hệ thống cho bạn. –