色yeye在线视频观看_亚洲人亚洲精品成人网站_一级毛片免费播放_91精品一区二区中文字幕_一区二区三区日本视频_成人性生交大免费看


linux 共享內存

分享到:
           

    本文關鍵字: linux 共享內存,linux 共享內存編程

    可以說,共享內存是一種為高效的進程間通信方式,因為進程可以直接讀寫內存,不需要任何數據的復制。為了在多個進程間交換信息,內核專門留出了一塊內存區,這段內存區可以由需要訪問的進程將其映射到自己的私有地址空間。因此,進程就可以直接讀寫這一內存區而不需要進行數據的復制,從而大大提高了效率。當然,由于多個進程共享一段內存,因此也需要依靠某種同步機制,如互斥鎖和信號量等。其原理示意圖如圖1所示。


圖1 共享內存原理示意圖

    共享內存的實現分為兩個步驟:第一步是創建共享內存,這里用到的函數是shmget(),也就是從內存中獲得一段共享內存區域;第二步是映射共享內存,也就是把這段創建的共享內存映射到具體的進程空間中,這里使用的函數是shmat()。到這里,就可以使用這段共享內存了,也就是可以使用不帶緩沖的I/O讀寫命令對其進行操作。除此之外,還有撤銷映射的操作,其函數為shmdt()。這里主要介紹這3個函數。

    表1 列舉了shmget()函數的語法要點。

表1 shmget()函數語法要點

所需頭文件 #include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
函數原型 int shmget(key_t key, int size, int shmflg)
函數傳入值 key:共享內存的鍵值,多個進程可以通過它訪問同一個共享內存,其中有個特殊值IPC_PRIVATE,用于創建當前進程的私有共享內存
size:共享內存區大小
shmflg:同open()函數的權限位,也可以用八進制表示法
函數返回值 成功:共享內存段標識符
出錯:-1

    表2列舉了shmat()函數的語法要點。

表2 shmat()函數語法要點

所需頭文件 #include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
函數原型 char *shmat(int shmid, const void *shmaddr, int shmflg)
函數傳入值 shmid:要映射的共享內存區標識符
shmaddr:將共享內存映射到指定地址(若為0則表示系統自動分配地址并把該段共享內存映射到調用進程的地址空間)
shmflg SHM_RDONLY:共享內存只讀
默認0:共享內存可讀寫
函數返回值 成功:被映射的段地址
出錯:-1

    表3列舉了shmdt()函數的語法要點。

表3 shmdt()函數語法要點

所需頭文件 #include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
函數原型 int shmdt(const void *shmaddr)
函數傳入值 shmaddr:被映射的共享內存段地址
函數返回值 成功:0
出錯:-1

    以下實例說明了如何使用基本的共享內存函數。首先創建一個共享內存區(采用的共享內存的鍵值為IPC_PRIVATE,是因為本實例中創建的共享內存是父子進程間的共用部分),然后創建子進程,在父子兩個進程中將共享內存分別映射到各自的進程地址空間中。

    父進程先等待用戶輸入,然后將用戶輸入的字符串寫入到共享內存,之后向共享內存的頭部寫入“WROTE”字符串表示父進程已成功寫入數據。子進程一直等到共享內存的頭部字符串為“WROTE”,然后將共享內存的有效數據(在父進程中用戶輸入的字符串)在屏幕上打印。父子兩個進程在完成以上工作后,分別解除與共享內存的映射關系。

    后在子進程中刪除共享內存。因為共享內存自身并不提供同步機制,所以應額外實現不同進程間的同步(如信號量)。為了簡單起見,在本實例中用標志字符串來實現非常簡單的父子進程間的同步。

    這里要介紹的一個命令是ipcs,用于報告進程間通信機制狀態,它可以查看共享內存、消息隊列等各種進程間通信機制的情況,這里使用了system()函數調用shell命令“ipcs”。程序源代碼如下:

    /* shmem.c */
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    #define BUFFER_SIZE 2048

    int main()
    {
        pid_t pid;
        int shmid;
        char *shm_addr;
        char flag[] = "WROTE";
        char *buff;

        /* 創建共享內存 */
        if ((shmid = shmget(IPC_PRIVATE, BUFFER_SIZE, 0666)) < 0)
        {
            perror("shmget");
            exit(1);
        }
        else
        {
        printf("Create shared-memory: %d\n",shmid);
        }

        /* 顯示共享內存情況 */
        system("ipcs -m");

        pid = fork();
        if (pid == -1)
        {
            perror("fork");
            exit(1);
        }
        else if (pid == 0) /* 子進程處理 */
        {
            /* 映射共享內存 */
            if ((shm_addr = shmat(shmid, 0, 0)) == (void*)-1)
            {
                perror("Child: shmat");
                exit(1);
            }
            else
            {
                printf("Child: Attach shared-memory: %p\n", shm_addr);
            }
            system("ipcs -m");

            /* 通過檢查在共享內存的頭部是否有標志字符串“WROTE”來確認父進程已經向共享內存寫入有效數據 */
            while (strncmp(shm_addr, flag, strlen(flag)))
            {
                printf("Child: Wait for enable data...\n");
                sleep(5);
            }

            /* 獲取共享內存的有效數據并顯示 */
            strcpy(buff, shm_addr + strlen(flag));
            printf("Child: Shared-memory :%s\n", buff);

            /* 解除共享內存映射 */
            if ((shmdt(shm_addr)) < 0)
            {
                perror("shmdt");
                exit(1);
            }
            else
            {
                printf("Child: Deattach shared-memory\n");
            }
            system("ipcs -m");

            /* 刪除共享內存 */
            if (shmctl(shmid, IPC_RMID, NULL) == -1)
            {
                perror("Child: shmctl(IPC_RMID)\n");
                exit(1);
            }
            else
            {
                printf("Delete shared-memory\n");
            }

            system("ipcs -m");
        }
        else /* 父進程處理 */
        {
            /* 映射共享內存 */
            if ((shm_addr = shmat(shmid, 0, 0)) == (void*)-1)
            {
                perror("Parent: shmat");
                exit(1);
            }
            else
            {
                printf("Parent: Attach shared-memory: %p\n", shm_addr);
            }

            sleep(1);
            printf("\nInput some string:\n");
            fgets(buff, BUFFER_SIZE, stdin);
            strncpy(shm_addr + strlen(flag), buff, strlen(buff));
            strncpy(shm_addr, flag, strlen(flag));

            /* 解除共享內存映射 */
            if ((shmdt(shm_addr)) < 0)
            {
                perror("Parent: shmdt");
                exit(1);
            }
            else
            {
                printf("Parent: Deattach shared-memory\n");
            }
            system("ipcs -m");

            waitpid(pid, NULL, 0);
            printf("Finished\n");
        }

        exit(0);
    }

    下面是運行結果,從該結果中可以看出,nattch的值隨著共享內存狀態的變化而變化,共享內存的值根據不同的系統會有所不同。

    $ ./shmem
    Create shared-memory: 753665
    /* 在剛創建共享內存時(尚未有任何地址映射)共享內存的情況 */
    ------ Shared Memory Segments --------
    key        shmid    owner    perms    bytes    nattch    status
    0x00000000 753665   david    666      2048      0

    Child: Attach shared-memory: 0xb7f59000 /* 共享內存的映射地址 */
    Parent: Attach shared-memory: 0xb7f59000
    /* 在父子進程中進行共享內存的地址映射后共享內存的情況 */
    ------ Shared Memory Segments --------
    key        shmid    owner    perms    bytes    nattch    status
    0x00000000 753665   david    666      2048      2

    Child: Wait for enable data...

    Input some string:
    Hello /* 用戶輸入字符串“Hello” */
    Parent: Deattach shared-memory
    /* 在父進程中解除共享內存的映射關系后共享內存的情況 */
    ------ Shared Memory Segments --------
    key        shmid    owner    perms    bytes    nattch    status
    0x00000000 753665   david    666      2048      1
    /* 在子進程中讀取共享內存的有效數據并打印 */
    Child: Shared-memory :hello

    Child: Deattach shared-memory
    /* 在子進程中解除共享內存的映射關系后共享內存的情況 */
    ------ Shared Memory Segments --------
    key        shmid    owner    perms    bytes    nattch    status
    0x00000000 753665   david    666      2048      0

    Delete shared-memory
    /* 在刪除共享內存后共享內存的情況 */
    ------ Shared Memory Segments --------
    key        shmid    owner    perms    bytes    nattch    status

    Finished

    本文選自華清遠見嵌入式培訓教材《從實踐中學嵌入式Linux應用程序開發》

   熱點鏈接:

   1、linux下的信號量
   2、linux下的信號處理實例
   3、信號處理函數signal()和信號集函數組
   4、信號捕捉函數alarm()和pause()
   5、信號發送函數kill()和raise()

更多新聞>> 

主站蜘蛛池模板: 亚洲色大成网站WWW永久 | 人妻人人添人妻人人爱 | 亚洲伊人情人综合网站 | 亚洲av无码久久久久久精品同性 | 亚洲乱码中文字幕久久孕妇黑人 | 欲求不満の人妻松下纱荣子 | 亚洲日产韩国一二三四区 | 男女无遮挡XX00动态图120秒 | 午夜A片免费 | 我朋友的妈妈在线免费观看 | 免费无码又爽又高潮视频 | 狠狠躁夜夜躁AV网站中文字幕 | 成人免费精品网站在线观看影片 | 成人A级毛片免费视频 | 久久久久亚洲AV无码麻豆 | 人妻蜜と1~4中文字幕月野定规 | 女人被强╳到高潮喷水在线观看 | 国产SM主人调教女M视频 | 少妇人妻互换不带套 | 狠狠久久永久免费观看 | 免费观看潮喷到高潮 | 四房色播开心网 | 欧美熟妇的荡欲在线观看 | 日本阿V网站在线观看中文 欧美深夜影院 | 亚洲综合一区国产精品 | 4438x五月 | 天天综合天天爱天天做天天爽 | 9I制作厂免费 | 亚洲第一福利网站在线 | 一个人免费在线观看动漫视频www | 精品人妻无码一区二区三区手机版 | 日韩不卡1卡2卡三卡免费网站2021 | 国产黑色丝袜在线播放 | 亚洲制服丝袜精品久久 | GOGOGO免费视频观看 高清国语 | 色妞AV永久一区二区国产AV | 亚洲色在线无码国产精品不卡 | 日日噜噜噜夜夜爽爽狠狠视频 | 国产强伦姧在线观看 | 久久精品人妻无码一区二区三区 | 欧美深度肠交惨叫 |