2012-02-16 14 views
6

Trong bash khi tôi chạy một lệnh như wc & hoặc cat & mà muốn tiêu chuẩn trong ngay lập tức, nó sẽ trả về ngay lập tức vớiLàm cách nào để biết liệu một đứa trẻ có yêu cầu stdin không? Làm thế nào để tôi nói nó dừng lại?

[1] + Stopped mèo

như thế nào thực hiện điều này? Làm thế nào để dừng một chương trình mà tôi đã bắt đầu với exec, và làm thế nào để tôi biết để ngăn chặn các chương trình này ở nơi đầu tiên? Có cách nào để nói rằng các chương trình này muốn stdin?

Cảm ơn!

PS cũng vậy, + là gì? Tôi luôn tự hỏi, nhưng điều đó thực sự khó khăn đối với google ...

+2

+1 cho biểu tượng "khó tìm kiếm" – Tim

+2

Bạn có thể tìm thấy câu trả lời cho câu hỏi này: [Làm cách nào để biết liệu chương trình thực thi của C có chạy ở nền trước hay nền không?] (Http://stackoverflow.com/ câu hỏi/2425005/how-do-i-know-if-an-c-programs-executable-là-chạy-trong-foreground-hoặc-nền) –

Trả lời

1

Các setpgid() thủ công trang giải thích cách làm việc này:

Một phiên có thể có một thiết bị đầu cuối kiểm soát. Bất cứ lúc nào, một (và chỉ một) của các nhóm quá trình trong phiên có thể là tiền tố nhóm quá trình cho thiết bị đầu cuối; các nhóm quá trình còn lại nằm ở nền. Nếu tín hiệu được tạo từ thiết bị đầu cuối (ví dụ: nhập khóa ngắt để tạo SIGINT), tín hiệu đó được gửi đến nhóm quá trình nền trước. (Xem termios(3) để biết mô tả của các ký tự tạo tín hiệu.) Chỉ có quy trình tiền cảnh nhóm có thể read(2) từ thiết bị đầu cuối; nếu nhóm quá trình nền cố gắng đến read(2) từ thiết bị đầu cuối, khi đó nhóm sẽ được gửi một tín hiệu SIGTSTP, sẽ tạm ngưng. Các chức năng tcgetpgrp(3)tcsetpgrp(3) được sử dụng để có được/thiết lập quy trình tiền cảnh nhóm của thiết bị đầu cuối điều khiển.

Vì vậy, những gì bạn muốn làm là thế này:

  1. Khi bạn tạo một đường ống mới, gọi setpgid() để đặt tất cả các thành viên của đường ống trong một nhóm quy trình mới (với PID của quá trình đầu tiên trong đường ống như PGID).

  2. Sử dụng tcsetpgrp() để quản lý nhóm quá trình nào đang ở nền trước - nếu bạn đặt đường ống ở chế độ nền với &, bạn nên đặt nhóm xử lý riêng của nhóm lại thành nhóm tiến trình.

  3. Gọi waitpid() với WNOHANGWUNTRACED cờ để kiểm tra trạng thái của tiến trình con - điều này sẽ thông báo cho bạn khi họ bị ngăn chặn bởi SIGTSTP, mà sẽ cho phép bạn in một thông báo như bash không.

+0

Bạn, thưa ông hay bà, đã làm nó. Đó là một trang hướng dẫn sử dụng dài, cảm ơn bạn đã tham khảo. Tôi không thể không chú ý bạn có 73 trang câu trả lời, nhưng chỉ có ba câu hỏi: đó là một cái gì đó! Bạn tôn trọng và truyền cảm hứng cho tôi. – Ziggy

2

Nếu bạn muốn các chương trình sinh sản hoạt động tương tự như cách trình bao hoạt động, hãy gọi setpgrp() sau khi giả mạo con bạn. Điều này sẽ làm cho chương trình nền chạy trong nhóm quá trình riêng của nó, và do đó có một tty tách rời. Khi nó cố gắng làm I/O đến bàn điều khiển, nó sẽ nhận được tín hiệu SIGTTIN hoặc SIGTTOU. Hành vi mặc định của SIGTTIN hoặc SIGTTOU là dừng quá trình giống như SIGSTOP.

Là phụ huynh, bạn có thể tìm hiểu xem bạn đã dừng quy trình con bằng cách sử dụng waitpid()WUNTRACED.

+0

'setpgrp()' được đánh dấu là lỗi thời trong POSIX; nó có lịch sử có chữ ký khác nhau trong các hệ thống SYSV và BSD. 'setpgid()' là giao diện ưu tiên. – caf

2

[Sửa - xem câu trả lời khác cho câu trả lời cho câu hỏi chính]

Dấu hiệu + chỉ đơn giản đề cập đến hiện tại việc. Mỗi đường ống lệnh (chẳng hạn như foo | bar | baz) là một công việc, có thể được tham chiếu đến bằng cách sử dụng jobspec bắt đầu bằng ký tự %. %1 là số công việc 1, %+ là công việc hiện tại và %- là công việc trước đó.

Để biết thêm thông tin về công việc, hãy xem Job Control section của hướng dẫn sử dụng Bash.

+0

Đoạn đầu tiên là sai. Nó nên đọc "từ các thiết bị đầu cuối kiểm soát của nhóm quá trình" (hoặc một cái gì đó gần đó - Tôi quên các chi tiết chính xác), không phải "từ stdin (tập tin mô tả 0)". Một cách hoàn toàn tốt để tránh điều này là làm cho bộ mô tả tập tin 0 tham chiếu đến một thiết bị không phải là thiết bị đầu cuối, ví dụ: bằng cách đặt '

+1

Và đó là hành động mặc định cho 'SIGTTIN', không phải là trình bao, tạm dừng quá trình này. Nó có thể được ghi đè bằng bộ xử lý tín hiệu. –

+0

Tôi nghĩ rằng điều này không trả lời câu hỏi của tôi, mà là về c chứ không phải là bash. Làm thế nào là quá trình bị đình chỉ, và làm thế nào để tôi biết nó được đọc từ stdin. Hãy nhớ, tôi bash. (bạn đi phần PS mặc dù! Cảm ơn!) – Ziggy

0

Bạn có thể sử dụng system("command &") trong quá trình con chia đôi và sau đó thoát khỏi thủ công, nếu không có thời gian và hạn chế ưu tiên.