2011-06-06 62 views
12

我的程序經過這樣的循環:當它等待輸入,這恰好是從插座中斷阻止讀

... 
while(1){ 
    read(sockfd,buf,sizeof(buf)); 
    ... 
} 

讀取功能塊。我想處理SIGINT並基本告訴它如果正在讀取並停止讀取函數,然後調用任意函數。做這個的最好方式是什麼?

回答

14

read(2)

EINTR The call was interrupted by a signal before any data 
      was read; see signal(7). 

如果你修改你的代碼看起來更像:

cont = 1; 
while (1 && cont) { 
    ret = read(sockfd, buf, sizeof(buf)); 
    if (ret < 0 && errno == EINTR) 
     cont = arbitrary_function(); 
} 

這讓arbitrary_function()決定是否read(2)應重新審理或者不。

更新

你需要爲了得到read(2)EINTR行爲來處理信號:

#include<unistd.h> 
#include<stdio.h> 
#include<stdlib.h> 
#include<signal.h> 
#include<errno.h> 

int interrupted; 

void handle_int(num) { 
    interrupted = 1; 
} 

int main(void){ 
    char buf[9001]; 
    struct sigaction int_handler = {.sa_handler=handle_int}; 
    sigaction(SIGINT,&int_handler,0); 
    while(!interrupted){ 
    printf("interrupted: %d\n", interrupted); 
    if(read(0,buf,sizeof(buf))<0){ 
     if(errno==EINTR){ 
     puts("eintr"); 
     }else{ 
     printf("%d\n",errno); 
     } 
     puts("."); 
    } 
    } 
    puts("end"); 
    return 0; 
} 

給出輸出:

$ ./foo 
interrupted: 0 
hello 
interrupted: 0 
^Ceintr 
. 
end 
+0

根據您提供什麼,發送SIGINT(通過Ctrl + C)只是結束程序。 – kaykun 2011-06-06 09:06:07

+0

@ kaykun,只有這是程序的最後一行。您可以在重新啓動傳輸的'while'塊之後添加更多行,您可以刪除特定客戶端並繼續執行程序的主循環,您可以啓動與用戶的交互式shell,以詢問接下來要執行的操作沒有什麼說這必須終止程序。 – sarnold 2011-06-06 09:13:25

+0

@sarnold不正確,至少對我來說,無論我在while循環後添加什麼,發送SIGINT時程序都會終止,這對幾乎所有其他命令行程序都是一樣的。 – kaykun 2011-06-06 09:21:58

2

當您的進程收到信號時,read()將返回並且errno的值將設置爲EINTR