Linux IO模型漫談(6)- 信號驅動IO模型


Unix上有定義了許多信號。源自Berkeley的實現使用的是SIGIO信號來支持套接字和終端設備上的信號驅動IO。

信號驅動IO模型主要是在UDP套接字上使用,在TCP套接字上幾乎是沒有什么使用的。

在UDP上,SIGIO信號會在下面兩個事件的時候產生:

1 數據報到達套接字

2 套接字上發上一部錯誤

因此我們很容易判斷SIGIO出現的時候,如果不是發生錯誤,那么就是有數據報到達了。

而在TCP上,由於TCP是雙工的,它的信號產生過於平凡,並且信號的出現幾乎沒有告訴我們發生了什么事情。因此對於TCP套接字,SIGIO信號是沒有什么使用的。

 

sigaction(查詢或設置信號處理方式)

int sigaction(int signum,const struct sigaction *act ,struct sigaction *oldact);

 

參數含義:

signum:所注冊的信號,我們這邊都設置為SIGIO

act :信號觸發所處理的函數

oldact:一般設置為NULL

這里涉及到了

sigaction結構

struct sigaction
{
  void (*sa_handler) (int);
  sigset_t sa_mask;
  int sa_flags;
  void (*sa_restorer) (void);

}

sa_handler代表的是新的信號處理函數

sa_mask 用來設置在處理該信號時暫時將sa_mask 指定的信號擱置

sa_flags 用來設置信號處理的其他相關操作

下面的例子是基於UDP的程序

服務器端:

#include <stdio.h>
  
  
  
          
           
   
   
   
#include <sys/types.h>
   
   
   
           
             #include <sys/socket.h> 
            
              #include <netinet/in.h> 
             
               #include <string.h> 
              
                #include <unistd.h> 
               
                 #include <signal.h> 
                
                  #include <fcntl.h> 
                 
                   int listenfd1; void do_sigio(int sig) { int clifd, clilen; struct sockaddr_in cli_addr; char buffer[256]; clifd = accept(listenfd1, (struct sockaddr *) &cli_addr, &clilen); bzero(buffer, 256); read(clifd, buffer, 255); printf("Listenfd1 Message%s\r\n", buffer); } int main(int argc, char *argv[]) { //綁定監聽7779端口的fd struct sockaddr_in serv_addr1; listenfd1 = socket(AF_INET, SOCK_DGRAM, 0); bzero((char *) &serv_addr1, sizeof(serv_addr1)); serv_addr1.sin_family = AF_INET; serv_addr1.sin_port = htons(7779); serv_addr1.sin_addr.s_addr = INADDR_ANY; struct sigaction sigio_action; memset(&sigio_action, 0, sizeof(sigio_action)); sigio_action.sa_flags = 0; sigio_action.sa_handler = do_sigio; sigaction(SIGIO, &sigio_action, NULL); fcntl(listenfd1, F_SETOWN, getpid()); int flags; flags = fcntl(listenfd1, F_GETFL, 0); flags |= O_ASYNC | O_NONBLOCK; fcntl(listenfd1, F_SETFL, flags); bind(listenfd1, (struct sockaddr *) &serv_addr1, sizeof(serv_addr1)); while(1); close(listenfd1); return 0; } 
                  
                 
                
               
              
             
           
  
  
  
          
客戶端:
#include <stdio.h> 
  
  
  
          
           
   
   
   
#include <sys/socket.h> 
   
   
   
           
             #include <sys/types.h> 
            
              #include <netinet/in.h> 
             
               #include <string.h> 
              
                #include <unistd.h> 
               
                 int main(int argc, char* argv[]) { int socketfd, n; socketfd = socket(AF_INET, SOCK_DGRAM, 0); struct sockaddr_in serv_addr; bzero((char *)&serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(7779); connect(socketfd,(struct sockaddr *) &serv_addr, sizeof(serv_addr)); write(socketfd, "client message", 14); return 0; } 
                
               
              
             
           
  
  
  
          

運行結果:

clip_image001

clip_image002


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM