久久婷婷香蕉热狠狠综合,精品无码国产自产拍在线观看蜜,寡妇房东在做爰3,中文字幕日本人妻久久久免费,国产成人精品三上悠亚久久

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

前幾天上進程間通訊的(de)課程,看到有同學對共享內存有些不(bu)是很明白(bai),而且(qie)在查man幫助的(de)時(shi)候也(ye)不(bu)是很能(neng)明白(bai)系(xi)統對其的(de)說明,故有了這篇文章。

共(gong)享內(nei)存是(shi)(shi)系(xi)統在(zai)做進(jin)程間通訊時比較(jiao)常(chang)用(yong)的(de)(de)IPC通訊方式(shi)之一,同時也(ye)是(shi)(shi)效(xiao)率(lv)高的(de)(de),但是(shi)(shi)由于(yu)其(qi)的(de)(de)獨特性導(dao)致(zhi)在(zai)使(shi)用(yong)共(gong)享內(nei)存的(de)(de)時候(hou)需要(yao)注意一點就(jiu)是(shi)(shi)幾個進(jin)程間通訊時的(de)(de)互斥和同步(bu)問題,所以在(zai)使(shi)用(yong)共(gong)享內(nei)存的(de)(de)時候(hou),我們一般要(yao)對其(qi)加(jia)鎖或(huo)者加(jia)一些其(qi)他的(de)(de)同步(bu)機(ji)制,比如信號(hao)燈之類的(de)(de)。

首先看(kan)下共享內存的(de)數據結構:

共享內(nei)存區的數(shu)據結構

每個共享內(nei)存段在(zai)內(nei)核中維護著一個內(nei)部(bu)結構shmid_ds,該(gai)結構定義在(zai)linux/shm.h中,代碼如下所示:

struct shmid_ds {
        struct ipc_perm shm_perm;/* 超作許可權數據結構指針 */
                int         shm_segsz;        /* 共享存儲段大小 (bytes) */
                time_t         shm_atime;        /* 后調用shmat時間 */
                time_t        shm_dtime;         /* 后調用shmdt的時間 */
                time_t        shm_ctime;        /* 后調用shmctl的改變的時間 */
                unsigned short        shm_cpid;        /*創建者的進程ID */
                unsigned short        shm_lpid;        /* 后對共享存儲段進行操作的進程ID */
                short        shm_nattch;        /* 當前連接數 */
    &nbsp;    };

共(gong)享(xiang)內存(cun)的創建和操作

A:共享內存區的(de)創建

linux下使用函數shmget來創建一個共享內存(cun)區,或者(zhe)訪問一個已經存(cun)在的共享內存(cun)區,該函數定義如下:

#include <sys/ipc.h>
       &nbsp;#include <sys/shm.h>;

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

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

第一個參數(shu)key是(shi)共享存(cun)(cun)儲關鍵字。它(ta)有特殊值(zhi)IPC_PRIVATE表示總是(shi)創建一個進程私有的(de)共享存(cun)(cun)儲段。當key值(zhi)不等于(yu)IPC_PRIVATE時,shmget動作取決于(yu)后一個參數(shu)shmflg標志:

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

如果沒有指定(ding)IPC_CREATE并(bing)且(qie)系統中(zhong)不存在相(xiang)同key值的共(gong)享(xiang)存儲段,將失敗返(fan)回。

第二個參(can)數(shu)(shu)size指(zhi)明要求的(de)(de)共(gong)(gong)(gong)享存(cun)儲段(duan)的(de)(de)大(da)小(xiao)。當key指(zhi)定的(de)(de)共(gong)(gong)(gong)享存(cun)儲段(duan)已(yi)(yi)存(cun)在(zai)時(shi),取值范(fan)圍(wei)為(wei)0和已(yi)(yi)存(cun)在(zai)共(gong)(gong)(gong)享段(duan)大(da)小(xiao)。或簡(jian)單(dan)指(zhi)定為(wei)0。成功后此函(han)數(shu)(shu)返回(hui)共(gong)(gong)(gong)享存(cun)儲段(duan)id,同時(shi)創建于(yu)參(can)數(shu)(shu)key相連的(de)(de)數(shu)(shu)據結構(gou)shmid_ds。此節構(gou)為(wei)系統(tong)內部使用。

 第三(san)個(ge)參數(shu)也可以(yi)設(she)置(zhi)共(gong)享存儲段的訪問權限,用或于上面的值操作。

B:共享內(nei)存區的操作

在使用(yong)(yong)共(gong)享(xiang)內(nei)存區之前(qian),必須通過(guo)shmat函數(shu)將(jiang)其(qi)附(fu)加到(dao)進(jin)程的地址空間,進(jin)程和地址空間就(jiu)建立了連接(jie)。shmat調(diao)用(yong)(yong)成(cheng)功(gong)后就(jiu)返回(hui)一(yi)個共(gong)享(xiang)內(nei)存區指針,使用(yong)(yong)該指針就(jiu)可以訪(fang)問共(gong)享(xiang)內(nei)存區了。

#include <sys/types.h>
&nbsp;       #include <sys/shm.h>

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

返回(hui):失敗-1并置errno, 成功(gong)返回(hui)連(lian)接的實際地(di)址。

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

 第(di)二個參數指(zhi)明共享存儲(chu)段(duan)要連接到的(de)地址。0,系統(tong)為(wei)我們創建一個適當的(de)地址值。否則(ze)自己指(zhi)定。

第(di)三個參數(shu)shmflg可以(yi)設成:SHM_RND, SHM_RDONLY。SHM_RND為(wei)自己指定連(lian)接地址(zhi)時用(yong)。SHM_RDONLY說明(ming)此存儲段(duan)只讀。

當進程結束使用共享內(nei)存區(qu)時(shi),就要(yao)通過函(han)數(shu)shmdt斷開于共享內(nei)存區(qu)的連接。函(han)數(shu)介(jie)紹如下(xia):

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

int shmdt(const void * shmaddr);

 返回(hui)(hui):失敗-1并置errno, 成(cheng)功(gong)返回(hui)(hui)0

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

共享內存區的控制
        #include <sys/ipc.h>
      &nbsp; #include <sys/shm.h>

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

存儲段控制(zhi)函(han)數。可(ke)獲(huo)得(de)shmid_ds全部內容。

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

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

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

附例子:
        #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>
   &nbsp;    #include <errno.h>

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

/*創建信號量函數*/
        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;
&nbsp;               }

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

/*打開信號量函數*/
        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;
           &nbsp; ;   }

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

        return (sid);
        }

/*P操作函數*/
        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;
  &nbsp;     }

/*V操作函數*/
        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;
      ;&nbsp; }

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

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

/*創建共享內存函數*/
        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;
       &nbsp;      &nbsp; }

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

/* 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);
 &nbsp;                      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處于阻塞狀態*/
                        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);
  &nbsp;             }

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

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

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

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

發表評論
評論列表(網友評論僅供網友表達個人看法,并不表明本站同意其觀點或證實其描述)