共享內(nèi)存區(qū)的使用

還是以操作系統(tǒng)第三章大作業(yè)中的一項作為導(dǎo)入。

大作業(yè)2要求.png

共享內(nèi)存就是允許多個不相關(guān)的進程共享訪問的一個邏輯內(nèi)存,是進程間數(shù)據(jù)共享的一種很有效的方式。所有進程都可以對這片區(qū)域進行寫入、讀取,類似于全局變量吧。

使用共享內(nèi)存需要一些函數(shù)接口來實現(xiàn),如shmget函數(shù)創(chuàng)建共享內(nèi)存,shmat函數(shù)將共享內(nèi)存連接到進程,shmdt函數(shù)將共享內(nèi)存從進程中分離,shmctl函數(shù)可用來刪除共享內(nèi)存段。

有關(guān)函數(shù)的具體用法可參考Linux進程間通信——使用共享內(nèi)存

共享內(nèi)存并沒有提供同步機制,故我們需要使用信號量等方式來控制進程間的互斥。本例沒有使用信號量,而是使用了written作為標(biāo)志起到互斥量相同的作用。

下面直接丟代碼了,這個問題理解起來沒什么難度,就是熟悉對共享內(nèi)存的操作。模型也借用了上面博客的例子,進行了部分修改。詳細內(nèi)容見代碼及注釋。

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <assert.h>

#define TEXT_SIZE 1024
void shmread();
void shmwrite();

struct shared_struct
{
    int written;//0表示可寫,非0表示可讀,類似于讀寫鎖 
    char text[TEXT_SIZE];//記錄讀寫的文本 
};

void shmread()
{
    int running = 1;//程序運行的標(biāo)志,1為運行 
    void *shm = NULL;//共享內(nèi)存的原始首地址 
    struct shared_struct *shared;//指向shm 
    int shmid;//共享內(nèi)存標(biāo)識符 
    key_t key;//key值 

    //創(chuàng)建key值 
    key = ftok("../", 1234);
    assert(key!=-1);
    //創(chuàng)建共享內(nèi)存 
    shmid = shmget(key, sizeof(struct shared_struct), 0666|IPC_CREAT);
    assert(shmid!=-1);  //值為假,則打印出錯信息并退出    
    //將共享內(nèi)存連接到當(dāng)前進程的地址空間 
    shm = shmat(shmid, 0, 0);
    assert(shm!=(void*)-1);
    
    //printf("\nMemory attached at %X\n", (int)shm);
    //設(shè)置共享內(nèi)存 
    shared = (struct shared_struct*)shm;
    shared->written = 0;
    while(running)//讀取共享內(nèi)存的數(shù)據(jù) 
    {
        //
        if(shared->written != 0)
        {
            printf("You just wrote: %s", shared->text);
            sleep(1);
            //讀完數(shù)據(jù)后設(shè)置written使共享內(nèi)存段可寫 
            shared->written = 0;
            //輸入end退出程序 
            if(strncmp(shared->text, "end", 3) == 0)
                running = 0;
        }
        else//有其他進程在寫數(shù)據(jù)則不能讀取數(shù)據(jù) 
            sleep(1);
    }
    //將共享內(nèi)存從當(dāng)前進程分離 
    assert(shmdt(shm)!=-1);
    //刪除共享內(nèi)存
    assert(shmctl(shmid, IPC_RMID, 0) != -1);
    
    exit(EXIT_SUCCESS);
}

void shmwrite()
{
    int running = 1;
    void *shm = NULL;
    struct shared_struct *shared;
    int shmid;
    key_t key;

    key = ftok("../", 1234);
    assert(key!=-1);

    char buffer[BUFSIZ + 1];//緩沖區(qū)用于保存輸入的文本,BUFSIZE=8192在stdlib.h中定義的 
    //創(chuàng)建 
    shmid = shmget(key, sizeof(struct shared_struct), 0666|IPC_CREAT);
    assert(shmid!=-1);
    //連接
    shm = shmat(shmid, (void*)0, 0);
    assert(shm!=(void*)-1);

    //printf("Memory attached at %X\n", (int)shm);
    //設(shè)置
    shared = (struct shared_struct*)shm;
    while(running)//寫數(shù)據(jù)
    {
        //等待數(shù)據(jù)被讀取后再寫數(shù)據(jù) 
        while(shared->written == 1)
        {
            sleep(1);
            printf("Waiting...\n");
        }
        //寫數(shù)據(jù)
        printf("Enter some text: ");
        fgets(buffer, BUFSIZ, stdin);
        strncpy(shared->text, buffer, TEXT_SIZE);
        
        //寫數(shù)據(jù)后設(shè)置written使共享內(nèi)存段可讀 
        shared->written = 1;
        //輸入end退出程序 
        if(strncmp(buffer, "end", 3) == 0)
            running = 0;
    }
    //分離
    assert(shmdt(shm)!=-1);
    //sleep(2);
    exit(EXIT_SUCCESS);
}

int main()
{
    pid_t pid;
    pid=fork();
    if(pid==0)  shmwrite(); //子進程使用共享區(qū)并讀數(shù)據(jù) 
    else    shmread();      //父進程創(chuàng)建并使用共享區(qū)并寫數(shù)據(jù) 
    exit(0);
}

運行示例如圖。


運行示例.png

其他參考鏈接也列出
linux 共享內(nèi)存(實現(xiàn)進程之間通信)
共享內(nèi)存的實現(xiàn)詳解

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容