2012-01-23 22 views
7

Tôi đã hiểu rằng: 1) waitpid được sử dụng để chờ đợi cái chết của đứa trẻ và sau đó thu thập SIGCHLD và trạng thái thoát của đứa trẻ, vv .. 2) Khi chúng tôi có bộ xử lý tín hiệu cho SIGCHLD, chúng tôi thực hiện thêm một số thứ liên quan đến dọn dẹp của trẻ em hoặc các công cụ khác (tối đa lập trình viên) và sau đó làm một waitpid để đứa trẻ sẽ không đi zombie và sau đó trở về.Sử dụng waitpid hoặc sigaction?

Bây giờ, chúng ta có cần phải có cả 1 và 2 trong các chương trình của mình khi chúng tôi thực hiện một ngã ba/exec và đứa trẻ quay trở lại? Nếu chúng ta có cả hai, các SIGCHLD thu được đầu tiên, vì vậy xử lý tín hiệu được gọi là đầu tiên và do đó waitpid của nó được gọi là thành công và không phải là waitpid trong mã trình cha mẹ như sau:

my_signal_handler_for_sigchld 
{ 
do something 
tmp = waitpid(-1,NULL,0); 
print tmp (which is the correct value of the child pid) 
} 

int main() 
{ 
    sigaction(SIGCHLD, my_signal_handler_for_sigchld) 
    fork() 
    if (child) //do something, return 
    if parent // waitpid(child_pid, NULL,0); print value returned from this waitpid - it is -1 
} 

Đánh giá cao nếu ai đó giúp tôi hiểu điều này.

Trả lời

1

Bạn cần phải gọi các syscalls chờ đợi như waitpid hoặc bạn bè -eg wait4 vv- giả sử bạn có thể có zombie processes.

Bạn có thể xử lý SIGCHLD để được thông báo rằng một số trẻ đã kết thúc (hoặc đã dừng, v.v ...) nhưng bạn sẽ cần phải đợi sau.

Trình xử lý tín hiệu bị hạn chế để gọi một bộ nhỏ các chức năng an toàn-tín hiệu-an toàn (xem signal(7) để biết thêm). Lời khuyên tốt là chỉ cần đặt một cờ volatile sig_atomic_t bên trong và thử nghiệm ở các vị trí sau và an toàn hơn.

18

Bạn thực sự không cần xử lý SIGCHLD nếu ý định của bạn là chạy quy trình con, thực hiện một số nội dung, sau đó đợi để hoàn thành. Trong trường hợp đó, bạn chỉ cần gọi waitpid khi bạn đã sẵn sàng để đồng bộ hóa. Điều duy nhất SIGCHLD hữu ích cho việc thông báo không đồng bộ về việc chấm dứt con, ví dụ nếu bạn có một ứng dụng tương tác (hoặc chạy dài) tương tác đang sinh ra nhiều trẻ em khác nhau và cần biết khi nào chúng kết thúc. Tuy nhiên, SIGCHLD thực sự xấu/xấu cho mục đích này, vì nếu bạn đang sử dụng mã thư viện để tạo quy trình con, bạn có thể nắm bắt các sự kiện cho trẻ em của thư viện chấm dứt và can thiệp vào việc xử lý chúng. Trình xử lý tín hiệu vốn đã quá trình toàn cầu và xử lý trạng thái toàn cầu, thường là A Bad Thing (tm).

Dưới đây là hai cách tiếp cận tốt hơn cho khi bạn có quá trình đứa trẻ đó sẽ được chấm dứt không đồng bộ:

Tiếp cận 1 (select/poll event-based): Hãy chắc chắn rằng bạn có một đường ống đến/từ mỗi tiến trình con bạn tạo . Nó có thể là stdin/stdout/stderr của họ hoặc chỉ là một fd giả bổ sung. Khi quá trình con chấm dứt, phần cuối của đường ống sẽ bị đóng và vòng lặp sự kiện chính của bạn sẽ phát hiện hoạt động trên bộ mô tả tệp đó. Từ thực tế là nó đóng cửa, bạn nhận ra rằng quá trình con đã chết, và gọi waitpid để gặt hái zombie.

Phương pháp tiếp cận 2 (dựa trên chủ đề): Đối với mỗi quy trình con bạn tạo, cũng tạo một chuỗi sẽ gọi ngay waitpid trên pid của tiến trình con. Khi waitpid trả về thành công, hãy sử dụng nguyên tắc đồng bộ hóa chuỗi yêu thích của bạn để phần còn lại của chương trình biết rằng trẻ đã chấm dứt hoặc đơn giản là quản lý mọi thứ bạn cần làm trong chuỗi bồi hoàn này trước khi nó kết thúc.

Cả hai cách tiếp cận này là mô-đun và thân thiện với thư viện (chúng tránh can thiệp vào bất kỳ phần nào khác của mã hoặc mã thư viện có thể sử dụng quy trình con).

+0

Xin chào, Cảm ơn câu trả lời của bạn.Nhưng những gì tôi đã thực sự tìm kiếm là: Khi tôi có cả sig_handler và waitpid trong tiến trình cha, sig_handler được gọi là becaues của sigchld và sau đó waitpid thứ 2 như được hiển thị ở trên trong câu trả về của tôi -1. Vì vậy, tôi có thể chỉ cần loại bỏ waitpid thứ 2 mà tôi đang có? – Vin

+0

Có, bạn chỉ có thể chờ đợi thành công một quá trình cho trẻ em một lần. Nó thực sự là một lỗi để chờ đợi một lần nữa kể từ khi pid là "giải phóng" bởi sự chờ đợi đầu tiên và có thể đã được tái sử dụng cho một quá trình con mới (nếu bạn xảy ra để tạo ra một số khác). –

+0

@R .. Chúng tôi có thể làm rõ 'Khi quá trình con chấm dứt, kết thúc của đường ống sẽ được đóng lại một chút? Để thực sự chính xác, nó sẽ không được 'Khi quá trình con đóng FD của nó mà là một kết nối với đầu ống, và không có quá trình khác có FDs kết nối với đầu ống, sau đó đầu kia của đường ống sẽ được báo hiệu là đóng (nhận EOF) '? Tôi tin rằng điều đó sẽ giải thích chính xác hơn những gì xảy ra, và cũng là trường hợp đặc biệt quan trọng của những gì sẽ xảy ra nếu có hơn 2 quy trình có FDs cho một đường ống mở. – nh2

Các vấn đề liên quan