2011-02-10 23 views
35

Tôi đang lập trình một ứng dụng người dùng cho một hệ thống Linux nhúng và tôi đang sử dụng các chức năng phổ biến như mở, đóng, đọc, ioctl, v.v. cho các thiết bị. Bây giờ, tôi đọc về EINTR, chỉ ra rằng chức năng đã bị gián đoạn bởi một tín hiệu, nhưng tôi không chắc chắn về các tác động. Trong tất cả các chương trình ví dụ tôi có, đôi khi nó được thực hiện, ví dụ: ioctl(), đôi khi nó không được thực hiện, ví dụ: đọc(). Vì vậy, tôi hơi bối rối một chút.Khi nào cần kiểm tra EINTR và lặp lại cuộc gọi chức năng?

Khi nào tôi nên kiểm tra EINTR và lặp lại cuộc gọi chức năng?

+0

tại sao bạn muốn gọi chức năng của bạn một lần thứ hai? sau khi ngắt được xử lý, điều khiển được đưa trở lại ứng dụng/chức năng của bạn – knittl

+0

Câu hỏi tương tự: http://stackoverflow.com/questions/3633844/question-on-signal-handling-interrupt-handling – stefangachter

Trả lời

11

Xem sigaction: http://pubs.opengroup.org/onlinepubs/009695399/functions/sigaction.html

SA_RESTART 
    This flag affects the behavior of interruptible functions; that is, those 
    specified to fail with errno set to EINTR. If set, and a function specified 
    as interruptible is interrupted by this signal, the function shall restart 
    and shall not fail with EINTR unless otherwise specified. If the flag is not 
    set, interruptible functions interrupted by this signal shall fail with errno 
    set to EINTR. 

Theo mặc định, bạn có hành vi SA_RESTART, vì vậy bạn không cần phải lo lắng về EINTR, nếu bạn không chơi với các tín hiệu.

+1

Vì vậy, miễn là tôi không sử dụng tín hiệu trong các ứng dụng của người dùng, tôi không phải lo lắng về EINTR? Nhưng ví dụ: read() là một cuộc gọi hệ thống, do đó không phải là nó có thể đọc() có thể bị gián đoạn bởi tín hiệu? – stefangachter

+3

Sau khi dành thêm thời gian đọc, tôi đi đến kết luận rằng tôi phải kiểm tra các cuộc gọi hệ thống bị gián đoạn, không được tính đến bởi cờ SA_RESTART. – stefangachter

+0

Sau khi tất cả, điều này chỉ quan trọng bên trong một bộ xử lý tín hiệu. Miễn là tôi không có một bộ xử lý tín hiệu, tôi không quan tâm. – stefangachter

3

Sự kiện ứng dụng của bạn có được thúc đẩy không? (Có nghĩa là vòng lặp chính của nó bao gồm cuộc gọi select()/epoll_wait()).

Trong ứng dụng điều khiển sự kiện, bạn có thể chặn tất cả các tín hiệu và chỉ bỏ chặn chúng trong khoảng thời gian gọi pselect()/epoll_pwait(). Bằng cách này phần còn lại của mã của bạn không bao giờ phải đối phó với EINTR.

3

Liên kết này có giải thích khá tốt.

http://www.ibm.com/developerworks/linux/library/l-reent.html

Chúc mừng!

+0

Liên kết có thể được quan tâm khi viết xử lý tín hiệu, nhưng nó không đề cập đến EINTR và hầu như không trả lời câu hỏi, "Khi nào thử lại trên EINTR?" –

1

Tôi gặp sự cố tương tự khi đợi đầu vào từ một đường ống được đặt tên có read().

Tôi tìm thấy một lời giải thích và một macro hữu ích cho nguyên thủy trong GNU libc documentation: TEMP_FAILURE_RETRY

Ví dụ:

TEMP_FAILURE_RETRY (read_return = read((int)example_fifo, buffer, (size_t)n)); 
if (read_return==-1){ 
    fprintf(stderr, "reader.c: read_fifo: read(): %s \n", strerror(errno)); 
    fflush(stderr); 
} 
Các vấn đề liên quan