天天看點

百度面試(程序通信、socket)

1.  程序間通信

        程序間通信主要包括管道, 系統IPC(包括消息隊列,信号量,共享存儲), SOCKET.

  系統IPC的三種方式類同,都是使用了核心裡的辨別符來識别.       
匿名管道( pipe ):匿名管道是一種半雙工的通信方式,通常是在父子程序間使用。      
命名管道 (named pipe) :命名管道也是半雙工的通信方式,但是它允許無親緣關系程序間的通信。      
信号量( semophore ) : 信号量是一個計數器,可以用來控制多個程序對共享資源的通路。它常作為一種鎖機制,防止某程序正在通路共享資源時,其他程序也通路該資源。是以,主要作為程序間以及同一程序内不同線程之間的同步手段。      
消息隊列( message queue ) : 消息隊列是消息的連結清單,存放在核心中并由消息隊列辨別符辨別。消息隊列克服了信号傳遞資訊少、管道隻能承載無格式位元組流以及緩沖區大小受限等缺點。      
信号 ( sinal ) :信号是一種比較複雜的通信方式,用于通知接收程序某個事件已經發生。      
共享記憶體( shared memory ) :共享記憶體就是映射一段能被其他程序所通路的記憶體,這段共享記憶體由一個程序建立,但多個程序都可以通路。共享記憶體是最快的 IPC 方式,它是針對其他程序間通信方式運作效率低而專門設計的。它往往與其他通信機制,如信号量,配合使用,來實作程序間的同步和通信。      
套接字( socket ) :套接字也是一種程序間通信機制,與其他通信機制不同的是,它可用于不同程序間的程序通信。      
FAQ1: 管道與檔案描述符,檔案指針的關系? 
  答: 其實管道的使用方法與檔案類似,都能使用read,write,open等普通IO函數. 管道描述符類似于檔案描述符. 事實上, 管道使用的描述符, 檔案指針和檔案描述符最終都會轉化成系統中SOCKET描述符. 都受到系統核心中SOCKET描述符的限制. 本質上LINUX核心源碼中管道是通過空檔案來實作.

FAQ2: 管道的使用方法? 
  答: 主要有下面幾種方法: 1)pipe, 建立一個管道,傳回2個管道描述符.通常用于父子程序之間通訊. 2)popen, pclose: 這種方式隻傳回一個管道描述符,常用于通信另一方是stdin or stdout; 3)mkpipe: 命名管道, 在許多程序之間進行互動.

FAQ3: 管道與系統IPC之間的優劣比較? 
  答: 管道: 優點是所有的UNIX實作都支援, 并且在最後一個通路管道的程序終止後,管道就被完全删除;缺陷是管道隻允許單向傳輸或者用于父子程序之間.

  系統IPC: 優點是功能強大,能在毫不相關程序之間進行通訊; 缺陷是關鍵字KEY_T使用了核心辨別,占用了核心資源,而且隻能被顯式删除,而且不能使用SOCKET的一些機制,例如select,epoll等.

FAQ4: WINDOS程序間通信與LINUX程序間通信的關系? 
  答: 事實上,WINDOS的程序通信大部分移植于UNIX, WINDOS的剪貼闆,檔案映射等都可從UNIX程序通信的共享存儲中找到影子. 

FAQ5: 程序間通信與線程間通信之間的關系? 
  答: 因為WINDOWS運作的實體是線程, 狹義上的程序間通信其實是指分屬于不同程序的線程之間的通訊.而單個程序之間的線程同步問題可歸并為一種特殊的程序通信.它要用到核心支援的系統調用來保持線程之間同步. 通常用到的一些線程同步方法包括:Event, Mutex, 信号量Semaphore, 臨界區資源等.      

2.關于socket的write和read

       百度面試中的一個問題:如果write 100位元組的資料,那麼讀多少?

       首先看這兩個函數原型:

      Write函數

      Ssize_t write(int fd,const void*buf,size_t nbytes);

      Write函數将buf中的nbytes位元組内容寫入到檔案描述符中,成功傳回寫的位元組數,失敗傳回-1.并設定errno變量。在網絡程式中,當我們向套接字檔案描述舒服寫資料時有兩種可能:

      1、write的傳回值大于0,表示寫了部分資料或者是全部的資料,這樣用一個while循環不斷的寫入資料,但是循環過程中的buf參數和nbytes參數是我們自己來更新的,也就是說,網絡程式設計中寫函數是不負責将全部資料寫完之後再傳回的,說不定中途就傳回了!

      2、傳回值小于0,此時出錯了,需要根據錯誤類型進行相應的處理。

      如果錯誤是EINTR表示在寫的時候出現了中斷錯誤,如果是EPIPE表示網絡連接配接出現了問題。

      Read函數

      Ssize_t read(int fd,void*buf,size_t nbyte)

      Read函數是負責從fd中讀取内容,當讀取成功時,read傳回實際讀取到的位元組數,如果傳回值是0,表示已經讀取到檔案的結束了,小于0表示是讀取錯誤。

      如果錯誤是EINTR表示在寫的時候出現了中斷錯誤,如果是EPIPE表示網絡連接配接出現了問題。

      雖然寫了100個位元組,但并不能保證read一次即讀100個位元組,寫的時候也并非寫100就成功了,write和read實際成功讀寫的位元組數由傳回值确定。

繼續閱讀