Theo thứ tự nào các lệnh đường ống chạy?


89

Tôi chưa bao giờ thực sự nghĩ về cách shell thực sự thực hiện các lệnh đường ống. Tôi đã luôn được thông báo rằng "thiết bị xuất chuẩn của một chương trình được đưa vào hệ thống của một chương trình khác", như một cách nghĩ về các đường ống. Vì vậy, tự nhiên, tôi nghĩ rằng trong trường hợp nói, A | B, A sẽ chạy trước, sau đó B lấy thiết bị xuất chuẩn của A và sử dụng thiết bị xuất chuẩn của A làm đầu vào.

Nhưng tôi đã nhận thấy rằng khi mọi người tìm kiếm một quy trình cụ thể trong ps, họ sẽ bao gồm grep -v "grep" ở cuối lệnh để đảm bảo rằng grep không xuất hiện trong đầu ra cuối cùng. Điều này có nghĩa là trong lệnh ps aux | grep "bash" | grep -v "grep", có nghĩa là ps biết rằng grep đang chạy và do đó nằm trong đầu ra của ps. Nhưng nếu ps kết thúc chạy trước khi đầu ra của nó được chuyển sang grep, làm sao nó biết rằng grep đang chạy?

flamingtoast@FTOAST-UBUNTU: ~$ ps | grep ".*"
PID TTY          TIME CMD
3773 pts/0    00:00:00 bash
3784 pts/0    00:00:00 ps
3785 pts/0    00:00:00 grep

Tại sao không chấp nhận một câu trả lời?
törzsmókus

Câu trả lời:


64

Các lệnh đường ống chạy đồng thời. Khi bạn chạy ps | grep …, đó là may mắn của vẽ (hoặc một vài chi tiết về các hoạt động của vỏ kết hợp với lịch trình tinh chỉnh sâu trong lòng của hạt nhân) về việc liệu pshoặc grepbắt đầu đầu tiên, và trong mọi trường hợp họ tiếp tục thực hiện đồng thời.

Điều này rất thường được sử dụng để cho phép chương trình thứ hai xử lý dữ liệu khi nó xuất hiện từ chương trình đầu tiên, trước khi chương trình đầu tiên hoàn thành hoạt động. Ví dụ

grep pattern very-large-file | tr a-z A-Z

bắt đầu hiển thị các dòng khớp bằng chữ hoa ngay cả trước khi grephoàn thành duyệt qua tệp lớn.

grep pattern very-large-file | head -n 1

hiển thị dòng khớp đầu tiên và có thể dừng xử lý tốt trước khi grepđọc xong tệp đầu vào của nó.

Nếu bạn đọc ở đâu đó các chương trình đường ống chạy theo trình tự, hãy chạy khỏi tài liệu này. Các chương trình đường ống chạy đồng thời và luôn luôn có.


7
Và điều thú vị về ví dụ này là khi đầu có được một dòng mà nó cần, nó sẽ chấm dứt và khi grep nhận thấy điều này, nó cũng chấm dứt mà không phải thực hiện một loạt công việc nào nữa.
Joe

Tôi đoán có một số loại bộ đệm IO liên quan đến đường ống ... làm thế nào để tôi biết kích thước của nó bằng byte? Tôi muốn đọc gì để tìm hiểu thêm về nó? :)
n611x007

3
@naxa Có hai bộ đệm, thực sự. Có bộ đệm stdio bên trong grepchương trình và có bộ đệm được quản lý bởi kernel trong chính đường ống. Đối với cái sau, xem bộ đệm ống lớn như thế nào?
Gilles

49

Thứ tự các lệnh được chạy thực sự không quan trọng và không được đảm bảo. Gác lại những chi tiết phức tạp của pipe(), fork(), dup()execve(), vỏ đầu tiên tạo ra các đường ống, các ống dẫn cho các dữ liệu mà sẽ chảy giữa các quá trình, và sau đó tạo ra các quá trình với sự kết thúc của đường ống kết nối với họ. Quá trình đầu tiên được chạy có thể chặn chờ đầu vào từ quy trình thứ hai hoặc chặn chờ quá trình thứ hai bắt đầu đọc dữ liệu từ đường ống. Những chờ đợi này có thể dài tùy ý và không thành vấn đề. Bất cứ thứ tự nào các quy trình được chạy, dữ liệu cuối cùng sẽ được chuyển và mọi thứ đều hoạt động.


5
Câu trả lời hay, nhưng OP dường như nghĩ rằng các quy trình chạy tuần tự. Ở đây bạn có thể nói rõ hơn rằng các quy trình được chạy đồng thời và đường ống giống như .... một đường ống giữa các xô, nơi nước chảy qua tất cả cùng một lúc (xấp xỉ).
Keith

Cảm ơn bạn đã làm rõ. Các nguồn mà tôi đã đọc làm cho có vẻ như các chương trình được chạy liên tục, thay vì đồng thời.
action_potato

Để xem trải nghiệm các quy trình bắt đầu theo cách không xác định, hãy thử chạy 1000 lần này: echo -na> & 2 | tiếng vang b> & 2
Ole Tange

28

Có nguy cơ đánh chết một con ngựa chết, quan niệm sai lầm dường như là

    Một | B

tương đương với

    Một > temporary_file 
    B < temporary_file 
    rm temporary_file

Nhưng, trở lại khi Unix được tạo ra và trẻ em cưỡi khủng long đến trường, các đĩa rất nhỏ và thông thường là một lệnh khá lành tính để tiêu thụ tất cả không gian trống trong hệ thống tệp. Nếu Blà một cái gì đó giống như , sản lượng cuối cùng của đường ống có thể là nhiều nhỏ hơn file trung gian. Do đó, đường ống đã được phát triển, không phải là một cách viết tắt cho việc chạy A trước, sau đó chạy B với đầu vào từ mô hình đầu ra của A , nhưng như một cách để thực hiện đồng thời và loại bỏ nhu cầu lưu trữ tệp trung gian trên đĩa.grep some_very_obscure_stringBA


2
Điều này trả lời tại sao và do đó nhận được phiếu bầu của tôi.
Rừng cổ LIttle Kami

1

Thông thường bạn chạy này dưới bash. quá trình làm việc và bắt đầu đồng thời, nhưng chạy song song với vỏ. Làm thế nào là nó có thể?

  1. nếu đó không phải là lệnh cuối cùng trong đường ống, hãy tạo đường ống không tên bằng cặp ổ cắm
  2. cái nĩa
  3. ở trẻ em hãy gán lại stdin / stdout cho socket nếu cần thiết (đối với quy trình đầu tiên trong ống stdin không được chỉ định lại, tương tự cho quy trình cuối cùng và thiết bị xuất chuẩn của anh ta)
  4. trong lệnh EXEC con được chỉ định với các đối số quét mã shell gốc, nhưng để lại tất cả các socket được mở. ID tiến trình con sẽ không được thay đổi vì đây là cùng tiến trình con
  5. đồng thời với con nhưng song song dưới vỏ chính chuyển sang bước 1.

hệ thống không đảm bảo sẽ thực thi nhanh như thế nào và lệnh được chỉ định bắt đầu. Nó độc lập với vỏ, nhưng hệ thống. Điều này là do:

ps auxww| grep ps | cat

một lần hiển thị grepvà / hoặc pslệnh, và tiếp theo bây giờ. Nó phụ thuộc vào mức độ nhanh chóng của kernel thực sự bắt đầu các quá trình sử dụng chức năng thực thi hệ thống.


1
Thực thi đồng thời có nghĩa là hai hoặc nhiều quá trình thực thi trong cùng một khung thời gian, thường có một số loại phụ thuộc giữa chúng. Thực thi song song có nghĩa là hai hoặc nhiều quá trình thực thi đồng thời (ví dụ trên các lõi CPU riêng biệt cùng một lúc). Tính song song không liên quan đến câu hỏi, cũng không phải là "tốc độ" exec()được thực hiện như thế nào, mà là cách các exec()cuộc gọi và thực hiện các chương trình trong một đường ống được xen kẽ .
Thomas Nyman
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.