2013-08-27 32 views
5

Có cách nào để sử dụng cuộc gọi hệ thống wait() với thời gian chờ, ngoài việc sử dụng vòng chờ bận hoặc bận?Có phiên bản của cuộc gọi hệ thống wait() đặt thời gian chờ không?

Tôi đã có một quy trình gốc là fork s chính nó và exec s một đứa trẻ có thể thực thi. Sau đó nó chờ đợi cho trẻ kết thúc, lấy sản lượng của nó bằng bất cứ điều gì có nghĩa là thích hợp, và và thực hiện chế biến tiếp. Nếu quá trình không kết thúc trong một khoảng thời gian nhất định, nó giả định rằng việc thực thi của nó hết thời gian chờ và thực hiện điều gì đó khác. Thật không may, phát hiện thời gian chờ này là cần thiết cho bản chất của vấn đề.

+2

Hãy nhớ nếu chúng tôi hỏi tại sao bạn cần một thứ như vậy? (trong trường hợp có các lựa chọn thay thế) –

+0

Bản sao có thể có của [Waitpid equivalent with timeout?] (http://stackoverflow.com/questions/282176/waitpid-equivalent-with-timeout) –

Trả lời

4

Không có cuộc gọi chờ hết thời gian chờ.

Thay vào đó, bạn có thể cài đặt trình xử lý tín hiệu đặt cờ cho SIGCHLD và sử dụng select() để thực hiện hết thời gian chờ. select() sẽ bị ngắt bởi tín hiệu.

static volatile int punt; 
static void sig_handler(int sig) 
{ 
    punt = 1; 
} 

... 

struct timeval timeout = {10,0}; 
int rc; 

signal(SIGCHLD, sig_handler); 

fork/exec stuff 
//select will get interrupted by a signal 

rc = select(0, NULL,NULL,NULL, &tv); 
if (rc == 0) { 
// timed out 
} else if (punt) { 
    //child terminated 
} 

More luận lý là cần thiết nếu bạn có tín hiệu khác mà bạn cần để xử lý cũng mặc dù

+0

Nếu bạn đã cài đặt vòng lặp bỏ phiếu, bạn cũng có thể thiết lập một biển báo để bắt tín hiệu. –

3

Bạn có thể sử dụng waitpid cùng với tùy chọn WNOHANG và chế độ ngủ.

while(waitpid(pid, &status, WNOHANG) == 0) { 
    sleep(1); 
} 

Nhưng đây sẽ là một hoạt động ngủ. Tuy nhiên tôi thấy không có cách nào khác bằng cách sử dụng các loại chức năng wait.

+0

"ngoài việc sử dụng máy bận chờ hoặc bận "Tôi nghĩ đây là một phương án cuối cùng không phù hợp. – Alex

+0

@Alex Dường như tôi chưa đọc đủ câu hỏi một cách cẩn thận. Tuy nhiên, tôi không thấy cách nào bên cạnh – hek2mgl

3

Trên Linux, bạn cũng có thể giải quyết vấn đề này bằng signalfd. signalfd về cơ bản có một bộ các tín hiệu và tạo ra một fd mà bạn có thể đọc; mỗi khối bạn đọc tương ứng với tín hiệu đã kích hoạt. (Bạn nên chặn các tín hiệu này với sigprocmask để họ không thực sự được gửi.)

Ưu điểm của signalfd là bạn có thể sử dụng fd với select, poll, hoặc epoll, tất cả đều cho phép timeout, và tất cả các cho phép bạn chờ đợi những thứ khác nữa.

Một lưu ý: Nếu cùng một tín hiệu kích hoạt hai lần trước khi số struct signalfd_siginfo tương ứng được đọc, bạn sẽ chỉ nhận được một dấu hiệu duy nhất. Vì vậy, khi bạn nhận được chỉ báo SIGCHLD, bạn cần phải liên tục waitpid(-1, &status, &WNOHANG) cho đến khi nó trả về -1.

Trên FreeBSD, bạn có thể đạt được hiệu ứng tương tự thay vì trực tiếp sử dụng kqueuekevent loại EVFILT_PROC. (Bạn cũng có thể kqueue một sự kiện SIGCHLD, nhưng EVFILT_PROC cho phép bạn chỉ định các sự kiện bởi pid con thay vì toàn cầu cho tất cả trẻ em.) Điều này cũng nên làm việc trên Mac OS X, nhưng tôi chưa bao giờ thử nó.

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