Sự khác biệt chính xác giữa một subshell trực tiếp và một quá trình con của trẻ là gì?


16

Theo cái nàycái này , một subshell được bắt đầu bằng cách sử dụng dấu ngoặc đơn (…).

( echo "Hello" )

Theo đó , cái nàycái này , một quá trình được rẽ nhánh khi lệnh được bắt đầu bằng một&

echo "Hello" &

Đặc tả Posix sử dụng từ subshelltrong trang này nhưng không định nghĩa nó và, trên cùng một trang, không định nghĩa "quy trình con" .

Cả hai đều đang sử dụng fork()chức năng kernel , đúng không?

Sự khác biệt chính xác sau đó để gọi một số dĩa là "vỏ phụ" và một số nhánh khác là "quy trình con".


Không rõ lý do tại sao bạn liên kết Cơ sở lý luận POSIX : Định nghĩa cơ sở thay vì chính Định nghĩa cơ sở : 3.93 Quy trình con "Một quy trình mới được tạo (bởi fork (), posix_spawn () hoặc ...) bởi một quy trình nhất định" ; 3.376 Subshell "Một môi trường thực thi shell, phân biệt với môi trường thực thi shell chính hoặc hiện tại" . Vì vậy, không phải trường hợp của cùng một loại điều. Đây có phải là sự khác biệt bạn đang tìm kiếm?
fra-san

@ fra-san A child processcó thể có một môi trường khác biệt hơn main: Thích trong ( LANG=C eval 'echo "$LANG"' ). Có phải quá trình con đó (bên trong dấu ngoặc đơn) cũng là một lớp con (môi trường khác nhau)?
NotAnUnixNazi

Biểu thức trong ( )theo định nghĩa một lớp con với môi trường thực thi riêng của nó. Quan điểm của tôi là một lớp con không bắt buộc phải được thực hiện như một quy trình con (như Stéphane chỉ ra trong câu trả lời của mình với ví dụ ksh93). Có vẻ như subshelltiến trình con không phải là cả hai kết quả của một fork()cuộc gọi; do đó, tìm kiếm sự khác biệt giữa hai loại ngã ba dường như không đúng với quan điểm của tôi. Đó là lý do tại sao tôi cố gắng hiểu rõ hơn câu hỏi của bạn.
fra-san

Ah, bây giờ tôi thấy rằng trang tldp mà bạn liên kết thực sự nói rằng một subshell một quá trình con. Theo tôi định nghĩa đó là một sự đơn giản hóa có thể gây hiểu nhầm.
fra-san

Câu trả lời:


15

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 /foophả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, pwdchạ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 bashsẽ 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ì cdcó 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 pwdlệnh với thiết bị xuất chuẩn của nó được chuyển hướng đến một đường ống, pwdviế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, nbiế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/echolệ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). ( bashtuy 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ỏ.


1

Subshell

Vỏ con còn được gọi là vỏ con. Subshell có thể được tạo từ shell cha và từ shell khác. Subshell có thể được tạo bằng cách sử dụng:

1. Danh sách quy trình

Một danh sách quy trình là nhóm lệnh được đặt trong ngoặc đơn. Thí dụ:

( pwd ; (echo $BASH_SUBSHELL)) 

Điều này sẽ in thư mục làm việc hiện tại và số lượng vỏ sinh sản. LƯU Ý Gọi subshell là đắt tiền.

2. Đồng xử lý

Nó sinh ra một subshell trong chế độ nền và thực thi một lệnh trong subshell đó.

coproc sleep 10

Nếu bạn gõ jobslệnh

[1]+  Running                 coproc COPROC sleep 10 &

bạn sẽ thấy giấc ngủ là quá trình chạy nền.

Ngã ba một quá trình trẻ em

Một quy trình con trong điện toán là một quy trình được tạo bởi một quy trình khác. Bất cứ khi nào một lệnh bên ngoài được thực thi, một tiến trình con được tạo. Hành động này được gọi là forking.

$ps -f
UID        PID  PPID  C STIME TTY          TIME CMD  
umcr7     3647  3638  0 13:54 pts/0    00:00:00 bash
umcr7     3749  3647  0 13:59 pts/0    00:00:00 ps -f

Như ps -flà lệnh bên ngoài (tức là Lệnh bên ngoài, đôi khi được gọi là lệnh hệ thống tập tin, là một chương trình tồn tại bên ngoài bash shell.) Điều này sẽ tạo ra tiến trình con với id cha của bash shell mà nó được thực thi.


0

Cả hai (vỏ con và vỏ con) là một quá trình riêng biệt so với vỏ cha (cả hai đều là con của vỏ cha). Đó là, họ có các PID khác nhau. Và cả hai đều bắt đầu với một ngã ba (bản sao) của vỏ cha.

Subshell là một bản sao của shell cha trong đó các biến, hàm, cờ và mọi thứ đều có sẵn như trong vỏ cha. Sửa đổi các giá trị như vậy không ảnh hưởng đến cha mẹ.

Một shell con bắt đầu như một ngã ba nhưng nó được đặt lại về các giá trị mặc định của shell được cung cấp bởi các cấu hình bắt đầu. Nó trở thành một quá trình được sử dụng để thực thi một số mã (có thể là shell hoặc lệnh).

Một subshell có thể truy cập các giá trị biến:

$ x=123; ( echo "$x")
123

Một shell con không thể (biến không xuất):

$ x=234; sh -c 'echo "x=$x"'
x=
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.