2012-01-13 31 views
7

Mã gọi hệ thống ngã ba được viết như thế nào. Tôi muốn biết một số chi tiết về cách một hàm có thể trả về hai giá trị khác nhau và cho hai quy trình khác nhau. Trong ngắn hạn muốn biết làm thế nào gọi hệ thống ngã ba được thực hiện?Thực hiện Fork

+3

Bạn có thể thử và xem mã nguồn hạt nhân Linux ... – fge

+1

Bạn có cảm thấy thoải mái với ý tưởng rằng hệ điều hành có thể tạo quy trình và có thể chọn vùng bộ nhớ nào để ánh xạ tới không gian địa chỉ của từng quy trình không? –

+0

điểm nào cần đặt câu hỏi? – Svisstack

Trả lời

9

Bạn đã giải thích khá nhiều bằng cách nói rằng đó là cuộc gọi hệ thống. Đó là công việc của hệ điều hành để làm tất cả những công việc đó, và hệ điều hành có thể làm bất cứ điều gì nó muốn ngoài ngữ cảnh của chương trình của bạn hoặc các quy tắc của bất kỳ ngôn ngữ nào bạn đang thực hiện nó. Đây là một ví dụ đơn giản về cách nó có thể xảy ra:

  1. chương trình gọi fork() hệ thống gọi
  2. kernel hệ thống fork gọi bản sao quá trình chạy chương trình
  3. các kernel đặt giá trị lợi nhuận cho các cuộc gọi hệ thống cho chương trình bản gốc và cho trùng lặp (PID của bản sao và 0, tương ứng)
  4. Hạt nhân đặt cả hai quy trình vào hàng đợi của lịch biểu
  5. Khi mỗi tiến trình được lên lịch, hạt nhân 'trả về' cho từng chương trình.
-1

Trong cách dễ dàng cho quá trình dụ được nhân bản trong fork() chức năng với Moving IP/EIP/RIP đăng ký để bỏ qua một số hướng dẫn trong các chức năng có thể trông giống như:

return pid; 
return 0; 

quá trình đầu tiên sẽ thực hiện đầu tiên hướng dẫn và chức năng pop từ ngăn xếp, quá trình thứ hai sẽ bắt đầu nhưng từ lệnh thứ hai trở về 0.

+0

Tôi nghĩ rằng nó chỉ là hạt nhân trả về các giá trị khác nhau từ cuộc gọi hệ thống cho mỗi quá trình. – tangrs

+0

Cả hai ngã ba quá trình từ cùng một điểm khi bạn gọi fork(). Tôi không biết ý bạn là gì bởi quá trình "thứ hai" (cha mẹ hoặc con cái) nhưng nó không chính xác – iantonuk

2

Có một chú thích trong tập sách mã nguồn Unix V6 cho các trường đại học được chú thích bởi Ken Thomps và Dennis Ritchie tự mô tả cách thức lợi nhuận kép thực sự hiệu quả. Nhận xét kết thúc bằng câu sau:

Bạn không được dự kiến ​​sẽ hiểu điều này.

+0

IIRC mà được gọi là hội đồng được sử dụng cho điều đó, không phải là ý tưởng trả lại hai lần. – ninjalj

7

Câu trả lời của Carl thật tuyệt vời. Tôi muốn thêm rằng trong nhiều hệ điều hành, các giá trị trả lại được truyền vào một trong các thanh ghi. Trong kiến ​​trúc x86, thanh ghi này có thể là eax, Trong kiến ​​trúc ARM thanh ghi này có thể là R0, v.v.

Mỗi quá trình cũng có khối kiểm soát quy trình tại thời điểm gián đoạn, syscall hoặc ngoại lệ đã xảy ra và kiểm soát được chuyển cho hệ điều hành. Lần sau, quy trình được lên lịch, giá trị của thanh ghi được khôi phục từ PCB.

Bây giờ, khi fork() xảy ra, hệ điều hành có thể làm:

child_process->PCB[return_value_register] = 0; 
parrent_process->PCB[return_value_register] = child_pid; 

Vì vậy, khi các quá trình cơ cấu lại, mỗi người trong số họ nhìn thấy một giá trị trả về khác nhau.

Ví dụ: bạn có thể xem xv6's implementation of fork. Trong đó, tiến trình cha vẫn ở trạng thái đang chạy, vì vậy nó trả về giá trị trả về của cha bằng cách sử dụng câu lệnh trả về đơn giản. Nhưng nó đặt giá trị của EAX đăng ký cho quá trình con để 0, vì vậy khi tiến trình con được lên kế hoạch nó thấy 0 như giá trị trả về:

// Clear %eax so that fork returns 0 in the child. 
np->tf->eax = 0; 

Lưu ý rằng trở về 0 cũng sẽ lập một cái gì đó như "eax mov, 0".

Cập nhật: Tôi vừa triển khai fork() cho hệ điều hành sở thích mà tôi đang thực hiện. Bạn có thể xem mã nguồn here.