2012-03-15 41 views
5

Tôi mới vào "fork()", tôi đọc ở khắp mọi nơi khi một ngã ba() được gọi là bản sao chính xác của quá trình hiện tại (gọi) được bắt đầu. Khi tôi chạy mã sau, cần có hai quy trình khác nhau, hai vị trí bộ nhớ khác nhau được gán cho các vars và chức năng của chúng.Cách bộ nhớ được ánh xạ khi sử dụng nĩa?

#include<stdio.h> 
int i=10; 
int pid; 
int main(){ 
    if((pid=fork())==0){ 
    i++;//somewhere I read that separate memory space for child is created when write is needed 
    printf("parent address= %p\n",&i);// this should return the address from parent's memory space 
    }else{ 
    i++; 
    i++; 
    printf("child address= %p\n",&i);// this should return the address of child's memory space 
    } 
    wait(0); 
    return(0); 
} 
 
Why The output looks like:: 
child address::804a01c 
parent address::804a01c 

Tại sao cả hai địa chỉ là như nhau cho cha mẹ cũng như đứa trẻ?

+4

Chúng * tốt hơn * giống nhau. Bạn muốn các con trỏ tham chiếu bộ nhớ theo cùng một cách trong cả hai quy trình (ngay cả khi cả hai khối bộ nhớ đều khác nhau). Đọc về * bộ nhớ ảo *, điều này sẽ trả lời câu hỏi của bạn. –

+1

Lưu ý rằng * giá trị * của 'i' khác nhau giữa cha mẹ và con, mặc dù cả hai bản sao được lưu trữ tại cùng một địa chỉ ảo. – markgz

Trả lời

8

có hai vị trí bộ nhớ khác nhau được gán cho vars và chức năng của chúng.

Không; Linux triển khai virtual memory, có nghĩa là mỗi quy trình có không gian địa chỉ đầy đủ của riêng nó. Kết quả là, sau fork, cả hai quy trình đều thấy cùng địa chỉ cho bản sao của các đối tượng trong bộ nhớ của chúng.

:

+4

Sự “sang một bên” là một thực tế khá quan trọng: không có gì thực sự được sao chép khi tiến trình con được sinh ra. Điều này sẽ là một mất mát hiệu suất rất lớn, cho rằng forking xảy ra rất thường xuyên trên Unixes (hầu như mỗi khi bạn sinh ra một quá trình mới). Cơ chế chính xác dựa trên "lỗi trang". Bạn có thể muốn đọc về chúng nếu bạn quan tâm. –

+0

ok, vậy làm thế nào chúng ta có thể nhận được địa chỉ thực tế của var đó chứ không phải địa chỉ ảo? (Chỉ yêu cầu thỏa mãn sự tò mò của tôi) – buch11

+1

@ buch11: Tôi nghĩ bạn không thể, nhưng tôi sẽ cho phép các chuyên gia xác nhận. Dù sao, bạn không nên. Loại thông tin này chỉ được hạt nhân biết, và nó sẽ chỉ cho phép bạn truy cập các địa chỉ cục bộ của quá trình. Điều này được gọi là "bộ nhớ được bảo vệ". Mỗi quá trình chỉ có thể truy cập bộ nhớ của riêng nó. –

2

Addresses là quá trình địa phương (Là một dành VM cũng gây mã để được chia sẻ giữa các quá trình trong bộ nhớ vật lý, và tất cả các dữ liệu sẽ chỉ copied-on-write.). 804a01c trong một quy trình không giống như 804a01c trong quy trình khác.

2

virtual memory: cả hai không gian địa chỉ đều giống hệt với các quy trình tương ứng. Các bộ nhớ vật lý được lưu trữ trong là khác nhau. Tuy nhiên, trong thực tế, phức tạp bởi một tối ưu hóa bộ nhớ (được thực hiện bởi hầu hết các hạt nhân) ánh xạ các trang ảo khác nhau tương ứng đến cùng một trang vật lý cho đến khi một trong các quy trình đó ghi vào trang đó của bộ nhớ, tại thời điểm đó trang được nhân bản đến một địa chỉ vật lý khác (và trang ảo được ánh xạ lại cho tiến trình).

Có nhiều biến chứng khác: Được nhận biết nhiều nhất là giá trị trả về của fork() khác nhau giữa các quy trình, mặc dù đó thường là sự khác biệt về giá trị đăng ký chứ không phải bộ nhớ. Tuy nhiên, các tệp mở và một số tài nguyên khác có thể được đánh dấu là không thể kế thừa, vì vậy có thể có các khác biệt khác — nhỏ nhưng đôi khi hữu ích.

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