亚洲精品一二区_国产黄色片网站_99久久久成人国产精品_蜜臀网_国产精品一区二区三区免费_成人av中文字幕_91精品国产欧美一区二区成人

當前位置:首頁 > 嵌入式培訓 > 嵌入式學習 > 講師博文 > 進程間通信方式——共享內存

進程間通信方式——共享內存 時間:2018-09-26      來源:未知

一、進程間通信的方式

在程序的運行中,我們必定會有關于進程與進程間通信的問題。而我們的先輩早已為我們準備了關于解決這些問題的方法。這些方法主要有幾種:無名管道,有名管道,信號,消息隊列,共享內存以及信號燈(信號量)等幾種方法。其中共享內存又是其中的翹楚。這篇文章講解一下共享內存。

二、共享內存介紹

1、共享內存是一種為高效的進程間通信方式,進程可以直接讀寫內存,而不需要任何數據的拷貝。

2、為了在多個進程間交換信息,內核專門留出了一塊內存區,可以由需要訪問的進程將其映射到自己的私有地址空間。進程就可以直接讀寫這一塊內存而不需要進行數據的拷貝,從而大大提高效率。

3、由于多個進程共享一段內存,因此也需要依靠某種同步機制(信號燈)。

三、共享內存的同步

共享內存為在多個進程之間共享和傳遞數據提供了一種有效的方式。但是它并未提供同步機制,所以我們通常需要用其他的機制來同步對共享內存的訪問。我們通常是用共享內存來提供對大塊內存區域的有效訪問,同時通過傳遞小消息來同步對該內存的訪問。在第一個進程結束對共享內存的寫操作之前,并無自動的機制可以阻止第二個進程開始對它進行讀取。對共享內存訪問的同步控制必須由程序員來負責。

四、共享內存的實現

共享內存的使用包括如下步驟:

1、創建/打開共享內存

2、映射共享內存,即把指定的共享內存映射到進程的地址空間用 于訪問。

3、撤銷共享內存的映射。

4、刪除共享內存對象

五、共享內存使用的函數

#include

int shmget(key_t key, size_t size, int shmflg);

 void *shmat(int shm_id, const void *shm_addr, int shmflg);

int shmdt(const void *shm_addr);

int shmctl(int shm_id, int cmd, struct shmid_ds *buf);

1. shmget函數

int shmget(key_t key, size_t size, int shmflg);

該函數用來創建共享內存:

參數:key : 和信號量一樣,程序需要提供一個參數key,它有效地為共享內存段命名。有一個特殊的鍵值IPC_PRIVATE,它用于創建一個只屬于創建進程的共享內存,通常不會用到。

size: 以字節為單位指定需要共享的內存容量。

shmflag: 包含9個比特的權限標志,它們的作用與創建文件時使用的mode標志是一樣由IPC_CREAT定義的一個特殊比特必須和權限標志按位或才能創建一個新的共享內存段。

NOTE:權限標志對共享內存非常有用,因為它允許一個進程創建的共享內存可以被共享內存的創建者所擁有的進程寫入,同時其它用戶創建的進程只能讀取共享內存。我們可以利用這個功能來提供一種有效的對數據進行只讀訪問的方法,通過將數據放共享內存并設置它的權限,就可以避免數據被其他用戶修改。

返回值:創建成功,則返回一個非負整數,即共享內存標識;如果失敗,則返回-1。

2. shmat函數

第一次創建共享內存段時,它不能被任何進程訪問。

要想啟動對該內存的訪問,

必須將其連接到一個進程的地址空間。

這個工作由shmat函數完成:

void *shmat(int shm_id, const void *shm_addr, int shmflg);

參數:shm_id : 由shmget返回的共享內存標識。shm_add: 指定共享內存連接到當前進程中的地址位置。它通常是一個空指針,表示讓系統來選擇共享內存出現的地址。

shmflg : 是一組標志。它的兩個可能取值是:

SHM_RND, 和shm_add聯合使用,用來控制共享內存連接的地址。

SHM_RDONLY, 它使連接的內存只讀。

返回值:如果調用成功, 返回一個指向共享內存第一個字節的指針;

如果失敗,返回-1。

共享內存的讀寫權限由它的屬主(共享內存的創建者),它的訪問權限和當前進程的屬主決定。共享內存的訪問權限類似于文件的訪問權限。

3. shmdt

將共享內存從當前進程中分離。

int shmdt(const void *shm_addr);

shm_addr: shmat返回的地址指針。

成功時,返回0,

失敗時,返回-1.

NOTE:共享內存分離并未刪除它,只是使得該共享內存對當前進程不再可用。

注意:當一個進程不再需要共享內存段時,它將調用shmdt()系統調用取消這個段,但是,這并不是從內核真正地刪除這個段,而是把相關shmid_ds結構的shm_nattch域的值減1,當這個值為0時,內核才從物理上刪除這個共享段。(每有一個進程映射到這段共享內存,這個值就會加1,每次調用shmctl刪除,僅僅只是刪掉這個標記)

用完共享存儲段后,將進程和該共享存儲段脫離。這并不是從系統中刪除其標識符以及其數據結構,直到某個進程(一般是創建者server)調用shmctl(IPC_RMID)特地刪除它。

4. shmctl

共享內存的控制函數

int shmctl(int shm_id, int cmd, struct shmid_ds *buf);

shmid_ds結構至少包含以下成員:

struct shmid_ds {

uid_t shm_perm.uid;

uid_t shm_perm.gid;

mode_t shm_perm.mode;

}

參數:

shm_id : 是shmget返回的共享內存標識符。

command: 是要采取的動作,

它可以取3個值:

IPC_STAT 把shmid_ds結構中的數據設置為共享內存的當前關聯值。

IPC_SET 如果進程有足夠的權限,就把共享內存的當前關聯值設置為shmid_ds結構中給出的值。

IPC_RMID 刪除共享內存段。

buf : 是一個指針,包含共享內存模式和訪問權限的結構。

返回值:

成功時,返回0,

失敗時,返回-1。

六、代碼示例

說了這么多,又到了實戰的時候了。下面我們就用代碼來進一步了解。

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define BUFF_SIZE 1024

typedef struct {

sem_t rsem; /* sem for read */

sem_t wsem; /* sem for write */

char buf[BUFF_SIZE];

}SHM;

int do_read (SHM *pSHM);

int do_write(SHM *pSHM);

int main(int argc, char *argv[])

{

int shmid = -1;

int pid = -1;

SHM *pSHM;

int retval = 0;

/* create share memory

* IPC_PRIVATE for communication betweeen parent-child processes

* IPC_CREAT to indicate a new creation of IPC object

*/

if ((shmid = shmget(IPC_PRIVATE, sizeof(SHM), 0666)) < 0) {

perror("shmget error");

return -1;

}

printf("pid[%d] create new shmid = %d\n", getpid(), shmid);

/* attach share memory */

if ((pSHM = (SHM *)shmat(shmid, NULL, 0)) == (void *)-1) {

perror("shmat error");

retval = -1;

goto _exit_point;

}

printf("parent: shmaddr = %p\n", pSHM);

/* set 3rd param of sem_init - pshared - as nonzero,

* then the semaphore is shared between processes

*/

if (sem_init(&(pSHM->rsem), 1, 0) < 0) { /* read sem is init as busy */

perror("sem_init read error");

retval = -1;

goto _exit_point;

}

if (sem_init(&(pSHM->wsem), 1, 1) < 0) { /* write sem is init as free */

perror("sem_init write error");

retval = -1;

goto _exit_point;

}

if ((pid = fork()) < 0) {

perror("fork error");

retval = -1;

goto _exit_point;

}else if (pid == 0) { /* child */

/* After a fork the child inherits the attached

* shared memory segments.

*/

retval = do_read(pSHM);

}else{ /* parent */

usleep(5000); /* just to make output looks better */

retval = do_write(pSHM);

/* detach the share memory */

if (shmdt(pSHM) < 0) {

perror("shmdt error");

retval = -1;

goto _exit_point;

}

/* wait child process */

wait(NULL);

}

_exit_point:

if (pid != 0) { /* child will not handle this */

if (shmid > 0) {

/* IPC_RMID just mark the share memory presented by

* the shmid should be deleted, but the deletion

* happens only when no proces is attached

*/

if (shmctl(shmid, IPC_RMID, NULL) < 0) {

perror("shmctl error");

}

}

}

return retval;

}

int do_write(SHM *pSHM)

{

while (1) {

/* try to lock for write */

if (sem_wait(&(pSHM->wsem)) < 0) {

perror("sem_wait error");

break;

}

printf(">");

/* access the share memory and write data which are got

* from stdin

*/

fgets(pSHM->buf, BUFF_SIZE, stdin);

/* eat the LF and complete the string */

pSHM->buf[strlen(pSHM->buf) - 1] = '\0';

/* allow read */

if (sem_post(&(pSHM->rsem)) < 0) {

perror("sem_post error");

break;

}

if (strncmp(pSHM->buf, "quit", 4) == 0) {

break;

}

usleep(500);

}

return 0;

}

int do_read(SHM *pSHM)

{

while(1) {

/* try to lock for read */

if (sem_wait(&(pSHM->rsem)) < 0) {

perror("sem_wait error");

break;

}

/* read the share memory buffer and print the content out */

printf("read buf: %s\n", pSHM->buf);

/* test the buf inside read lock */

if (strncmp(pSHM->buf, "quit", 4) == 0) {

/* detach the share memory */

if(shmdt(pSHM) < 0) {

perror("shmdt error");

return -1;

}

break;

}

/* allow write */

if (sem_post(&(pSHM->wsem)) < 0) {

perror("sem_post error");

break;

}

}

return 0;

}

大家可以看到,在這個程序中加入了信號燈的代碼。主要是因為兩個進程在調用同一個內存空間所以需要加入信號燈以達到同步或互斥的目的。

七、共享內存的優缺點

1、優點:我們可以看到使用共享內存進行進程間的通信真的是非常方便,而且函數的接口也簡單,數據的共享還使進程間的數據不用傳送,而是直接訪問內存,也加快了程序的效率。同時,它也不像匿名管道那樣要求通信的進程有一定的父子關系。

2、缺點:共享內存沒有提供同步的機制,這使得我們在使用共享內存進行進程間通信時,往往要借助其他的手段來進行進程間的同步工作。

上一篇:Ubuntu的網絡配置

下一篇:消息隊列

熱點文章推薦
華清學員就業榜單
高薪學員經驗分享
熱點新聞推薦
前臺專線:010-82525158 企業培訓洽談專線:010-82525379 院校合作洽談專線:010-82525379 Copyright © 2004-2022 北京華清遠見科技集團有限公司 版權所有 ,京ICP備16055225號-5,京公海網安備11010802025203號

回到頂部

主站蜘蛛池模板: 精品一区二区三区在线观看 | 日韩在线不卡一区在线观看 | 国产精品久久久久毛片 | 天天色天天综合网 | 国产自产视频 | 国产一级持黄大片99久久 | 色综合天天综合网国产人 | 天天操人人 | 国产成人a视频在线观看 | 久久久久国产一级毛片高清版 | 日本午夜在线观看 | 久久91久久91精品免费观看 | 青青影院在线观看 | 日日摸碰夜夜爽 | 日韩福利视频精品专区 | 天天摸天天操 | 人操人爱 | 日本大片免a费观看在线 | 人人澡人人澡人人看 | 免费成人黄色 | 午夜久草 | 精品一区二区三区在线观看 | 欧美视频在线观看免费精品欧美视频 | 2019亚洲日韩新视频 | 亚洲视频在线免费观看 | 一区二区三区波多野结衣 | 日本成人片网站 | 欧美一区二区三区视频在线观看 | 看视频免费 | 99亚洲精品高清一二区 | 久久丁香视频 | 中文国产成人精品久久96 | 天天干天操 | 成人a级高清视频在线观看 成人a毛片手机免费播放 | 国产黄色片在线免费观看 | 骚碰97 | a毛片免费全部播放毛 | 国产乱人伦精品一区二区 | 黄色网址在线免费观看 | 免费观看a级毛片 | 国产午夜精品一区二区三区不卡 |