Tại sao một đứa trẻ của vfork hoặc fork gọi _exit () thay vì exit ()?


12

Từ trang người đàn ông của vfork():

vfork () khác với fork () ở chỗ cha mẹ bị đình chỉ cho đến khi đứa trẻ thực hiện cuộc gọi để thực hiện (2) hoặc _exit (2). Đứa trẻ chia sẻ tất cả bộ nhớ với cha mẹ của nó, bao gồm cả ngăn xếp, cho đến khi exec () được phát hành bởi đứa trẻ. Đứa trẻ không được trả về từ hàm hiện tại hoặc gọi exit (), nhưng có thể gọi _exit ().

Tại sao trẻ nên sử dụng một _exit()thay vì chỉ đơn giản là gọi exit()? Tôi hy vọng điều này được áp dụng cho cả vfork()fork().


2
nếu bạn quan tâm đến một cuộc thảo luận
xenoterracide

Câu trả lời:


11

Như đã thấy trước đó , vforkkhông cho phép tiến trình con truy cập vào bộ nhớ của cha mẹ. exitlà một chức năng thư viện C (đó là lý do tại sao nó thường được viếtexit(3)). Nó thực hiện các tác vụ dọn dẹp khác nhau như xả và đóng luồng C (các tệp mở thông qua các hàm được khai báo stdio.h) và thực thi các hàm do người dùng chỉ định đã đăng ký atexit. Tất cả các tác vụ này liên quan đến việc đọc và ghi vào bộ nhớ quá trình.

_exitthoát ra mà không dọn dẹp. Đó trực tiếp là một cuộc gọi hệ thống (đó là lý do tại sao nó được viết là _exit(2)), thường được thực hiện bằng cách đặt số cuộc gọi hệ thống vào một thanh ghi bộ xử lý và thực hiện một lệnh xử lý cụ thể (phân nhánh đến trình xử lý cuộc gọi hệ thống). Điều này không cần phải truy cập vào bộ nhớ quá trình, vì vậy nó an toàn để thực hiện sau vfork.

Sau forkđó, không có hạn chế nào như vậy: quá trình cha mẹ và con cái hoàn toàn tự chủ.


vfork không cho phép quá trình con truy cập vào bộ nhớ của cha mẹ ? Nhưng tôi nghĩ rằng họ chia sẻ cùng một không gian địa chỉ, vì vậy đứa trẻ có thể truy cập không gian địa chỉ của cha mẹ. Có phải sự hiểu biết đó là sai?
Sen

Sau ngã ba, không có hạn chế nào như vậy: quy trình cha mẹ và con bây giờ hoàn toàn tự chủ. Điều đó có nghĩa là tôi có thể gọi một lối ra () từ một đứa trẻ của ngã ba?
Sen

1
@Sen: Trẻ không được phép truy cập vào bộ nhớ của cha mẹ. Nếu bạn thử nó, nó có thể hoạt động, bởi vì kernel sẽ không bảo vệ bạn. Nhưng hiệu quả có thể không như bạn dự định; ví dụ, nếu trình biên dịch của bạn quyết định để lại một số giá trị trong một thanh ghi, thì quá trình cha sẽ không nhìn thấy nó.
Gilles 'SO- ngừng trở nên xấu xa'

@Sen: Sau một ngã ba, bạn có thể thực hiện cuộc gọi thoát hoặc bất kỳ chức năng nào khác. Mọi tiến trình bắt đầu sau một ngã ba (trên Linux, ngay cả quá trình ban đầu initcũng được nhân bởi kernel).
Gilles 'SO- đừng trở nên xấu xa'

3

exitthực hiện dọn dẹp bổ sung như các chức năng gọi được đăng ký bởi atexitvì nó truy cập dữ liệu bên ngoài phần được sao chép. _exitthực hiện các tòa nhà trực tiếp mà không cần dọn dẹp, ngoại trừ trong kernel.


... Và cần lưu ý rằng fork () sao chép mọi thứ, vì vậy bạn có thể gọi exit () và bạn chắc chắn có thể quay lại từ hàm hiện tại.
derobert

3

Bạn có con gọi _exit () để tránh xóa bộ đệm stdio (hoặc khác) khi tiến trình con thoát ra. Vì quy trình con tạo thành một bản sao chính xác của quy trình cha mẹ, quy trình con vẫn có bất cứ điều gì cha mẹ có trong "stdout" hoặc "stderr", bộ đệm từ <stdio.h>. Bạn có thể (và sẽ, vào thời điểm không thuận lợi) nhận được kết quả đầu ra gấp đôi bằng cách gọi exit (), một từ trình xử lý atexit của tiến trình con và một từ cha mẹ, khi bộ đệm trong tiến trình cha mẹ đầy, và bị xóa.

Tôi nhận ra câu trả lời ở trên tập trung vào các chi tiết cụ thể của stdio.h, nhưng ý tưởng đó có thể mang đến các I / O được đệm khác, giống như một trong những câu trả lời ở trên chỉ ra.


1

exit(): - thực hiện một số tác vụ dọn dẹp, như đóng luồng i / o và nhiều luồng, sau đó quay lại kernel. _exit(): - trực tiếp đến kernel (không thực hiện bất kỳ tác vụ dọn dẹp nào).

fork() : cả cha và con đều có bảng tệp khác nhau, do đó, thay đổi được thực hiện bởi con không ảnh hưởng đến các tham số môi trường của cha mẹ và ngược lại.

vfork(): cả cha mẹ và con cái đều sử dụng cùng một bảng tệp, vì vậy thay đổi được thực hiện bởi con ảnh hưởng đến các tham số môi trường của cha mẹ. ví dụ: một số biến var=10, bây giờ được chạy var++bởi con và sau đó chạy cha, bạn cũng có thể thấy tác động của var++đầu ra của cha mẹ.

Như tôi đã nói nếu bạn sử dụng exit()trong vfork()đó tất cả các I / O đã được đóng lại. Vì vậy, ngay cả khi cha mẹ chạy chính xác, bạn không thể có được đầu ra thích hợp, bởi vì tất cả các biến được tuôn ra và tất cả các luồng được đóng lại.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.