高級編程之進程間通信(一)

進 程 間 通 信

 

進程間通信:三大類
1、古老的通信方式
  無名管道
  有名管道
  信號  ====》唯一的異步通信方式

2、systemV  IPC 對象
  消息隊列
  共享內存  ===》效率最高的通信方式
  信號量集

 

3、BSD socket 套接字
  域內套接字  ==》單機進程間通信
  網絡套接字  ==》不同主機上的進程間通信

古老的通信方式:
1、管道  ==》無名管道  有名管道

 無名管道 ==》pipe

 1、特性
  只能用於具有親緣關係的進程間使用。
  半雙工的通信模式,有固定的讀寫端。
  屬於特殊的設備文件,只能用文件IO讀寫。
  該類型的文件不支持定位操作。

 2、使用流程
 創建管道===》打開管道 ===》讀寫管道 ==》關閉管道
   pipe()           read()/write()  close()


 頭文件: #include <unistd.h>

 原型: int pipe(int fd[2]);
 功能:該函數可以創建一個無名管道,
       並且自動打開該管道。
 參數: fd[2] 管道的讀寫端,有如下默認約定
    fd[0] 固定的讀端
    fg[1] 固定的寫端
 返回值:成功  0
   失敗  -1;

 讀: read
 寫: write()


 關閉: close()



有名管道  ===>fifo  ===>在無名管道基礎之上增加了一個文件名稱
      方便在不同進程間使用。

操作流程:
 創建有名管道 ===》打開管道 ===》讀寫管道 ==》關閉管道 ===》卸載管道。
 mkfifo              open        read/write    close        unlink


1、創建有名管道 ==》mkfifo

#include <sys/types.h>
#include <sys/stat.h>

int mkfifo(const char *pathname, mode_t mode);
功能:在指定的pathname路徑下創建一個權限爲mode的有名管道。
參數:pathname 要創建的有名管道的路徑+管道名稱
   mode  要創建的管道文件權限。
返回值:成功  0
  失敗  -1;


***** 注意:
所有的管道都是設備文件,同時該設備文件有固定的讀寫端。
  open();的參數2 不能是 O_RDWR,只能是O_RDONLY 或者 O_WRONLY 之一

 

 

#include <unistd.h>

int unlink(const char *pathname);
功能:通過該函數可以完成指定的有名管道卸載。文件會被刪除。
參數:pathname 要卸載的管道
返回值:成功  0
  失敗   -1;

注意:unlink函數一般用於最後管道沒有人使用的時候卸載用。


一般爲了有名管道的配合使用。管道的創建工作可以獨立執行
或者在讀端啓動的時候首先創建。


練習:
1、從a.out程序中讀取指定文件內容通過有名管道發送到b.out
   並從 b.out 中打印輸出。

2、測試有名管道能否在fork之後的父子進程間使用。


注意:一般在項目中需要有一個有名管道的維護工具,
  可以動態的手工創建並刪除管道.比如:
  fifo_tool 名稱
  功能: fifo_tool -A abc   ===>在當前路徑下新建一個名稱爲
         abc 的有名管道
   fifo_tool -D abc   ===》刪除當前路徑下名稱爲abc的管道。

 

信號通信:====》傳遞的是信號 ,而不是數據.

通信框架:  發送端進程 ===》信號 ===》接收端進程


1、發送端進程 ===》函數: kill()  raise()  alarm ()  pause()

#include <sys/types.h>
#include <signal.h>

原型:int kill(pid_t pid, int sig);
功能: 通過該函數可以給指定的pid進程發送sig編號的信號。
參數: pid 要接受信號的進程pid號
      sig 要接受的信號。
返回值:成功 0
  失敗  -1;

原型: int raise(int sig);
功能: 進程自身給自己發送一個sig信號。
參數: sig 發給自己的信號編號
返回值:成功 0
  失敗  -1;

頭文件  #include <unistd.h>

原型: unsigned int alarm(unsigned int seconds);
功能:定時由OS給當前進程發送一個定時信號SIGALRM
   默認該信號會殺死進程。
參數:seconds  程序從當前函數開始後seconds秒後會
  收到來自OS的SIGALRM信號。
返回值:成功  0
  失敗   -1;


原型:int pause(void);
功能:使當前運行的進程暫停。
返回值:成功  0
  失敗   -1;

2、信號  ===》kill  -l 中前32個不穩定信號。

  
3、接受端進程 ===》進程收到信號的處理過程:

 每個進程對信號有三種處理方式:
  1、默認處理
  2、忽略處理
  3、自定義處理

信號的註冊函數: ==》signal  函數

原型:
 void (*signal(int signum,void (*handler)(int)))(int);

===>void (*xxx)(int aa);===>函數指針
    xxx == signal(int signum,void(*handler)(int));

===>typedef void (*sighandler_t)(int);

   sighandler_t signal(int signum, sighandler_t handler);
 
   signal(int signum,fun); ===>信號註冊函數

   其中:signum 表示要處理的信號編號
      fun 表示信號的處理方式:
     如果fun == SIG_IGN ===>表示忽略處理方式
       SIG_DFL ===>表示默認處理方式
      函數地址 ===》自定義函數‘

重要:在所有的信號中9 號的SIGKILL 和  19 號的 SIGSTOP
      信號不能被忽略。同時也不能被修改。


特殊:10  SIGUSR1
   12  SIGUSR2
   以上兩個信號在所有32個信號中是唯一的兩個沒有具體
   含義的臨時信號,預留給程序員編程使用。

練習題:
 編寫信號處理程序,當收到10號和12號信號的時候啓動不同的程序。
 其他信號都按默認處理流程。

 

 

 

 

 

 

 


 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章