linux學習筆記之進程間通訊

 

1、基礎知識。linux

1:進程通訊基礎(interProcess Communication, IPC):管道,FIFO(命名管道),XSI IPC,POSIX 信號量。shell

2:管道。數組

  1,缺陷。服務器

    1)部分系統支持全雙工(不肯定linux)函數

    2)管道只能在具備公共祖先的兩個進程之間使用。post

  2,相關函數。性能

  3,協同進程:一個過濾程序既產生某個過濾程序的輸入,又讀取該過濾程序的輸出。ui

3:FIFO。spa

  1,做用:可以使 不相關的進程 進行通訊。調試

  2,一些注意點。

    1)FIFO路徑名存在於文件系統中。

  3,一些用途。

    1)shell命令使用FIFO將數據從一條管道傳送到另一條。無需建立中間文件。

    2)C/S模式中,FIFO用做匯聚點,在客戶進程和服務器進程之間傳遞數據。

4:XSI IPC。

  1,有三種:消息隊列,信號量,共享儲存器。

  2,使用 非負整數 的標識符。數據類型爲: key_t <sys/types.h>

  3,有多種方法使 客戶進程 和服務器進程 在同一IPC結構上匯聚。

    1)服務器進程指定鍵IPC_PROVATE建立新IPC結構,並將標識符存放在某處,讓客戶進程取用。

    2)在公共頭文件中定義一個 兩個進程 都承認的鍵。

    3)兩個進程 承認一個路徑名和項目ID使用ftok函數將兩個值變成一個KEY。

  4,基本問題。

    1)IPC結構在系統範圍內起做用,沒有引用計數。

    2)IPC結構在文件系統中沒有名字。

    3)IPC不能使用文件描述符,因此不能對它們使用多路轉接IO函數。

  5,消息隊列:消息的連接表。

  6,信號量:一個計數器。用於爲多個進程提供對共享數據對象的訪問。

    1)信號量一般在內核中實現。且減1操做爲原子操做。

    2)進程終止時,內核會自動檢測信號量,並進行調整。

    3)互斥量比信號量快不少。但若是可能儘可能使用信號量。由於信號量的心痛支持度較高,並且複雜性更低。

  7,共享存儲:最快的IPC。

    1)信號量可用於同步共享儲存訪問。

5:POSIX 信號量。

  1,相對XSI優勢。

    1)更高性能。

    2)使用更簡單:沒有信號量集,部分操做統一化。

    3)信號量刪除表現的更完美:直到最後一次使用後才釋放。

  2,擁有兩種性是:命名的和未命名的。差別:建立和銷燬的形式上。

  3,爲增長移植性,信號量命名應該有必定規則:

    1)第一個字符爲 斜槓 / 。

    2)名字不包含其餘斜槓以免實現定義的行爲。

    3)信號量名最大長度由實現定義。

  4,P470 客戶進程-服務器進程屬性。

2、相關函數。

1:管道。

1 建立管道。
  int pipe( int fd[2] );
  // 1 fd[0]爲讀 fd[1]爲寫。fd[1]的輸出是fd[0]的輸入。
2 建立一個管道,fork一個子進程,關閉未使用的管道端,執行一個shell命令,等待命令終止。
  // !!!須要進一步瞭解者兩個函數原理和使用機制!!!
  FILE *popen( cosnt char *cmdstring, const char *type );  // fork --> exec and cmd --> return a ptr of IO.
  int pclose( FILE *fp );
  // 適用於簡單的過濾器程序

 

 2:FIFO:命名管道。

#include <sys/stat.h>
1 建立FIFO
  int mkfifo( const char *path, mode_t mode );
  int mkfifoat( int fd, const char *path, mode_t mode );
  // 1 通常狀況下,都是阻塞到讀寫開始爲止。但設置非阻塞時,會當即返回-1,errno設置ENXIO。

 

 

 3:XSI IPC

1 經過路徑名+項目ID產生一個KEY。
  key_t ftok( const char *path, int id );
  // 1 參數path必須引用現有文件,參數id只使用低8位。
2 ipc_perm 權限和全部者.
  struct ipc_perm
  {
    uid_t   uid;    // owner's effective user id.
    gid_t   gid;    // owner's effective group id.
    uid_t   cuid;   // creator's effective user id.
    gid_t   cgid;   // creator's effective group id.
    mode_t  mode;   // access modes
  }  // 此爲最小結構。具體實現 可添加成員
3 消息隊列的信息結構 msqid_ds。
  struct msqid_ds
  {
    struct ipc_perm      msg_perm;   // see section.
    msgqnum_t            msg_qnum;   // # of messages on queue.
    msglen_t             msg_qbytes; // max # of bytes on queue.
    pid_t                msg_lspid;  // pid of last msgsnd()
    pid_t                msg_lrpid;  // pid of last msgrcv()
    time_t               msg_stime;  // last-msgsnd() time
    time_t               msg_rtime;  // last-msgrcv() time
    time_t               msg_ctime;  // last-change time
  }
4 打開/建立 一個隊列。
  int msgget( key_t key, int flag );
5 對 隊列 執行多種操做。
  int msgctl( int msqid, int cmd, struct msqid_ds *buf );
  // 1 參數cmd:IPC_STAT, IPC_SET, IPC_RMID
6 將數據放到消息隊列中。
  int msgsnd( int msqid, cosnt void *ptr, size_t nbytes, int flag );
  // 1 參數ptr:指向mymesg結構。
7 從隊列取消息。
  ssize_t megrcv( int msqid, void *ptr, size_t nbytes, long type, int flag );
  // 1 參數type:>0時,以非 先進先出 的次序 獲取消息。
8 獲取一個信號量。
  int semget( key_t key, int nsems, int flag );
9 多種信號量操做。
  int semctl( int semid, int semnum, int cmd, .../* union semun arg */ );
  // 1 參數cmd:IPC_STAT,IPC_SET,IPC_RMID,GETVAL...
10 自動執行信號量集合上的操做數組。
  int semop( int semid, struct sembuf semoparray[], size_t nops );   // 具備原子性,或者執行全部,或者所有不執行。
  struct sembuf
  {
    unsigned short    sum_num;   // member # in set (0, 1, ..., nsems-1)
    short             sem_op;    // operation(negative, 0, or pasitive )
    short             sem_flg;   // IPC_NOWAIT, SEM_UNDO
  }
11 內核爲每一個共享儲存段維護一個結構。
  struct shmid_ds
  {
    struct ipc_perm  shm_perm;   // see section
    size_t           shm_segsz;  // size of segment in bytes
    pid_t            shm_lpid;   // pid of last shmop
    pid_t            shm_cpid;   // pid of creator
    shmatt_t         shm_nattch; // number of current attaches
    time_t           shm_atime;  // last-attach time
    time_t           shm_dtime;  // last-detach time
    time_t           shm_ctime;  // last-change time
    ...
  }
12 得到一個共享儲存標示符。
  int shmget( key_t key, size_t size, int flag );
  // 1 參數size:字節爲單位。一般爲系統頁長的整倍數。
13 對共享存儲 執行多種操做。
  int shmctl( int shmid, int cmd, struct shmid_ds *buf );
  // 1 參數cmd:IPC_STAT,IPC_SET,IPC_RMID,SHM_LOCK,SHM_UNLOCK
14 將共享存儲鏈接到進程中。
  void shmat( int shmid, cosnt void *addr, int flag );
15 進程和共享存儲的分離操做(不刪除共享存儲)。
  int shmdt( const void *addr );

 

4:POSIX 信號量。

1 建立信號量 / 使用現有信號量。
  sem_t sem_open( const char *name, int oflag, mode_t mode, unsinged int value );
2 釋放信號量相關資源。
  int sem_close( sem_t *sem );
3 銷燬一個命名信號量。
  int sem_unlink( const char *name );  // 當最後一個引用關閉時 才銷燬。
4 實現信號量減一操做。
  int sem_trywait( sem_t *sem );
  int sem_wait( sem_t *sem );
  int sem_timedwait( sem_t *sem, const struct timespec *restrict tsptr );
  // 1 資源爲0時,發生阻塞。>0,減一
5 信號量+1
  int sem_post( sem_t *sem );
6 建立/銷燬 一個未命名信號量。
  int sem_init( sem_t *sem, int pshared, unsigned int value );
  int sem_destroy( sem_t *sem );
7 檢索信號量值。
  int sem_getvalue( sem_t *restrict sem, int *restrict valp );
  // 1 除非使用額外的同步機制來避免競爭,不然此函數只能用於調試

 

3、

相關文章
相關標籤/搜索