Khi bạn gọi vfork()
, một quy trình mới được tạo và quy trình mới đó mượn hình ảnh quy trình của quy trình cha ngoại trừ ngăn xếp. Quá trình con được cung cấp một ngôi sao ngăn xếp mới của riêng mình, tuy nhiên không cho phép return
từ hàm được gọi vfork()
.
Trong khi đứa trẻ đang chạy, quá trình cha mẹ bị chặn, vì đứa trẻ đã mượn không gian địa chỉ của cha mẹ.
Bất kể bạn làm gì, mọi thứ chỉ cần truy cập vào ngăn xếp đều chỉ sửa đổi ngăn xếp riêng tư của trẻ. Tuy nhiên, nếu bạn sửa đổi dữ liệu toàn cầu, điều này sẽ sửa đổi dữ liệu chung và do đó cũng ảnh hưởng đến cha mẹ.
Những thứ sửa đổi dữ liệu toàn cầu là ví dụ:
Khi bạn gọi _exit()
(quan trọng, không bao giờ gọi exit()
), đứa trẻ bị chấm dứt và quyền kiểm soát được trao lại cho cha mẹ.
Nếu bạn gọi bất kỳ chức năng nào từ exec*()
gia đình, một không gian địa chỉ mới sẽ được tạo bằng mã chương trình mới, dữ liệu mới và một phần của ngăn xếp từ cha mẹ (xem bên dưới). Một khi điều này đã sẵn sàng, đứa trẻ không còn mượn không gian địa chỉ từ đứa trẻ, mà sử dụng một không gian địa chỉ riêng.
Kiểm soát được trao lại cho cha mẹ, vì không gian địa chỉ của nó không còn được sử dụng bởi quy trình khác.
Quan trọng: Trên Linux, không có vfork()
triển khai thực sự . Linux thực hiện vfork()
dựa trên fork()
khái niệm Copy on Write do SunOS-4.0 giới thiệu vào năm 1988. Để khiến người dùng tin rằng họ sử dụng vfork()
, Linux chỉ thiết lập dữ liệu chia sẻ và đình chỉ phụ huynh trong khi đứa trẻ không gọi _exit()
hoặc một trong các exec*()
chức năng.
Do đó, Linux không được hưởng lợi từ thực tế là vfork()
không thực sự cần thiết lập một mô tả không gian địa chỉ cho đứa trẻ trong kernel. Điều này dẫn đến kết quả vfork()
là không nhanh hơn fork()
. Trên các hệ thống triển khai thực tế vfork()
, nó thường nhanh hơn gấp 3 lần fork()
và ảnh hưởng đến hiệu suất của các shell sử dụng vfork()
- ksh93
, gần đây Bourne Shell
và csh
.
Lý do tại sao bạn không bao giờ nên gọi exit()
từ vfork()
đứa trẻ ed là để exit()
xóa stdio trong trường hợp có dữ liệu không được lưu lại từ thời điểm trước khi gọi vfork()
. Điều này có thể gây ra kết quả kỳ lạ.
BTW: posix_spawn()
được triển khai trên đầu trang vfork()
, do đó vfork()
sẽ không bị xóa khỏi HĐH. Nó đã được đề cập rằng Linux không sử dụng vfork()
cho posix_spawn()
.
Đối với ngăn xếp, có rất ít tài liệu, đây là những gì trang người Solaris nói:
The vfork() and vforkx() functions can normally be used the
same way as fork() and forkx(), respectively. The calling
procedure, however, should not return while running in the
child's context, since the eventual return from vfork() or
vforkx() in the parent would be to a stack frame that no
longer exists.
Vì vậy, việc thực hiện có thể làm bất cứ điều gì nó thích. Việc triển khai Solaris sử dụng bộ nhớ dùng chung cho khung ngăn xếp của chức năng gọi vfork()
. Không có triển khai nào cấp quyền truy cập vào các phần cũ của ngăn xếp từ cha mẹ.