色偷偷偷亚洲综合网另类,亚洲欧美另类在线观看,欧美午夜激情在线,久久久精品一区

Hi,歡迎來到嵌入式培訓(xùn)高端品牌 - 華清遠見教育科技集團<北京總部官網(wǎng)>,專注嵌入式工程師培養(yǎng)15年!
當前位置: > 華清遠見教育科技集團 > 嵌入式學(xué)習(xí) > 講師博文 > ShareMem
ShareMem
時間:2017-01-05作者:華清遠見

前幾天上進程間通訊的課程,看到有同學(xué)對共享內(nèi)存有些不是很明白,而且在查man幫助的時候也不是很能明白系統(tǒng)對其的說明,故有了這篇文章。

共享內(nèi)存是系統(tǒng)在做進程間通訊時比較常用的IPC通訊方式之一,同時也是效率高的,但是由于其的獨特性導(dǎo)致在使用共享內(nèi)存的時候需要注意一點就是幾個進程間通訊時的互斥和同步問題,所以在使用共享內(nèi)存的時候,我們一般要對其加鎖或者加一些其他的同步機制,比如信號燈之類的。

首先看下共享內(nèi)存的數(shù)據(jù)結(jié)構(gòu):

共享內(nèi)存區(qū)的數(shù)據(jù)結(jié)構(gòu)

每個共享內(nèi)存段在內(nèi)核中維護著一個內(nèi)部結(jié)構(gòu)shmid_ds,該結(jié)構(gòu)定義在linux/shm.h中,代碼如下所示:

struct shmid_ds {
        struct ipc_perm shm_perm;/* 超作許可權(quán)數(shù)據(jù)結(jié)構(gòu)指針 */
                int         shm_segsz;        /* 共享存儲段大小 (bytes) */
                time_t         shm_atime;        /* 后調(diào)用shmat時間 */
                time_t        shm_dtime;         /* 后調(diào)用shmdt的時間 */
                time_t        shm_ctime;        /* 后調(diào)用shmctl的改變的時間 */
                unsigned short        shm_cpid;        /*創(chuàng)建者的進程ID */
                unsigned short        shm_lpid;        /* 后對共享存儲段進行操作的進程ID */
                short        shm_nattch;        /* 當前連接數(shù) */
        };

共享內(nèi)存的創(chuàng)建和操作

A:共享內(nèi)存區(qū)的創(chuàng)建

linux下使用函數(shù)shmget來創(chuàng)建一個共享內(nèi)存區(qū),或者訪問一個已經(jīng)存在的共享內(nèi)存區(qū),該函數(shù)定義如下:

#include <sys/ipc.h>
        #include <sys/shm.h>

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

返回:失敗-1, 成功返回非負的共享存儲段id。

第一個參數(shù)key是共享存儲關(guān)鍵字。它有特殊值IPC_PRIVATE表示總是創(chuàng)建一個進程私有的共享存儲段。當key值不等于IPC_PRIVATE時,shmget動作取決于后一個參數(shù)shmflg標志:

1. IPC_CREAT 單獨設(shè)置此標志,當系統(tǒng)中不存在相同key時,創(chuàng)建一個新的共享存儲段,否則返回已存在的共享存儲段。
        2. IPC_EXCL 單獨設(shè)置不起作用。與 IPC_CREAT同時設(shè)置時,當系統(tǒng)中存在相同key時,錯誤返回。保證不會打開一個已存在的共享存儲段。

如果沒有指定IPC_CREATE并且系統(tǒng)中不存在相同key值的共享存儲段,將失敗返回。

第二個參數(shù)size指明要求的共享存儲段的大小。當key指定的共享存儲段已存在時,取值范圍為0和已存在共享段大小。或簡單指定為0。成功后此函數(shù)返回共享存儲段id,同時創(chuàng)建于參數(shù)key相連的數(shù)據(jù)結(jié)構(gòu)shmid_ds。此節(jié)構(gòu)為系統(tǒng)內(nèi)部使用。

第三個參數(shù)也可以設(shè)置共享存儲段的訪問權(quán)限,用或于上面的值操作。

B:共享內(nèi)存區(qū)的操作

在使用共享內(nèi)存區(qū)之前,必須通過shmat函數(shù)將其附加到進程的地址空間,進程和地址空間就建立了連接。shmat調(diào)用成功后就返回一個共享內(nèi)存區(qū)指針,使用該指針就可以訪問共享內(nèi)存區(qū)了。

#include <sys/types.h>
        #include <sys/shm.h>

void *shmat(int shmid, const void *shmaddr, int shmflg);

返回:失敗-1并置errno, 成功返回連接的實際地址。

第一個參數(shù),必須由shmget返回的存儲段的id。

第二個參數(shù)指明共享存儲段要連接到的地址。0,系統(tǒng)為我們創(chuàng)建一個適當?shù)牡刂分怠7駝t自己指定。

第三個參數(shù)shmflg可以設(shè)成:SHM_RND, SHM_RDONLY。SHM_RND為自己指定連接地址時用。SHM_RDONLY說明此存儲段只讀。

當進程結(jié)束使用共享內(nèi)存區(qū)時,就要通過函數(shù)shmdt斷開于共享內(nèi)存區(qū)的連接。函數(shù)介紹如下:

#include <sys/types.h>
        #include <sys/shm.h>

int shmdt(const void * shmaddr);

返回:失敗-1并置errno, 成功返回0

分離由shmaddr指定的存儲段。此值應(yīng)該由shmat返回的值。
        此函數(shù)不是刪除共享存儲段,而是從當前進程分離存儲段。
        當進程推出時,系統(tǒng)會自動分離它連接的所有共享段。

共享內(nèi)存區(qū)的控制
        #include <sys/ipc.h>
        #include <sys/shm.h>

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

存儲段控制函數(shù)。可獲得shmid_ds全部內(nèi)容。

返回:失敗-1并置errno, 成功返回0。

第一個參數(shù),必須由shmget返回的存儲段的id。cmd為指定要求的操作。

CMD 說明 參數(shù)
        IPC_STAT          放置與shmid相連的shmid_ds結(jié)構(gòu)當前值于buf所指定用戶區(qū) buf
        IPC_SET          用buf指定的結(jié)構(gòu)值代替與shmid相連的shmid_ds結(jié)構(gòu)值 buf
        IPC_RMID          刪除制定的信號量集合 
        SHM_LOCK          鎖住共享存儲段。只能由超級管理員使用 
        SHM_UNLOCK          unlock共享存儲段。只能由超級管理員使用

附例子:
        #include <stdio.h>
         #include <stdlib.h>
        #include <unistd.h>
        #include <sys/types.h>
        #include <sys/ipc.h>
        #include <sys/sem.h>
        #include <sys/shm.h>
        #include <errno.h>

#define SHM_SIZE 1024
        union semun 
        {
                int val;
                struct semid_ds *buf;
                unsigned short *array;
};

/*創(chuàng)建信號量函數(shù)*/
        int createsem (const char *pathname,int proj_id,int members,int init_val)
        {
                key_t msgkey;
                int index,sid;
                union semun semopts;
                if ((msgkey = ftok(pathname,proj_id)) == -1) {
                        perror ("ftok error1\n");
                        return -1;
                }

        if ((sid = semget (msgkey,members,IPC_CREAT |0666)) == -1) {
                        perror("semget call failed!");
                        return -1;
                }

        /*初始化操作*/
                semopts.val = init_val;
                for (index = 0;index < members; index ++){
                        semctl(sid,index,SETVAL,semopts);
                }
                return (sid);
        }

/*打開信號量函數(shù)*/
        int opensem (const char *pathname,int proj_id)
        {
                key_t msgkey;
                int sid;

                if ((msgkey = ftok(pathname,proj_id)) == -1) {
                        perror ("ftok error1\n");
                        return -1;
                }

        if ((sid = semget (msgkey,0,IPC_CREAT |0666)) == -1) {
                perror("semget call failed!");
                return -1;
                }

        return (sid);
        }

/*P操作函數(shù)*/
        int sem_p(int semid,int index)
        {
                struct sembuf buf = {0,-1,IPC_NOWAIT};
                if (index < 0) {
                        perror("index of array can not equals a minus value!");
                        return -1;
                }
                buf.sem_num = index;
                if (semop(semid ,&buf,1) == -1) {
                        perror("a wrong operations to semaphore occured!");
                        return -1;
                }
                return 0;
        }

/*V操作函數(shù)*/
        int sem_v(int semid,int index)
        {
                struct sembuf buf = {0,+1,IPC_NOWAIT};
                if (index < 0) {
                        perror("index of array can not equals a minus value!");
                        return -1;
                }
                buf.sem_num = index;
                if (semop(semid ,&buf,1) == -1) {
                        perror("a wrong operations to semaphore occured!");
                        return -1;
                }
                return 0;
        }

/*刪除信號集函數(shù)*/
        int sem_delete(int semid)
        {
                return (semctl(semid,0,IPC_RMID));
        }

/*等待信號集函數(shù)*/
        int wait_sem (int semid,int index)
        {
                while (semctl(semid,index,GETVAL,0) == 0) {
                        sleep(1);
                }
                return 1;
        }

/*創(chuàng)建共享內(nèi)存函數(shù)*/
        int createshm(char * pathname,int proj_id,size_t size)
        {
                key_t shmkey;
                int sid;
                /*獲取鍵值*/
                if ((shmkey = ftok(pathname,proj_id)) == -1 ) {
                        perror("shmkey ftok error! \n");
                        return -1;
                }

        if ((sid = shmget(shmkey,size,IPC_CREAT | 0666)) == -1) {
                        perror("shmget call failed!\n");
                        return -1;
                }
                return (sid);
        }

/* Write.c */
        #include <string.h>
        #include "sharemem.h"
        int main(void)
        {
                int semid,shmid;
                char *shmaddr;
                char write_str[SHM_SIZE];
                if ((shmid = createshm(".",'m',SHM_SIZE)) == -1) {
                        exit (1);
                }

        if ((shmaddr = shmat(shmid,(char*)0,0)) == (char *)-1) {
                        perror("attach shared memory error!\n");
                        exit (1);
                }

        if ((semid = createsem(".",'s',1,1)) == -1) {
                        exit(1);
                }

        while(1) {
                        wait_sem(semid,0);
                        sem_p(semid,0);

                printf("write:");
                        fgets(write_str,1024,stdin);
                int len = strlen(write_str) -1;
                        write_str[len] = '\0';
                        strcpy(shmaddr,write_str);
                        sleep(2); /*使reader處于阻塞狀態(tài)*/
                        sem_v(semid,0); /*v操作*/
                        sleep(2); /*等待reader進行讀操作*/
                }
                return 0;
        }

/* Read.c */
        #include "sharemem.h"
        int main(void)
        {
                int semid,shmid;
                char *shmaddr;
                char write_str[SHM_SIZE];
                if ((shmid = createshm(".",'m',SHM_SIZE)) == -1) {
                        exit (1);
                }

        if ((shmaddr = shmat(shmid,(char*)0,0)) == (char *)-1) {
                        perror("attach shared memory error!\n");
                        exit (1);
                }

        if ((semid = opensem(".",'s')) == -1) {
                        exit(1);
                }

        while(1) {
                        printf("reader:");
                        wait_sem(semid,0); /*等待信號值為1*/
                        sem_p(semid,0);

                printf("%s\n",shmaddr);
                        sleep(2); /*使writer處于阻塞狀態(tài)*/
                        sem_v(semid,0); /*v操作*/
                        sleep(2); /*等待write進行寫操作*/
                }
                return 0;
        }

發(fā)表評論
評論列表(網(wǎng)友評論僅供網(wǎng)友表達個人看法,并不表明本站同意其觀點或證實其描述)
色偷偷偷亚洲综合网另类,亚洲欧美另类在线观看,欧美午夜激情在线,久久久精品一区
主站蜘蛛池模板: 日韩国产欧美精品一区二区三区| 日韩经典第一页| 91超碰caoporn97人人| 2019av中文字幕| 国产成人精品视频在线| 国产精品青青在线观看爽香蕉| 欧美在线一区二区三区四| 69影院欧美专区视频| 国产精品大片wwwwww| 成人免费福利在线| 亚洲美女av黄| 另类少妇人与禽zozz0性伦| 欧美日韩中文字幕日韩欧美| 海角国产乱辈乱精品视频| 国产精品久久久久久久久久| 亚洲综合国产精品| 国产亚洲精品久久久久久777| 欧美成人久久久| 51午夜精品视频| 亚洲成人av中文字幕| 日日狠狠久久偷偷四色综合免费| 丁香五六月婷婷久久激情| 国产成人精品一区二区| 亚洲成人精品久久久| 另类天堂视频在线观看| 91成人在线视频| 日韩大陆毛片av| 欧美日韩高清在线观看| 国产精品美女免费视频| 亚洲一区二区久久久| 欧美激情第1页| 91精品中国老女人| 久久久电影免费观看完整版| 欧美中文字幕第一页| 日韩黄色av网站| 欧美精品福利视频| 亚洲国产精品免费| 欧美第一黄色网| 亚洲最大av在线| 欧美精品福利在线| 亚洲老头同性xxxxx|