嵌入式Linux併發程式設計,程序間通訊方式,System V IPC物件,ftok(),共享記憶體使用步驟,建立shmget(),對映shmat(),撤銷對映shmdt(),控制shmctl(),注意
阿新 • • 發佈:2018-12-14
文章目錄
1,System V IPC
- IPC 物件包含: 共享記憶體、訊息佇列和訊號燈集
- 每個IPC物件有唯一的ID(IPC物件建立的時候由系統分配的一個數字,只有建立IPC物件的程序可以獲得ID,別的程序不知道這個ID號)
- IPC物件建立後一直存在,直到被顯式地刪除
- 每個IPC物件有一個關聯的KEY(可以看成IPC物件的一個屬性,通過KEY值,可以使不同的程序能夠開啟同一個IPC物件。建立IPC物件的程序把KEY值和IPC物件關聯)
- ipcs / ipcrm
·ipcs檢視System V的IPC物件(顯示當前系統中所有的IPC物件)
·iprm刪除System V的IPC物件
[email protected]:~$ ipcs ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status 0x00000000 1769472 linux 600 524288 2 dest 0x00000000 327681 linux 600 524288 2 dest 0x00000000 425986 linux 600 524288 2 dest 0x00000000 819203 linux 600 524288 2 dest 0x00000000 1376260 linux 600 33554432 2 dest 0x00000000 917509 linux 600 524288 2 dest 0x00000000 950278 linux 600 16777216 2 0x00000000 1277959 linux 600 524288 2 dest 0x00000000 1146888 linux 600 524288 2 dest 0x00000000 1900553 linux 600 524288 2 dest 0x00000000 1998858 linux 600 524288 2 dest 0x00000000 1802251 linux 600 2097152 2 dest ------ Semaphore Arrays -------- key semid owner perms nsems ------ Message Queues -------- key msqid owner perms used-bytes messages
- KEY值為0,表示私有的IPC物件
ipcrm [ -M key | -m id | -Q key | -q id | -S key | -s id ] ...
- M/m 對應共享記憶體
- Q/q 對應訊息佇列
- S/s 對應訊號燈集
2,使用IPC物件的大致流程
- 程序建立IPC物件之前先指定一個KEY,KEY的值可以為0(巨集IPC_PRIVATE的值為0),為0表示這是一個私有物件,不為0表示這個物件會被多個程序訪問
- KEY值還可以通過函式ftok()建立(避免指定的KEY值會與系統中已有的KEY值衝突)
- 根據KEY值去建立IPC物件
3,生成KEY值ftok()
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *path, int proj_id);
- 成功時返回合法的key值,失敗時返回EOF
- path 存在且可訪問的檔案的路徑(ftok()生成的KEY值實際上path所指的檔案的i節點的編號)
- proj_id 用於生成key的數字,不能為0(i節點的編號和proj_id的低8為進行移位,拼成一個新的數字)
ftok示例
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
key_t key;
if ((key = ftok(“.”, ‘a’)) == -1)
{
perror(“key”);
exit(-1);
}
……
- 每個程序必須生成相同的KEY,才能通過相同的KEY,找到相同的IPC物件(每個程序都需要呼叫ftok()函式,且引數必須一致,引數一致才能生成相同的KEY)
4,共享記憶體
- 共享記憶體是一種最為高效的程序間通訊方式,程序可以直接讀寫記憶體,而不需要任何資料的拷貝
- 共享記憶體在核心空間建立,可被程序對映到使用者空間訪問,使用靈活
- 由於多個程序可同時訪問共享記憶體,因此需要同步和互斥機制配合使用
4.1,共享記憶體使用步驟
- 建立/開啟共享記憶體
- 對映共享記憶體,即把指定的共享記憶體對映到程序的地址空間用於訪問
- 讀寫共享記憶體
- 撤銷共享記憶體對映
- 刪除共享記憶體物件
4.2,共享記憶體建立 shmget()
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, int size, int shmflg);
- 成功時返回共享記憶體的id,失敗時返回EOF
- key 和共享記憶體關聯的key,IPC_PRIVATE 或 ftok生成
- size指定共享記憶體的大小,以位元組為單位
- shmflg 共享記憶體標誌位 IPC_CREAT|0666(是否新建,以及對共享記憶體的讀寫許可權)
4.2.1,共享記憶體建立shmget()示例
示例一:建立一個私有的共享記憶體,大小為512位元組,許可權為0666
int shmid;
if ((shmid = shmget(IPC_PRIVATE, 512, 0666)) < 0)
{
perror(“shmget”);
exit(-1);
}
- 私有的共享記憶體一定是新建的,所以不需要加 IPC_CREAT標誌
示例二:建立/開啟一個和key關聯的共享記憶體,大小為1024位元組,許可權為0666
key_t key;
int shmid;
if ((key = ftok(“.”, ‘m’)) == -1)
{
perror(“ftok”);
exit(-1);
}
if ((shmid = shmget(key, 1024, IPC_CREAT|0666)) < 0)
{
perror(“shmget”);
exit(-1);
}
- 指定了IPC_CREAT標誌,執行shmget()函式的時候,系統會檢查,如果和key關聯的共享記憶體物件不存在則建立一個,並把key值和物件關聯;如果已經存在,直接返回物件ID,並開啟
4.3,共享記憶體對映 shmat()
#include <sys/ipc.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
- 成功時返回對映後的地址,失敗時返回(void *)-1
- shmid 要對映的共享記憶體id
- shmaddr 對映後的地址, NULL表示由系統自動對映
- shmflg 標誌位 0表示可讀寫;SHM_RDONLY表示只讀
4.4,共享記憶體讀寫—示例
例如:在共享記憶體中存放鍵盤輸入的字串
char *addr;
int shmid;
……
if ((addr = (char *)shmat(shmid, NULL, 0)) == (char *)-1)
{
perror(“shmat”);
exit(-1);
}
fgets(addr, N, stdin);
……
- 通過指標訪問共享記憶體,指標型別取決於共享記憶體中存放的資料型別
4.5,共享記憶體撤銷對映 shmdt()
#include <sys/ipc.h>
#include <sys/shm.h>
int shmdt(void *shmaddr);
- 成功時返回0,失敗時返回EOF
- 不使用共享記憶體時應撤銷對映
- 程序結束時自動撤銷
- shmaddr 對映後的地址
4.6,共享記憶體控制 shmctl()
#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
- 成功時返回0,失敗時返回EOF
- shmid 要操作的共享記憶體的id
- cmd 要執行的操作 IPC_STAT(獲取當前共享記憶體的shmid_ds結構並儲存在buf中) IPC_SET(使用buf中的值設定當前共享記憶體的shmid_ds結構) IPC_RMID(刪除當前共享記憶體,第三個引數傳NULL)
- buf 儲存或設定共享記憶體屬性的地址
- shmid_ds結構 ,共享記憶體的屬性,包括:大小、跟它關聯的key值、許可權、建立者使用者ID等
4.7,共享記憶體 - 注意事項
- 每塊共享記憶體大小有限制
·ipcs -l(檢視當前系統中關於三類IPC物件的設定)
·cat /proc/sys/kernel/shmmax(檢視當前系統中關於共享記憶體最大大小的設定) - 修改共享記憶體大小
·sysctl -w kernel.shmmax=134217728
·echo 134217728 >/proc/sys/kernel/shmmax - 共享記憶體刪除的時間點(最後一個程序負責刪除共享記憶體)
·shmctl(shmid, IPC_RMID, NULL) 新增刪除標記
·nattach 變成0時真正刪除(nattach記錄了有幾個程序映射了共享記憶體,呼叫shmat()時nattach加一,呼叫shmdt()nattach減一)
[email protected]:~$ ipcs -l
------ Shared Memory Limits --------
max number of segments = 4096
max seg size (kbytes) = 32768
max total shared memory (kbytes) = 8388608
min seg size (bytes) = 1
------ Semaphore Limits --------
max number of arrays = 128
max semaphores per array = 250
max semaphores system wide = 32000
max ops per semop call = 32
semaphore max value = 32767
------ Messages Limits --------
max queues system wide = 1737
max size of message (bytes) = 8192
default max size of queue (bytes) = 16384
[email protected]:~$ cat /proc/sys/kernel/shmmax
33554432