2012-02-09 36 views
7

Tôi có một đoạn mã đơn giản để ghi định kỳ dữ liệu vào một fd được truyền cho nó. Các fd rất có thể sẽ là một đường ống hoặc ổ cắm nhưng có khả năng có thể là bất cứ điều gì. Tôi có thể phát hiện khi socket/pipe bị đóng/bị hỏng bất cứ khi nào tôi viết() cho nó, vì tôi gặp lỗi EPIPE (tôi bỏ qua SIGPIPE). Nhưng tôi không viết cho nó mọi lúc, và vì vậy có thể không phát hiện được một ổ cắm kín trong một thời gian dài. Tôi cần phải phản ứng với việc đóng cửa càng sớm càng tốt. Có một phương pháp kiểm tra fd mà không cần phải viết một()? Sau đó tôi có thể làm điều này định kỳ nếu tôi không viết bất cứ điều gì.Linux: Kiểm tra xem ổ cắm/ống có bị hỏng mà không đọc()/write()

+2

chọn, thăm dò, và epoll tất cả sẽ cho bạn biết –

+0

Cảm ơn cho câu trả lời, nhưng tôi không chắc chắn làm thế nào để làm cho công việc này với ống. Tôi đã thử một cuộc gọi select() với fd của tôi trong ghi và ngoại trừ fdsets, và kết quả của cuộc gọi không thay đổi khi đường ống bị hỏng (luôn luôn trả lại fd của tôi trong bộ ghi). Tôi cũng đã thử poll() với tất cả các sự kiện được thiết lập và một lần nữa không có sự khác biệt. – gimmeamilk

+0

Không đẩy fd của bạn vào fdsets viết. Chỉ có một ngoại trừ. –

Trả lời

8
struct pollfd pfd = {.fd = yourfd, .events = POLLERR}; 
if (poll(&pfd, 1, whatever) < 0) abort(); 
if (pfd.revents & POLLERR) printf("pipe is broken\n"); 

này làm việc cho tôi. Lưu ý rằng ổ cắm không chính xác ống và do đó cho thấy hành vi khác nhau (-> sử dụng POLLRDHUP).

+0

Aha! Tôi đã có lỗi đánh máy và đang kiểm tra các sự kiện trên đường ra ngoài thay vì bị lộ. Rất cám ơn, điều này đã làm việc rất tốt. – gimmeamilk

+1

Câu trả lời hay. Tôi quá quen với việc chọn() gọi. Tôi chắc chắn phải cố gắng phát triển vào thời điểm đó. +1 –

2

Hãy thử với lựa chọn và errorfds của tham số:

int **select**(int nfds, fd_set *restrict readfds, 
     fd_set *restrict writefds, **fd_set *restrict errorfds**, 
     struct timeval *restrict timeout); 
+1

Cảm ơn, nhưng tôi đã thử thêm fd của tôi vào bộ ngoại lệ và không thể làm cho nó hoạt động khác khi ống bị hỏng. (Nó có thể làm việc tốt với ổ cắm; Tôi đã không cố gắng được nêu ra kể từ khi thiết lập hiện tại của tôi mang lại cho tôi một đường ống) – gimmeamilk

1

Câu trả lời hay, tôi thích chúng ... Tôi cũng cần thoát khỏi habbit chọn và vào (e) bình chọn.

Dưới đây là một số phương pháp truyền thống hơn, nếu bạn cần chúng:

/* check whether a file-descriptor is valid */ 
int fd_valid(int fd) 
{ 
    if (fcntl(fd, F_GETFL) == -1 && errno == EBADF) return FALSE; 
    return TRUE; 
}  

một này cố gắng lặp lại trong các ổ cắm/fd. Nó đơn giản hơn rất nhiều so với vẻ bề ngoài, tôi rời rất nhiều debug trong.

/* check a file descriptor */ 
int fd_check(int i) { 
    int fd_dup = dup(i); 
    if (fd_dup == -1) { 
     strcpy(errst, strerror(errno)); 
     // EBADF oldfd isn’t an open file descriptor, or newfd is out of the allowed range for file descriptors. 
     // EBUSY (Linux only) This may be returned by dup2() during a race condition with open(2) and dup(). 
     // EINTR The dup2() call was interrupted by a signal; see signal(7). 
     // EMFILE The process already has the maximum number of file descriptors open and tried to open a new one. 

     if (errno == EBADF) { 
      return FALSE; 
     } 

     return TRUE; 
    } 
    close(fd_dup); 
    return TRUE; 
} 
Các vấn đề liên quan