Trong thuật ngữ POSIX, một môi trường lớp con được liên kết với khái niệm Môi trường thực thi Shell .
Một môi trường lớp con là một môi trường thực thi shell riêng biệt được tạo như là một bản sao của môi trường cha. Môi trường thực thi đó bao gồm những thứ như tệp đã mở, ô, thư mục làm việc, biến / hàm / bí danh shell ...
Thay đổi môi trường subshell đó không ảnh hưởng đến môi trường cha.
Theo truyền thống trong vỏ Bourne hoặc ksh88 dựa trên đặc tả POSIX, được thực hiện bằng cách hủy bỏ một quy trình con.
Các khu vực nơi POSIX yêu cầu hoặc cho phép lệnh chạy trong môi trường mạng con là những khu vực mà ksh88 theo truyền thống rẽ nhánh một quy trình vỏ con.
Tuy nhiên, nó không bắt buộc phải sử dụng một quy trình con cho việc đó.
Một shell có thể chọn thay thế để thực hiện môi trường thực thi riêng biệt đó theo bất kỳ cách nào họ muốn.
Ví dụ, ksh93 thực hiện điều đó bằng cách lưu các thuộc tính của môi trường thực thi cha mẹ và khôi phục chúng sau khi chấm dứt môi trường lớp con trong bối cảnh có thể tránh được việc giả mạo (vì tối ưu hóa việc rèn là khá tốn kém trên hầu hết các hệ thống).
Ví dụ: trong:
cd /foo; pwd
(cd /bar; pwd)
pwd
POSIX không yêu cầu cd /foo
phải chạy trong một môi trường riêng biệt và để xuất ra một cái gì đó như:
/foo
/bar
/foo
Nó không yêu cầu nó chạy trong một quy trình riêng biệt. Ví dụ, nếu thiết bị xuất chuẩn trở thành một đường ống bị hỏng, pwd
chạy trong môi trường lớp con rất có thể SIGPIPE được gửi đến quy trình một và duy nhất.
Hầu hết các shell bao gồm bash
sẽ triển khai nó bằng cách đánh giá mã bên (...)
trong một tiến trình con (trong khi tiến trình cha chờ kết thúc), nhưng thay vào đó, ksh93 sẽ chạy mã bên trong (...)
, tất cả trong cùng một quy trình:
- hãy nhớ rằng nó là trong một môi trường subshell.
- khi
cd
, lưu thư mục làm việc trước đó (thường trên một bộ mô tả tệp được mở bằng O_CLOEXEC), lưu giá trị của các biến OLDPWD, PWD và bất cứ điều gì cd
có thể sửa đổi và sau đó thực hiệnchdir("/bar")
- Khi trở về từ subshell, thư mục làm việc hiện tại được khôi phục (với một
fchdir()
fd đã lưu) và mọi thứ khác mà subshell có thể đã sửa đổi.
Có những bối cảnh mà một quá trình con không thể tránh được. ksh93 không rẽ nhánh:
var=$(subshell)
(subshell)
Nhưng có trong
{ subshell; } &
{ subshell; } | other command
Đó là, các trường hợp mà mọi thứ phải chạy trong các quy trình riêng biệt để chúng có thể chạy đồng thời.
tối ưu hóa ksh93 đi xa hơn thế. Chẳng hạn, trong khi ở
var=$(pwd)
hầu hết các shell sẽ rẽ nhánh một tiến trình, để đứa trẻ chạy pwd
lệnh với thiết bị xuất chuẩn của nó được chuyển hướng đến một đường ống, pwd
viết thư mục làm việc hiện tại vào đường ống đó và quá trình cha mẹ đọc kết quả ở đầu kia của đường ống, ksh93
ảo hóa tất cả những điều đó yêu cầu ngã ba cũng không phải đường ống. Một ngã ba và đường ống sẽ chỉ được sử dụng cho các lệnh không dựng sẵn.
Lưu ý rằng có các bối cảnh khác mà các lớp con cho các shell đó xử lý một tiến trình con. Ví dụ, để chạy một lệnh được lưu trữ trong một tệp thực thi riêng biệt (và đó không phải là một tập lệnh dành cho cùng một trình thông dịch shell), một shell sẽ phải rẽ nhánh một quy trình để chạy lệnh đó trong trường hợp khác. có thể chạy nhiều lệnh hơn sau khi lệnh đó trả về.
Trong:
/bin/echo "$((n += 1))"
Đó không phải là một lớp con, lệnh sẽ được đánh giá trong môi trường thực thi shell hiện tại, n
biến của môi trường thực thi shell hiện tại sẽ được tăng lên, nhưng shell sẽ rẽ nhánh một tiến trình con để thực thi /bin/echo
lệnh đó trong đó với việc mở rộng $((n += 1))
dưới dạng đối số .
Nhiều shell thực hiện tối ưu hóa ở chỗ chúng không rẽ nhánh một tiến trình con để chạy lệnh bên ngoài đó nếu đó là lệnh cuối cùng của tập lệnh hoặc lớp con (đối với các lớp con được triển khai như các tiến trình con). ( bash
tuy nhiên chỉ thực hiện nếu lệnh đó là lệnh duy nhất của lớp con).
Điều đó có nghĩa là, với các shell đó, nếu lệnh cuối cùng trong subshell là một lệnh bên ngoài, subshell không gây ra một quá trình bổ sung nào được sinh ra. Nếu bạn so sánh:
a=1; /bin/echo "$a"; a=2; /bin/echo "$a"
với
a=1; /bin/echo "$a"; (a=2; /bin/echo "$a")
sẽ có cùng số lượng quá trình được tạo, chỉ trong trường hợp thứ hai, ngã ba thứ hai được thực hiện trước đó để nó a=2
được chạy trong môi trường dưới vỏ.