linux進程間通信(消息隊列、信號量、共享內存等)_第1頁
linux進程間通信(消息隊列、信號量、共享內存等)_第2頁
linux進程間通信(消息隊列、信號量、共享內存等)_第3頁
linux進程間通信(消息隊列、信號量、共享內存等)_第4頁
linux進程間通信(消息隊列、信號量、共享內存等)_第5頁
已閱讀5頁,還剩65頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、Company nameLinux培培訓訓主講人:主講人:肖勇軍肖勇軍Linux進程間通信(下)Linux IPC programme桂電嵌入式交流群:156619189Linux 培培訓訓課程目標lSystem V IPC 接口簡介System V 消息隊列消息隊列System V 信號量System V 共享內存lPOSIX IPC接口Posix 消息隊列Posix 信號量信號量Posix 共享內存共享內存Company nameLinux培培訓訓主講人:主講人:肖勇軍肖勇軍桂電嵌入式交流群:156619189Linux 培培訓訓System V IPC 接口l由于歷史原因, linux下

2、的進程通信手段基本上是從Unix平臺上的進程通信手段繼承而來的 .lUnix發(fā)展做出重大貢獻的兩大主力AT&T的貝爾實驗室及BSD(加州大學伯克利分校的伯克利軟件發(fā)布中心)在進程間通信方面的側重點有所不同 貝爾實驗室對Unix早期的進程間通信手段進行了系統(tǒng)的改進和擴充,形成了“system V IPC”,通信進程局限在單個計算機內 .BSD則形成了基于套接口(socket)的進程間通信機制 ,可以在跨機器進行通信.l由于Unix版本的多樣性,電子電氣工程協(xié)會(IEEE)開發(fā)了一個獨立的Unix標準,這個新的ANSI Unix標準被稱為計算機環(huán)境的可移植性操作系統(tǒng)界面(POSIX)。 他

3、也發(fā)展出一套新的IPC接口.Linux 本身支持POSIX接口.因此也支持POSIX的IPC接口l最初Unix IPC包括:管道、FIFO、信號 , System V IPC包括:System V消息隊列、System V信號燈、System V共享內存區(qū) , Posix IPC包括: Posix消息隊列、Posix信號燈、Posix共享內存區(qū)。l System V IPC通常在多個操作系統(tǒng)均實現(xiàn),包括一般的嵌入式Linux系統(tǒng),因此本課程主要介紹system V IPCLinux 培培訓訓Linux 的IPCLinux 培培訓訓lSystemV IPC指以下三種類型的IPC:SystemV消

4、息隊列 sys/msg.hSystemV信號燈 sys/sem.hSystemV共享內存區(qū) sys/shm.hl創(chuàng)建或打開函數創(chuàng)建或打開函數msgget,semget,shmgetl控制操作函數控制操作函數msgctl,semctl,shmctll操作函數操作函數 msgsnd,msgrcv,semop,shmat,shmdtLinux 培培訓訓System V關鍵字l每一個System V 對象(消息隊列,共享內存和信號量)創(chuàng)建時,需要的第一個參數是整數的Key值,頭文件把key_t定義為一個整數lSystem V 創(chuàng)建對象時假設進行IPC通訊雙方都取了相同的key值.這樣將雙方關聯(lián)起來l生

5、成key的方法有三種雙方直接設置為一個相同的整數為key值用IPC_PRIVA讓系統(tǒng)自動產生一個key值,用ftok函數將一個路徑轉換為key值Linux 培培訓訓ftok函數lftok函數把一個已存在的路徑名和一個整數標識符轉換成一個key_t值,稱為IPC鍵(IPC key):#include key_t ftok(const char *pahtname, int id);l如果pathname不存在,或者對調用進程不可訪問,ftok返回-1 l不能保證兩個不同的路徑名與同一個id值的組合產生不同的鍵。 l用于產生鍵的pahtname不能是服務器存活期間由它反復創(chuàng)建并刪除的文件,否則會導

6、致ftok多次調用返回不同的值 Linux 培培訓訓System V IPC的類型l報文(Message)隊列(消息隊列):消息隊列是消息的鏈接表,包括Posix消息隊列system V消息隊列。有足夠權限的進程可以向隊列中添加消息,被賦予讀權限的進程則可以讀走隊列中的消息。消息隊列克服了信號承載信息量少,管道只能承載無格式字節(jié)流以及緩沖區(qū)大小受限等缺點。 l共享內存:使得多個進程可以訪問同一塊內存空間,是最快的可用IPC形式。是針對其他通信機制運行效率較低而設計的。往往與其它通信機制,如信號量結合使用,來達到進程間的同步及互斥。l信號量(semaphore):主要作為進程間以及同一進程不同線

7、程之間的同步手段。 Company nameLinux培培訓訓主講人:主講人:肖勇軍肖勇軍桂電嵌入式交流群:156619189Linux 培培訓訓消息隊列l(wèi)消息隊列就是一個消息的鏈表。可以把消息看作一個記錄,具有特定的格式以及特定的優(yōu)先級。對消息隊列有寫權限的進程可以向中按照一定的規(guī)則添加新消息;對消息隊列有讀權限的進程則可以從消息隊列中讀走消息。 l消息隊列能夠克服早期unix通信機制的一些缺點 ,如數據量小,沒有實時性Linux 培培訓訓消息隊列(2)l消息隊列消息通常要以一個long mtype放在消息開始, mtype成員代表消息類型,從消息隊列中讀取消息的一個重要依據就是消息的類型s

8、truct msgbuf long mtype; char mtext1; ; l消息隊列與管道以及有名管道相比,具有更大的靈活性 它提供有格式字節(jié)流,有利于減少開發(fā)人員的工作量 消息具有類型,在實際應用中,可作為優(yōu)先級使用。這兩點是管道以及有名管道所不能比的 消息隊列可以在幾個進程間復用,而不管這幾個進程是否具有親緣關系,這一點與有名管道很相似;但消息隊列是隨內核持續(xù)的,與有名管道(隨進程持續(xù))相比,生命力更強,應用空間更大。 Linux 培培訓訓消息隊列編程l頭文件#include #include #include lmsgget打開或創(chuàng)建消息隊列int msgget(key_t key

9、, int msgflg) ;返回線隊列IDlmsgrcv從隊列接收消息int msgrcv(int msqid, struct msgbuf *msgp, int msgsz, long msgtyp, int msgflg); lmsgsnd 向隊列發(fā)送消息int msgsnd(int msqid, struct msgbuf *msgp, int msgsz, int msgflg); lmsgctl 發(fā)送隊列控制命令msgctl(int msqid, int cmd, struct msqid_ds *buf); 共有三種cmd操作:IPC_STAT、IPC_SET 、IPC_RMID

10、。 Linux 培培訓訓消息隊列數據結構l對于系統(tǒng)中的每個System V消息隊列,內核維護一個如下的結構:struct msqid_ds struct ipc_perm msg_perm; /* operation permission struct */ struct msg *msg_first; /* ptr to first message on q */ struct msg *msg_last; /* ptr to last message on q */ unsigned short msg_cbytes; /* current # bytes on q */ msgqnum_

11、t msg_qnum; /* # of messages on q */ msglen_t msg_qbytes; /* max # of bytes on q */ 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 */;Linux 培培訓

12、訓msgget函數 l#include lint msgget(key_t key, int oflag);返回:成功時為非負標識符,出錯時為-1用于創(chuàng)建一個新的SystemV消息隊列或訪問一個已經存在的消息隊列。l參數key和oflag的說明見前。lOflag :取值取值,IPC_CREAT 創(chuàng)建新對象成功,IPC_EXCL檢查新對象l返回值是一個整數標識符,其他三個msg函數用它來指代該隊列。l當創(chuàng)建一個消息隊列時,msqid_ds結構的如下成員被初始化:msg_perm結構的uid和cuid被設置為當前進程的有效用戶ID,gid和cgid被設置為當前用戶的有效組ID; oflag中的讀寫

13、權限位存放在msg_perm.mode中; msg_qnum、msg_lspid、msg_lrpid、msg_stime和msg_rtime被置為0; msg_ctime被設置成當前時間; msg_qbytes被設置為系統(tǒng)限制值。 Linux 培培訓訓msgsnd函數 l#include lint msgsnd(int msgid, const void *ptr, size_t length, int flag);l返回:成功時為0,出錯時為-1l該函數用于往消息隊列上放置一個消息。lmsgid是msgget返回的標識符,ptr是一個結構指針,該結構有如下的模板:struct msgbuf

14、long mtype; /* message type, must be 0 */ char mtext 1 ; /* message data */;l消息類型mtype必須大于0,因為非正消息類型有特殊的指示作用。llength參數以字節(jié)為單位指定待發(fā)送消息的長度。這是位于長整數消息類型之后的用戶自定義數據的長度,該長度可以是0。lflag參數可以是0,也可以是IPC_NOWAIT。IPC_NOWAIT標志使得msgsnd調用非阻塞。當有如下情形之一時:在指定的隊列中已經有太多的字節(jié)(對應msqid_ds結構中的msg_qbytes值); 在系統(tǒng)范圍存在太多的消息。 若設置了IPC_NOW

15、AIT,則msgsnd立即返回,返回一個EAGAIN錯誤。若未指定該標志,則msgsnd阻塞,直到具備存放新消息的空間; 有msgid標識的消息隊列被刪除,此時返回EIDRM錯誤; 被信號中斷,此時返回EINTR錯誤。Linux 培培訓訓msgrcv函數 l#include lssize_t msgrcv(int msqid, void *ptr, size_t length, long type, int flag);l返回:成功時為讀入緩沖區(qū)中數據的字節(jié)數,出錯時為-1l該函數從某個消息隊列中讀出一個消息。lptr參數指定所接收消息的存放位置。跟msgsnd一樣,該指針指向緊挨在真正的消息

16、數據之前返回的長整數類型字段。llength指定由ptr指向的緩沖區(qū)中數據部分的大小。這是該函數能返回的最大數據量。該長度不包含長整數類型字段。ltype指定希望從所給定的隊列中讀出什么樣的消息:type為0,返回隊列中第一個消息。每個消息隊列是作為一個FIFO鏈表維護的,所以返回的是隊列中最早的消息。 type大于0,返回其類型值為type的第一個消息。 type小于0,返回其類型值小于或等于type參數的絕對值的消息中類型值最小的第一個消息。 lflag參數指定所請求的消息不在隊列中時怎么辦。在沒有消息時,若設置了IPC_NOWAIT標志,則函數立即返回一個ENOMSG錯誤;否則,調用者阻

17、塞直到如下某個時間發(fā)生:l有一個所請求類型的消息可獲??; l由msqid標識的消息隊列被刪除,此時返回個EIDRM錯誤; l被某個捕獲的信號中斷,此時返回EINTR錯誤。 Linux 培培訓訓msgctl函數 l#include lint msgctl(int msqid, int cmd, struct msqid_ds *buf);l返回:成功時為0,出錯時為-1l該函數提供在一個消息隊列上的各種控制操作。lmsgctl提供三個命令:IPC_RMID:從系統(tǒng)中刪除由msqid指定的消息隊列。當前在該隊列上的任何消息都被丟棄。此時。第三個參數忽略不用。 IPC_SET:給指定的消息隊列設置其

18、msqid_ds結構的以下四個成員:msg_perm.uid、msg_perm.gid、msg_perm.mode和msg_perm.qbytes。它們的值來自buff指向的結構中的相應成員。 IPC_STAT:通過buff參數給調用者返回所指定消息隊列中的當前msqid_ds結構。Linux 培培訓訓消息隊列打開l如果沒有調用 msgctl(semid,IPC_RMID,0)刪除消息隊列,則消息隊列一直存在內核中,即便是創(chuàng)建進程已經退出也是如此,這個用ipcs可以看到l如果對一個已經創(chuàng)建的消息隊列的路徑再次創(chuàng)建消息隊列,通常都會出錯.因此可以采用一種保險的寫法/* 首先查詢這個隊列是否創(chuàng)建,

19、如創(chuàng)建直接用它*/if(msgid =msgget(key,IPC_EXCL|0666) = -1)/*沒有創(chuàng)建才去創(chuàng)建這個消息隊列*/msgid=msgget(key,IPC_CREAT|IPC_EXCL|00666);if(msgid=-1) printf(msg create errorn); return;l其它對象也用這樣打開方法Company nameLinux培培訓訓主講人:主講人:肖勇軍肖勇軍桂電嵌入式交流群:156619189Linux 培培訓訓信號量l信號量與其他進程間通信方式不大相同,它主要提供對進程間共享資源訪問控制機制。 l信號量相當是一個全局的整數變量,這個變量只能

20、用原子操作來改變值l信號燈與其它進程間通信方式有所不同,它主要用于進程間同步。通常所說的系統(tǒng)V信號燈實際上是一個信號燈的集合,可用于多種共享資源的進程間同步。每個信號燈都有一個值,可以用來表示當前該信號燈代表的共享資源可用(available)數量,l如果一個進程要申請共享資源,那么就從信號燈值中減去要申請的數目,如果當前沒有足夠的可用資源,進程可以睡眠等待,也可以立即返回。當進程要申請多種共享資源時,linux可以保證操作的原子性,即要么申請到所有的共享資源,要么放棄所有資源,這樣能夠保證多個進程不會造成互鎖。 Linux 培培訓訓信號量集的數據結構lSystemV信號燈是信號燈集的概念:一

21、個或多個信號燈構成一個集合。對于系統(tǒng)每個信號燈集,內核維護如下的一個結構:struct semid_ds struct ipc_perm sem_perm; /* operation permission struct */ struct sem *sem_base; /* ptr to first semaphore in set */ unsigned short sem_nsems; /* # of semaphores in set */ time_t sem_otime; /* last semop time */ time_t sem_ctime; /* last change t

22、ime */;l當前信號燈集中的每個信號燈對應一個sem結構。定義如下:struct sem signed short semval; /* semaphore text map address */ pid_t sempid; /* pid of last operation */ unsigned short semncnt; /* # awaiting semval cval */ unsigned short semzcnt; /* # awaiting semval = 0 */;Linux 培培訓訓關于關于P原語原語lP原語:原語:P是荷蘭語Proberen(測試)的首字母。為阻塞

23、原語,負責把當前進程由運行狀態(tài)轉換為阻塞狀態(tài),直到另外一個進程喚醒它。操作為:申請一個空閑資源(把信號量減1),若成功,則退出;若失敗,則該進程被阻塞;P原語的操作過程lsem減1;l若sem減1后仍大于或等于零,則進程繼續(xù)執(zhí)行;l若sem減1后小于零,則該進程被阻塞后進入與該信號相對應的隊列中,然后轉進程調度。System V 實現(xiàn)代碼 int p(int semid) struct sembuf sops=0,+1,IPC_NOWAIT; return (semop(semid,&sops,1);Linux 培培訓訓關于關于V原語原語lV原語V是荷蘭語Verhogen(增加)的首字

24、母。為喚醒原語,負責把一個被阻塞的進程喚醒,它有一個參數表,存放著等待被喚醒的進程信息。操作為:釋放一個被占用的資源(把信號量加1),如果發(fā)現(xiàn)有被阻塞的進程,則選擇一個喚醒之V原語的操作過程lsem加1; l若相加結果大于零,則進程繼續(xù)執(zhí)行; l 若相加結果小于或等于零,則從該信號的等待隊列中喚醒一等待進程,然后再返回原進程繼續(xù)執(zhí)行或轉進程調度。 System V 實現(xiàn)代碼int v(int semid) struct sembuf sops=0,-1,IPC_NOWAIT; return (semop(semid,&sops,1);Linux 培培訓訓信號量的處理流程信號量的處理流程

25、 l用到頭文件#include #include #include lsemget創(chuàng)建或打開一個信號量int semget(key_t key, int nsems, int semflg) lSemop()對信號量 +1 或 -1 或測試是否為0 int semop(int semid, struct sembuf *sops, unsigned nsops); linux可以增加或減小信號量的值,相應于對共享資源的釋放和占有 lsemctl 對信號量進行各種控制int semctl(int semid,int semnum,int cmd,union semun arg) Linux 培培

26、訓訓semget函數 l#include lint semget(key_t key, int nsems, int oflag);l返回:成功時為非負標識符,出錯時為-1l創(chuàng)建一個信號燈集或訪問一個已存在的信號燈集。l返回值是信號燈標識符,供其他信號燈函數使用。lnsems是集合中的信號燈數。如果不是創(chuàng)建一個信號燈集,而只是訪問已存在的集合,則該參數可以指定為0。一旦創(chuàng)建完畢一個信號燈集,就不能改變其中的信號燈數。l當實際操作為創(chuàng)建一個新的信號燈集時,semid_ds結構的以下成員將被初始化:sem_perm結構的uid和cuid被設置為調用進程的有效用戶ID,gid和cgid被設置為調用進

27、程的有效組ID; oflag參數中的讀寫權限存入sem_perm.mode中; sem_otime被設置為0,sem_ctime被置為當前時間; sem_nsems被置為nsems參數的值; 與該集合中每個信號燈關聯(lián)的各個sem結構并不初始化。這些結構必須是在以SETVAL或SETALL命令調用semctl時初始化的。Linux 培培訓訓信號量創(chuàng)建問題lSystemV信號燈的創(chuàng)建和初始化需兩次函數調用是一個致命的缺陷,這會導致競爭狀態(tài)的出現(xiàn)。l解決競爭狀態(tài)的方法是:當semget創(chuàng)建一個新的信號燈集時,其semid_ds結構的sem_otime成員保證被設置為0。該成員只是在semop調用成功

28、時才被設置為當前值。在調用semget進行訪問而不是創(chuàng)建時,以IPC_STAT命令調用semctl,然后等待sem_otime變?yōu)榉橇阒?。到時就可斷定該信號燈已經被初始化,而且對它初始化的進程已成功完成semop調用。所以,創(chuàng)建該信號燈集的進程必須初始化它的值,而且必須在任何其他進程可以使用該信號燈集之前調用semop。l這樣將會造成程序相當復雜Linux 培培訓訓semop函數 l#include lint semop(int semid, struct sembuf *opsptr, size_t nops);l返回:成功時為0,出錯時為-1l對一個或多個信號燈進行操作。lopsptr指向

29、如下結構模板的數組(該結構可能不止如下幾個成員):struct sembuf shrot sem_num; /* semaphore number:0,1,.,nsems-1 */ short sem_op; /* semaphore operation: 0 */ short sem_flg; /* operation flags:0,IPC_NOWAIT,SEM_UNDO */;lnops參數指出結構數組中元素的個數。每個元素給目標信號燈集中某個信號燈指定一個操作。特定的信號燈由sem_num指定;sem_op指定特定的操作;sem_flg指定非阻塞(IPC_NOWAIT)、恢復等標志。在

30、阻塞、非阻塞情況下返回的錯誤情況與其他SystemV IPC相同。lsemop函數由內核保證原子的執(zhí)行,內核或者完成所有操作,或者什么也不做。lsemop操作的具體描述:如果sem_op是正數,其值就加到semval(信號燈的當前值)上,這對應于釋放由某個信號燈控制的資源。如果指定了SEM_UNDO標志,就從相應信號燈的semadj值中減掉sem_op的值。 如果sem_op是0,那么調用者希望等待到semval變?yōu)?,如果semval已經是0,則立即返回;如果semval不為0,相應信號燈的semzcnt(等待semval變?yōu)?的線程數)值就加1,調用線程阻塞到semval變?yōu)?(那時sem

31、zcnt再減1)。若指定了IPC_NOWAIT,則調用線程不會睡眠,返回EAGAIN。 如果sem_op是負數,那么調用者希望等待semval變?yōu)榇笥诨虻扔趕em_op的絕對值,這對應于分配資源。如果semval大于或等于sem_op的絕對值,則從semval中減掉sem_op的絕對值,如果指定了SEM_UNDO,那么sem_op的絕對值就加到相應信號燈的semadj值上。如果semval小于sem_op的絕對值,相應信號燈的semncnt值就加1,調用線程阻塞直到semval變?yōu)榇笥诨虻扔趕em_op的絕對值。若指定了IPC_NOWAIT,則調用線程不會睡眠,返回EAGAIN。 lsemad

32、j稱為指定信號燈針對調用進程的調整值。當調用進程終止時,semadj的值就加到相應信號燈的semval上。若調用進程對某個信號燈的全部操作都指定SEM_UNDO標志,則該進程終止時,該信號燈的值就會變得像根本沒有運行過該進程一樣,這就是復舊(undo)的本意。Linux 培培訓訓semop的調用問題lsemop采用復雜的信號燈集做參數,因此造成程序調用變得復雜.l信號燈的值加1,或值減1都在semop完成,相當于加鎖或解鎖都是有一個函數完成,這也是與其它互質量等其它同步機制不一樣的地方l一般是將其封裝成P,V原語的函數來操作/* 申請資源,用P原語*/int semaphore_wait_p(

33、int sem_id) struct sembuf sb;sb.sem_num = 0;sb.sem_op = -1;sb.sem_flg = SEM_UNDO;if (semop(sem_id, &sb, 1) = -1) fprintf(stderr, semaphore_p failedn);return (-1);return 0;/* 釋放或分配資源用,用V原語 */int semaphore_signal_v(int sem_id) struct sembuf sb;sb.sem_num = 0;sb.sem_op = 1;sb.sem_flg = SEM_UNDO;if

34、(semop(sem_id, &sb, 1) = -1) fprintf(stderr, semaphore_v failedn);return (-1);return 0;Linux 培培訓訓semctl函數 l#include lint semctl(int semid, int semnum, int cmd, /* union arg */);l返回:成功時為非負值,出錯時為-1l對一個信號燈執(zhí)行各種控制操作。lsemnum標識某個信號燈,semnum僅僅用于GETVAL、SETVAL、GETNCNT、GETZCNT和GETPID命令。l第四個參數是可選的,它依賴于第三個參數c

35、md。它是一個聯(lián)合:union semun int val; /* used for SETVAL only */ struct semid_ds *buf; /* used fro IPC_SET and IPC_STAT */ ushort *array; /* used for GETALL and SETALL */;l該聯(lián)合沒有出現(xiàn)在任何系統(tǒng)頭文件中,由應用程序聲明。而且它是以值傳遞的,而不是以引用傳遞的。Linux 培培訓訓semop命令選項lGETVAL:把semval的當前值作為函數返回值返回。 lSETVAL:把semval設置為arg.val。如果操作成功,那么相應信號燈在

36、所在進程中的調整值(semadj)將被置為0。 lGETPID:把sempid的當前值作為函數值返回。 lGETNCNT:把semncnt的當前值作為函數值返回。 lGETZCNT:把semzcnt的當前值作為函數值返回。 lGETALL:返回所指定信號燈集的每個成員的semval值。這些值通過arg.array指針返回。函數本身返回值為0。注意,調用者必須分配足夠容納所指定信號燈集中所有成員的semval值的一個unsigned short整數數組,然后把arg.array設置成指向這個數組。 lSETALL:設置所指定信號燈集中每個成員的semval值。這些值通過arg.array數組指定

37、。 lIPC_RMID:把由semid指定的信號燈集從系統(tǒng)中刪除。 lIPC_SET:設置semid_ds結構中的以下三個成員:sem_perm.uid、sem_perm.gid和sem_perm.mode。這些值來自由arg.buf參數指向的結構中相應成員。semid_ds中的sem_ctime成員也被設置為當前值。 lIPC_STAT:通過arg.buf參數返回當前的semid_ds結構。注意,調用者必須首先分配一個semid_ds結構,并把arg.buf設置為指向這個結構。Company nameLinux培培訓訓主講人:主講人:肖勇軍肖勇軍桂電嵌入式交流群:156619189Linux

38、 培培訓訓共享內存數據表示l對于每個System V共享內存區(qū),內核維護如下的信息結構:struct shmid_ds struct ipc_perm shm_perm; /* operation permission struct */ 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; /* current # attached */ shmat_t

39、shm_cnattch; /* in-core # attached */ time_t shm_atime; /* last shmat time */ time_t shm_dtime; /* last shmdt time */ time_t shm_ctime; /* last change time */;Linux 培培訓訓System V 共享內存使用流程l使用頭文件#include #include lshmget() 獲得共享內存區(qū)域的ID 如果不存在指定的共享區(qū)域就創(chuàng)建相應的區(qū)域。 int shmget(key_t key,int size,int shmflg); lsh

40、mat()把共享內存區(qū)域映射到調用進程的地址空間中去 這樣,進程就可以方便地對共享區(qū)域進行訪問操作。void *shmat(int shmid,const void *shmaddr,int shmflg); lshmdt()調用用來解除進程對共享內存區(qū)域的映射 int shmdt(const void *shmaddr); lShmctl()實現(xiàn)對共享內存區(qū)域的控制操作 int shmctl(int shmid,int cmd,struct shmid_ds *buf); Linux 培培訓訓shmget函數 l#include lint shmget(key_t key, size_t s

41、ize, int oflag);l返回:成功時為共享內存區(qū)對象,出錯時為-1l函數創(chuàng)建一個尚未存在的共享內存區(qū),或者訪問一個已存在的共享內存區(qū)。l返回值是共享內存區(qū)標識符,供其他函數使用。lsize參數以字節(jié)為單位指定內存的大小。當實際操作為創(chuàng)建一個新的內存區(qū)時,必須指定一個不為0的size值;如果實際操作是訪問一個已存在的共享內存區(qū),則size應為0。l當實際操作為創(chuàng)建一個新的內存區(qū)時,該內存區(qū)被初始化為size個字節(jié)的0。Linux 培培訓訓shmat函數 l#include lvoid * shmat(int shmid, const void *shmaddr, int flag);l

42、返回:成功時為映射區(qū)的其始地址,出錯時為-1l調用shmat將共享內存區(qū)附接到調用進程的地址空間。lshmid是shmget的返回值。shmat的返回值是所指定的共享內存區(qū)在調用進程內的起始地址。確定此地址的規(guī)則如下:如果shmaddr是空指針,則系統(tǒng)替調用者選擇地址。這是推薦(也是可移植性最好的)方法。 如果shmaddr非空,則返回地址取決于調用者是否給flag參數指定了SHM_RND值。如果SHM_RND沒有指定,則共享內存區(qū)附接到由shmaddr指定的地址;若指定SHM_RND,則附接到由shmaddr指定的地址向下舍入一個SHMLBA常值。LBA代表“低端邊界地址(lower bou

43、ndary address)”。 lflag參數可以指定SHM_RDONLY值,它限定只讀訪問。Linux 培培訓訓shmdt函數 l#include lint shmdt(const void *shmaddr);l返回:成功時為0,出錯時為-1l調用shmdt斷開與共享內存區(qū)的連接。l當一個進程終止時,它的所有當前附接著的共享內存區(qū)都自動斷接掉。Linux 培培訓訓shmctl函數 l#include lint shmctl(int shmid, int cmd, struct shmid_ds *buff);l返回:成功時為0,出錯時為-1l函數提供三個命令:IPC_RMID:從系統(tǒng)中刪

44、除由shmid標識的共享內存區(qū)并拆除它。 IPC_SET:給所指定的共享內存區(qū)設置其shmid_ds結構的以下三個成員:shm_perm.uid、shm_perm.gid和shm_perm.mode,它們的值來自參數中的相應成員。shm_ctime的值用當前時間替換。 IPC_STAT:向調用者返回所指定共享內存區(qū)的當前shmid_ds結構。 Linux 培培訓訓關于System V的維護命令l可以用ipcs命令查看system V對象l用ipcrm可以刪除system V 對象ipcrm sem 196632 l刪除semid 為196632的信號量ipcrm shm 12395l刪除shm

45、id 為12395的共享內存ipcrm msg 234l刪除msgid為 234的消息隊列Company nameLinux培培訓訓主講人:主講人:肖勇軍肖勇軍桂電嵌入式交流群:156619189Linux 培培訓訓兩大類應用接口區(qū)別lSystem V IPC存在時間比較老,許多系統(tǒng)都支持,而Posix IPC是新出的標準.很多嵌入式平臺只支持System V 的接口lSystem V的接口相對復雜,而POSIX比較簡單,優(yōu)先選擇后者.參見system V的信號量和Posix信號量的操作比較lPOSIX IPC是線程安全的lSystem V內置在glibc中,因此所有使用glibc庫的環(huán)境都可

46、以使用,POSIX IPC的使用必須鏈接librt.XXX庫,(即使用-lrt參數)Linux 培培訓訓POSIX 消息隊列接口名稱接口名稱目的目的mq_open(3RT) 連接到以及創(chuàng)建(可選)命名消息隊列連接到以及創(chuàng)建(可選)命名消息隊列mq_close(3RT) 結束到開放式消息隊列的連接結束到開放式消息隊列的連接mq_unlink(3RT) 結束到開放式消息隊列的連接,并在最后一個進程關閉此隊結束到開放式消息隊列的連接,并在最后一個進程關閉此隊列時將其刪除列時將其刪除mq_send(3RT) 將消息放入隊列將消息放入隊列mq_receive(3RT) 在隊列中接收(刪除)最早且優(yōu)先級最

47、高的消息在隊列中接收(刪除)最早且優(yōu)先級最高的消息mq_notify(3RT) 通知進程或線程消息已存在于隊列中通知進程或線程消息已存在于隊列中mq_setattr(3RT), mq_getattr(3RT) 設置或獲取消息隊列屬性設置或獲取消息隊列屬性Linux 培培訓訓POSIX消息隊列使用l使用頭文件使用頭文件mqueue.hl隊列數據結構隊列數據結構 mqd_tl打開隊列打開隊列mqd_t mq_open(const char *name, int oflag, /* unsigned long mode, mq_attr attr */ .); l關閉隊列關閉隊列Linux 培培訓訓

48、POSIX 信號量 lPosix信號量的使用遠比System V信號量簡單.而且支持多種操作系統(tǒng).lsem_open(3RT) 連接到以及創(chuàng)建(可選)命名信號量連接到以及創(chuàng)建(可選)命名信號量lsem_init(3RT) 初始化信號量結構(在調用程序內部,因此不是命名信號量)初始化信號量結構(在調用程序內部,因此不是命名信號量)lsem_close(3RT) 結束到打開信號量的連接結束到打開信號量的連接lsem_unlink(3RT) 結束到打開信號量的連接,并在最后一個進程關閉此信號量時將其刪除結束到打開信號量的連接,并在最后一個進程關閉此信號量時將其刪除lsem_destroy(3RT)

49、銷毀信號量結構(在調用程序內部,因此不是命名信號量)銷毀信號量結構(在調用程序內部,因此不是命名信號量)lsem_getvalue(3RT) 將信號量的值復制到指定整數中將信號量的值復制到指定整數中l(wèi)sem_wait(3RT)、sem_trywait(3RT) 當其他進程擁有信號量時進行阻塞,或者當其他進程擁有信號量時返回錯誤當其他進程擁有信號量時進行阻塞,或者當其他進程擁有信號量時返回錯誤lsem_post(3RT) 遞增信號量計數遞增信號量計數Company nameLinux培培訓訓主講人:主講人:肖勇軍肖勇軍桂電嵌入式交流群:156619189Linux 培培訓訓共享內存l共享內存可以

50、說是最有用的進程間通信方式,也是最快的IPC形式。兩個不同進程A、B共享內存的意思是,同一塊物理內存被映射到進程A、B各自的進程地址空間。進程A可以即時看到進程B對共享內存中數據的更新,反之亦然。l由于多個進程共享同一塊內存區(qū)域,必然需要某種同步機制,互斥鎖和信號量都可以。l共享內存通信的一個顯而易見的好處是效率高,因為進程可以直接讀寫內存,而不需要任何數據的拷貝。對于像管道和消息隊列等通信方式,則需要在內核和用戶空間進行四次的數據拷貝,而共享內存則只拷貝兩次數據1:一次從輸入文件到共享內存區(qū),另一次從共享內存區(qū)到輸出文件。 l共享內存廣泛被應用數據庫系統(tǒng)實現(xiàn)到驅動程序各種應用 Linux 培

51、培訓訓共享內存的實現(xiàn)lLinux有三種共享內存實現(xiàn)機制mmap()System V 共享內存Posix 共享內存前兩者較為常用l系統(tǒng)調用mmap()通過映射一個普通文件實現(xiàn)共享內存。系統(tǒng)V則是通過映射特殊文件系統(tǒng)shm中的文件實現(xiàn)進程間的共享內存通信。也就是說,每個共享內存區(qū)域對應特殊文件系統(tǒng)shm中的一個文件(這是通過shmid_kernel結構聯(lián)系起來的)Linux 培培訓訓mmaplmmap函數把一個文件或一個Posix共享內存區(qū)對象映射到調用進程的地址空間。使用該函數有三個目的: 1.使用普通文件以提供內存映射I/O 2.使用特殊文件以提供匿名內存映射。 3.使用shm_open以提供

52、無親緣關系進程間的Posix共享內存區(qū) Linux 培培訓訓mmap-創(chuàng)建一個共享內存區(qū)名稱::mmap功能:把I/O文件映射到一個存儲區(qū)域中頭文件:#include 函數原形:void *mmap(void *addr,size_t len,int prot,int flag,int filedes,off_t off);參數:addr 指向映射存儲區(qū)的起始地址,addr參數用于指定映射存儲區(qū)的起始地址。通常將其設置為NULL,這表示由系統(tǒng)選擇該映射區(qū)的起始地址。len 映射的字節(jié)prot 對映射存儲區(qū)的保護要求flag flag標志位filedes 要被映射文件的描述符, 在映射該文件到一

53、個地址空間之前,先要打開該文件。len是映射的字節(jié)數。off 要映射字節(jié)在文件中的起始偏移量,通常將其設置為0。 返回值:若成功則返回映射區(qū)的起始地址,若出錯則返回MAP_FAILEDLinux 培培訓訓mmap參數說明l prot參數說明對映射存儲區(qū)的保護要求??蓪rot參數指定為PROT_NONE,或者是PROT_READ(映射區(qū)可讀),PROT_WRITE(映射區(qū)可寫),PROT_EXEC(映射區(qū)可執(zhí)行)任意組合的按位或,也可以是PROT_NONE(映射區(qū)不可訪問)。對指定映射存儲區(qū)的保護要求不能超過文件open模式訪問權限。 l flag參數影響映射區(qū)的多種屬性: MAP_FIXED

54、 返回值必須等于addr.因為這不利于可移植性,所以不鼓勵使用此標志。MAP_SHARED 這一標志說明了本進程對映射區(qū)所進行的存儲操作的配置。此標志指定存儲操作修改映射文件。MAP_PRIVATE 本標志導致對映射區(qū)建立一個該映射文件的一個私有副本。所有后來對該映射區(qū)的引用都是引用該副本,而不是原始文件。要注意的是必須指定MAP_FIXED或MAP_PRIVATE標志其中的一個,指定前者是對存儲映射文件本身的一個操作,而后者是對其副本進行操作。Linux 培培訓訓unmmap取消一個共享內存名稱::munmap功能:解除存儲映射頭文件:#include 函數原形:int munmap(cad

55、dr_t addr,size_t len);參數:addr 指向映射存儲區(qū)的起始地址,其中addr參數是由mmap返回的地址 ,len 映射的尺寸。再次訪問這些地址導致向調用進程產生一個SIGSEGV信號。 返回值:若成功則返回0,若出錯則返回-1Linux 培培訓訓名稱::msync功能:同步文件到存儲器頭文件:#include 函數原形:int msync(void *addr,size_t len,int flags);參數:addr 指向映射存儲區(qū)的起始地址len 映射的字節(jié)prot flags返回值:若成功則返回0,若出錯則返回-1Linux 培培訓訓posix共享內存lposix共

56、享內存區(qū)涉及兩個步驟:1、指定一個名字參數調用shm_open,以創(chuàng)建一個新的共享內存區(qū)對象或打開一個以存在的共享內存區(qū)對象。2、調用mmap把這個共享內存區(qū)映射到調用進程的地址空間。傳遞給shm_open的名字參數隨后由希望共享該內存區(qū)的任何其他進程使用。Linux 培培訓訓shm_open打開共享內存名稱::shm_open功能:打開或創(chuàng)建一個共享內存區(qū)頭文件:#include 函數原形:int shm_open(const char *name,int oflag,mode_t mode);參數:name 共享內存區(qū)的名字cflag 標志位, oflag參數必須含有O_RDONLY和O_RDWR標志,還可以指定如下標志:O_CREAT,O_EXCL或O_TRUNC. mode 權限

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論