1. 程式人生 > >linux io 學習筆記(03)---共享內存,信號燈,消息隊列

linux io 學習筆記(03)---共享內存,信號燈,消息隊列

pat value maximum oid 選擇性 同步互斥 接收 實現 映射

system V IPC

1)消息隊列

2)共享內存

3)信號燈(信號量集)

1.消息隊列、

  ipcs -q 查看系統中使用消息隊列的情況

  ipcrm -q +msqid 刪除消息隊列

  消息隊列工作原理:在內核空間上創建隊列,信息發送者將發送信息打包成結點添加到隊列中,信息的接受者選擇性從隊列上讀取想要的節點

  1)創建隊列,2)向隊列中添加信息,3)從隊列中移除信息,4)實現隊列的控制(獲取隊列的屬性,設置隊列的屬性,刪除不使用的隊列)

  1)創建隊列:

      函數原型:key_t ftok(const char *pathname,int proj_id);

      功能  :生成key值

      參數  :pathname 路徑名(用戶給定,路徑必須真實存在)

            proj_id 傳字符

      返回值:成功 key值 隨機數

          失敗:-1

      函數原型:intmsgget(key_t key,int msgflg);

      功能:  創建消息隊列

      參數:  key 值 0或非0  key值確保消息隊列的唯一性

            msgflg 標誌位    IPC_CREAT|IPC_EXCL|0664 創建並打開消息隊列(如果消息隊列不存在,自動創建,如果存在,返回EEXIST)

                        0664 按該權限打開消息隊列。

      返回值:成功: 消息隊列標識符

          失敗 -1

  2)添加消息

    函數原型:int msgsnd(int msqid,const void *msgp,size_t msgsz,int msgflg);

    功能  :將消息添加到隊列的末尾

    參數  :msqid 消息隊列的標識符

          msgp 發送的消息

            struct msgbuf{

                  long mtype; 消息的類型

                  char mtext[1]; 消息的征文

                };

          msgsz 消息征文的大小

          msgflg  0 消息隊列沒空間,寫操作阻塞

    返回值  : 成功:0;失敗:-1;

  3)將消息從隊列中移除

     函數原型:ssize_t masrcv(int msqid,void *msgp,size_t msgsz,long msgtype,int msgflg);

     參數  :msqid 消息隊列標識符

          msgp 保存接受的消息(定義和寫入時保持一致)

          msgsz 消息正文的大小

          msgtype 消息的類型    0 讀取消息隊列中的第一個消息

                      >0 讀取消息隊列中類型為msgtype 的第一個消息

                      <0 讀取消息隊列中不小於msgtype 的絕對值,且類型最小的第一個消息

          msgflg 0  消息隊列中無數據,讀操作阻塞

      返回值:成功 消息正文的大小

          失敗 -1

  4)對消息隊列的控制

      函數原型:int msgctl(int msqid,int cmd,struct msqid_ds *buf);

      功能  :實現對消息隊列的控制

      參數  :msqid 消息隊列的標識符

          :cmd 制定消息隊列的操作處理

              IPC_STAT 從第三個參數讀取消息隊列的屬性信息

              IPC_SET  設置消息隊列的屬性

              IPC_RMID  刪除消息隊列

          :buf  描述消息隊列屬性的結構體          

struct msqid_ds {

struct ipc_perm msg_perm; /* Ownership and permissions */ 消息隊列的權限
time_t msg_stime; /* Time of last msgsnd(2) */ 消息隊列發送消息的時間
time_t msg_rtime; /* Time of last msgrcv(2) */ 消息隊列接受消息的時間
time_t msg_ctime; /* Time of last change */ 消息隊列改變的時間
unsigned long __msg_cbytes; /* Current number of bytes in
queue (nonstandard) */ 消息隊列當前的字節數
msgqnum_t msg_qnum; /* Current number of messages
in queue */ 消息隊列當前消息的個數
msglen_t msg_qbytes; /* Maximum number of bytes
allowed in queue */ 消息隊列最大的字節數
pid_t msg_lspid; /* PID of last msgsnd(2) */ 發送消息的用戶ID
pid_t msg_lrpid; /* PID of last msgrcv(2) */ 接收消息的用戶ID

};

返回值:成功 0
失敗 -1

實現兩個終端數據交互(創建子進程)

2.共享內存

  工作原理:系統為每一個進程創建4G的虛擬地址空間,共享內存開辟一塊實際的物理內存區域(共享內存區域)將該區域映射給每一個進程

  本質  :多進程實際都是在訪問同一塊物理內存區域

   其通信效率最高,適用場合:實現實時數據傳輸

   多進程訪問同一塊物理內存區域,容易產生竟態,共享內存結合同步互斥機制,保證數據的正確性,任何一個時刻只有一個任務在訪問共享的內存區域

  1)申請物理內存區域

    函數原型:int shmget(key_t key,size_t size,int shmflg);

    功能  :開辟實際物理內存區域

    參數  :key: 來自ftok

        :size 物理內存的大小

        :shmflg   IPC_CREAT|IPC_EXCK|0664 創建並打開物理內存(內存不存在,開辟;已存在,報錯)

    返回值 :成功 共享內存的標識符

         失敗 -1

  2)將物理內存映射到進程的虛擬地址空間上(進程只需要操作屬於自己的虛擬地址空間,本質訪問實際物理內存)

    函數原型: void *shmat(int shmid,const void *shmaddr,int shmflg);

    功能  :將物理內存區域映射到進程的虛擬地址空間(將物理地址轉換為虛擬地址)

    參數  :shmid  共享內存標識符

        :shmaddr  NULL 將物理內存映射進程一個合理的位置(未使用,且內存足夠大區域)

        :shmflg  0 對於共享內存段,可以實現讀寫

    返回值  :成功 鏈接物理內存的虛擬地址

          失敗 -1

  3)將物理內存釋放

    函數原型:int shmctl(int shmid,int cmd,struct shmid_ds *buf);

    功能  :實現對共享內存的控制

    參數  :shmid  共享內存的標識符

        :cmd  制定對共享內存的操作

              IPC_STAT 從第三個參數中讀取共享內存的屬性信息

              IPC_SET  設置共享內存的屬性信息

              IPC_RMID  刪除共享內存

        :buf  描述共享內存屬性的結構體

struct shmid_ds {
struct ipc_perm shm_perm; /* Ownership and permissions */ 訪問的權限
size_t shm_segsz; /* Size of segment (bytes) */ 共享內存的大小
time_t shm_atime; /* Last attach time */ 上一次被映射的時間
time_t shm_dtime; /* Last detach time */ 上一次被斷開映射的時間
time_t shm_ctime; /* Last change time */ 上一次改變的時間
pid_t shm_cpid; /* PID of creator */ 創建共享內存的用戶ID
pid_t shm_lpid; /* PID of last shmat(2)/shmdt(2) */ 上一次執行映射和斷開映射的進程ID
shmatt_t shm_nattch; /* No. of current attaches */ 被映射的次數(編號)
...
};
返回值:成功 0
失敗 -1

4.信號燈

  信號燈:信號量集

  信號量的核心:PV操作

  1)創建多個信號量

    函數原型:int semget(key_t key,int nsems,int semflg);

    功能  :創建或打開多個信號量

    參數  :key 值 ftok

        :nsems 創建或打開信號量的個數

        :semflg IPC_CREAT|IPC_EXCL|0664 創建並打開信號量(信號量存在,報錯,不存在,自動創建)

        : 0664 打開信號量集的標識符

    返回值: 成功:信號量集的標識符,失敗:-1

  2)申請,釋放信號量

    函數原型:int semop(int semid,struct sembuf *sops,unsigned nsops);

    功能  :實現對信號量集的操作

    參數  :semid 信號量集的標識符

        : sops:

struct sembuf{
  unsigned short sem_num; /* semaphore number */ 信號量的編號
  short sem_op; /* semaphore operation */
      1   釋放信號量 值+1
      0 等待信號量的值變為0
      -1 申請信號量 值-1
short sem_flg; /* operation flags */ 默認為0
}
nsops 本次函數操作的信號量的個數
返回值:成功 0
失敗 -1

   3)信號量集的控制

函數原型:int semctl(int semid, int semnum, int cmd, ...);
功能:實現對信號量集中某一個信號量的控制
參數:semid 信號量集的標識符
semnum 信號量集信號量的編號
cmd 指定對信號量的控制
IPC_STAT 獲取信號量的屬性信息
IPC_SET 設置信號量的屬性信息
IPC_RMID 刪除信號量
SETVAL 設置第semnum個信號量的初始值
GETVAL 獲取第semnum個信號量的值
返回值:成功 0
GETVAL 當前信號量的值

失敗 -1
  ... 附件參數
 union semun {
    int val; /* Value for SETVAL */
    struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
    unsigned short *array; /* Array for GETALL, SETALL */
    struct seminfo *__buf; /* Buffer for IPC_INFO
    (Linux-specific) */
  };
信號量的屬性
truct semid_ds {
  struct ipc_perm sem_perm; /* Ownership and permissions */ 訪問的權限
  time_t sem_otime; /* Last semop time */ 上一次PV操作的時間
  time_t sem_ctime; /* Last change time */ 上一次改變的時間
  unsigned short sem_nsems; /* No. of semaphores in set */ 信號量集合中信號量個數
};

linux io 學習筆記(03)---共享內存,信號燈,消息隊列