国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Linux--進(jìn)程間的通信-共享內(nèi)存

這篇具有很好參考價(jià)值的文章主要介紹了Linux--進(jìn)程間的通信-共享內(nèi)存。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

前文:
Linux–進(jìn)程間的通信-匿名管道
Linux–進(jìn)程間的通信–進(jìn)程池
Linux–進(jìn)程間的通信-命名管道

共享內(nèi)存

對于兩個(gè)進(jìn)程,通過在內(nèi)存開辟一塊空間(操作系統(tǒng)開辟的),進(jìn)程的虛擬地址通過頁表映射到對應(yīng)的共享內(nèi)存空間中,進(jìn)而實(shí)現(xiàn)通信

特點(diǎn)和作用:

  1. 高效性: 共享內(nèi)存是一種高效的進(jìn)程間通信方式,因?yàn)樗试S多個(gè)進(jìn)程直接訪問同一塊內(nèi)存,而無需進(jìn)行復(fù)制或數(shù)據(jù)傳輸。
  2. 快速通信: 由于共享內(nèi)存直接映射到進(jìn)程的地址空間,因此讀寫速度快,適用于對通信速度有較高要求的場景。
  3. 靈活性: 共享內(nèi)存提供了一種靈活的通信方式,允許多個(gè)進(jìn)程在需要時(shí)訪問共享數(shù)據(jù),而無需通過中間介質(zhì)進(jìn)行通信。
  4. 數(shù)據(jù)共享: 多個(gè)進(jìn)程可以通過共享內(nèi)存實(shí)現(xiàn)數(shù)據(jù)共享,從而實(shí)現(xiàn)對數(shù)據(jù)的共同讀寫和處理。

模擬實(shí)現(xiàn)

Linux--進(jìn)程間的通信-共享內(nèi)存,Linux,linux,數(shù)據(jù)庫,運(yùn)維
Linux--進(jìn)程間的通信-共享內(nèi)存,Linux,linux,數(shù)據(jù)庫,運(yùn)維

代碼

Comm.hpp:包含共享內(nèi)存的創(chuàng)建,銷毀,掛接進(jìn)程等。

#pragma once

#include<stdio.h>
#include<iostream>
#include<string>
#include<cerrno>
#include<cstring>
#include<cstdlib>
#include<sys/ipc.h>
#include<sys/types.h>
#include<sys/shm.h>
using namespace std;


const char* pathname="/home/ubuntu/Learning/Pipe";
const int proj_id=0x66;

//在內(nèi)核中,共享內(nèi)存的基本單位是4kb,我們申請的大小相當(dāng)于是n*4kb
const int DefaultSize=4096;

//將key值轉(zhuǎn)換為16進(jìn)制的;
string ToHEX(key_t k)
{
    char buffer[1024];
    snprintf(buffer,sizeof(buffer),"0x%x",k);
    return buffer;
}

//獲取鍵值
key_t GetShmKeyorDie()
{
    key_t k=ftok(pathname,proj_id);
    if(k<0)
    {
        //當(dāng)返回值為-1時(shí),錯(cuò)誤表示stat(2)系統(tǒng)調(diào)用錯(cuò)誤
        cerr << "ftok error, errno : " << errno << ", error string: " << strerror(errno) << endl;
        exit(1);
    }
    return k;
}

//創(chuàng)建共享內(nèi)存,只在該函數(shù)內(nèi)調(diào)用
int CreateShmOrDie(key_t key,int size,int flag)
{
    int shmid = shmget(key,size,flag);
    if(shmid<0)
    {
        std::cerr << "shmget error, errno : " << errno << ", error string: " << strerror(errno) << std::endl;
        exit(2);
    }
    return shmid;

}

//調(diào)用時(shí)的創(chuàng)建共享內(nèi)存
int CreateShm(key_t key,int size)
{
    //如果已經(jīng)存在了,那么會(huì)報(bào)錯(cuò);
    return CreateShmOrDie(key,size,IPC_CREAT|IPC_EXCL|0666);
}
//調(diào)用時(shí)的獲取
int GetShm(key_t key,int size)
{
    return CreateShmOrDie(key,size,IPC_CREAT);
}

//刪除共享內(nèi)存
void DeleteShm(int shmid)
{
    int n=shmctl(shmid,IPC_RMID,nullptr);
    if(n<0)
    {
        cerr<<"shmctl error"<<endl;
    }
    else
    {
        cout<<"shmctl delete shm success, shmid: "<<shmid<<endl;
    }
}

//查看共享內(nèi)存的狀態(tài)
void ShmDebug(int shmid)
{
    struct shmid_ds shmds;
    int n=shmctl(shmid ,IPC_STAT,&shmds);
    if(n<0)
    {
        std::cerr << "shmctl error" << std::endl;
        return;
    }
    std::cout << "shmds.shm_segsz: " << shmds.shm_segsz << std::endl;
    std::cout << "shmds.shm_nattch:" << shmds.shm_nattch << std::endl;
    std::cout << "shmds.shm_ctime:" << shmds.shm_ctime << std::endl;
    std::cout << "shmds.shm_perm.__key:" << ToHEX(shmds.shm_perm.__key) << std::endl;
}

void* ShmAttach(int shmid)
{
    void* addr = shmat(shmid,nullptr,0);
    //第二個(gè)參數(shù)設(shè)置nullptr,表示讓系統(tǒng)選擇合適的地址進(jìn)行連接
    if((long long int)addr==-1)
    {
        cerr<<"shmat error"<<endl;
        return nullptr;
    }
    return addr;
}

void ShmDetach(void* addr)
{
    int n=shmdt(addr);
    if(n<0)
    {
        cerr<<"shmdt error"<<endl;
    }
}

fifo.hpp:利用管道來實(shí)現(xiàn)對共享內(nèi)存實(shí)現(xiàn)同步機(jī)制。

#include<iostream>
#include<string>
#include<cstring>
#include<cerrno>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
#include<assert.h>
using namespace std;

#define Mode 0666
#define Path "./fifo"

class fifo
{
public:
    fifo(const string & path=Path)
    :_path(path)
    {
        umask(0);
        int n=mkfifo(_path.c_str(),Mode);
        if(n==0)
        {
            cout<< "mkfifo success" << endl;
        }
        else
        {
            cerr << "mkfifo failed, errno: " << errno << ", errstring: " << strerror(errno) << endl;
        }
    }
    ~fifo()
    {
        int n=unlink(_path.c_str());
        if (n == 0)
        {
            cout << "remove fifo file " << _path << " success" << endl;
        }
        else
        {
            cerr << "remove failed, errno: " << errno << ", errstring: " << strerror(errno) << endl;
        }
    }
private:
    string _path; //文件路徑
};

class Sync
{
public:
    Sync()
    :_rfd(-1),
    _wfd(-1)
    {}
    void OpenReadOrDie()
    {
        _rfd=open(Path,O_RDONLY);
        if(_rfd<0)
            exit(1);
    }
    void OpenWriteDie()
    {
        _wfd=open(Path,O_WRONLY);
        if(_wfd<0)
            exit(1);
    }
    bool Wait()
    {
        bool ret=true;
        uint32_t c=0;
        ssize_t n=read(_rfd,&c,sizeof(uint32_t));
        if(n==sizeof(uint32_t))
        {
            cout<<"server wakeup ,begin read shm..."<<endl;
        }
        else if(n==0)
        {
            ret=false;
        }
        else
        {
            return false;
        }
        return ret;
    }
    void Wakeup()
    {
        uint32_t c=0;
        ssize_t n=write(_wfd,&c,sizeof(c));
        assert(n==sizeof(uint32_t));

        cout<<"wakeup server..."<<endl;
    }
    ~Sync() {}
private:
    int _wfd;
    int _rfd;
};

ShmServer.cc

#include "Comm.hpp"
#include "fifo.hpp"
#include<unistd.h>
int main()
{
    
    //1.獲取key
    key_t key = GetShmKeyorDie();
    std::cout << "key: " << ToHEX(key) << std::endl;
    // sleep(2);
    
    //2.創(chuàng)建共享內(nèi)存
    int shmid = CreateShm(key, DefaultSize);
    std::cout << "shmid: " << shmid << std::endl;
     sleep(2);
  

    //4.將共享內(nèi)存與進(jìn)程掛接
    char* addr=(char*)ShmAttach(shmid);
    cout<<"Attach shm success, addr: "<<ToHEX((uint64_t)addr)<<endl;
   
    //0.先引入管道
    fifo ff;
    Sync syn;
    syn.OpenReadOrDie();

   //進(jìn)行通信
     while(1)
     {
        if(!syn.Wait())break;
        cout<<"shm content: "<<addr<<endl;
     }

    ShmDetach(addr);
    std::cout << "Detach shm success, addr: " << ToHEX((uint64_t)addr) << std::endl;
     
     
    //3.刪除共享內(nèi)存
    DeleteShm(shmid);
    return 0;
}

ShmClient.cc

#include"Comm.hpp"
#include "fifo.hpp"
#include<unistd.h>
int main()
{
    key_t key = GetShmKeyorDie();
    std::cout << "key: " << ToHEX(key) << std::endl;
    // sleep(2);

    int shmid = GetShm(key, DefaultSize);
    std::cout << "shmid: " << shmid << std::endl;
    
    
    char* addr=(char*)ShmAttach(shmid);
    cout<<"Attach shm success, addr: "<<ToHEX((uint64_t)addr)<<endl;
    
    
    //通信
    memset(addr,0,DefaultSize);
    Sync syn;
    syn.OpenWriteDie();
    for(char c ='A';c<='Z';c++)
    {
        addr[c-'A']=c;
        sleep(1);
        syn.Wakeup();
    }

    ShmDetach(addr);
    std::cout << "Detach shm success, addr: " << ToHEX((uint64_t)addr) << std::endl;
    
    return 0;
}

解釋

獲取鍵值和創(chuàng)建共享內(nèi)存

Linux--進(jìn)程間的通信-共享內(nèi)存,Linux,linux,數(shù)據(jù)庫,運(yùn)維

如果ftok函數(shù)返回失敗時(shí),我們就需要不斷的嘗試,對路徑名和id值進(jìn)行修改,直至成功。一般來說,有幾種可能:

  • 1:如果傳入的路徑名不存在
  • 2:傳入的路徑名沒有讀取權(quán)限,無法讀取該文件的索引節(jié)點(diǎn)號
  • 3:文件的索引節(jié)點(diǎn)超過了8位,即超過了一個(gè)字節(jié)的范圍
  • 4:系統(tǒng)中已經(jīng)使用了所有的IPC鍵值

Linux--進(jìn)程間的通信-共享內(nèi)存,Linux,linux,數(shù)據(jù)庫,運(yùn)維
Linux--進(jìn)程間的通信-共享內(nèi)存,Linux,linux,數(shù)據(jù)庫,運(yùn)維
Linux--進(jìn)程間的通信-共享內(nèi)存,Linux,linux,數(shù)據(jù)庫,運(yùn)維
Linux--進(jìn)程間的通信-共享內(nèi)存,Linux,linux,數(shù)據(jù)庫,運(yùn)維
Linux--進(jìn)程間的通信-共享內(nèi)存,Linux,linux,數(shù)據(jù)庫,運(yùn)維

刪除共享內(nèi)存

Linux--進(jìn)程間的通信-共享內(nèi)存,Linux,linux,數(shù)據(jù)庫,運(yùn)維
Linux--進(jìn)程間的通信-共享內(nèi)存,Linux,linux,數(shù)據(jù)庫,運(yùn)維

查看共享內(nèi)存的狀態(tài)

Linux--進(jìn)程間的通信-共享內(nèi)存,Linux,linux,數(shù)據(jù)庫,運(yùn)維
Linux--進(jìn)程間的通信-共享內(nèi)存,Linux,linux,數(shù)據(jù)庫,運(yùn)維
Linux--進(jìn)程間的通信-共享內(nèi)存,Linux,linux,數(shù)據(jù)庫,運(yùn)維

掛接進(jìn)程

Linux--進(jìn)程間的通信-共享內(nèi)存,Linux,linux,數(shù)據(jù)庫,運(yùn)維
Linux--進(jìn)程間的通信-共享內(nèi)存,Linux,linux,數(shù)據(jù)庫,運(yùn)維
Linux--進(jìn)程間的通信-共享內(nèi)存,Linux,linux,數(shù)據(jù)庫,運(yùn)維
Linux--進(jìn)程間的通信-共享內(nèi)存,Linux,linux,數(shù)據(jù)庫,運(yùn)維

進(jìn)入通信

Linux--進(jìn)程間的通信-共享內(nèi)存,Linux,linux,數(shù)據(jù)庫,運(yùn)維

協(xié)同機(jī)制

Linux--進(jìn)程間的通信-共享內(nèi)存,Linux,linux,數(shù)據(jù)庫,運(yùn)維
Linux--進(jìn)程間的通信-共享內(nèi)存,Linux,linux,數(shù)據(jù)庫,運(yùn)維
Linux--進(jìn)程間的通信-共享內(nèi)存,Linux,linux,數(shù)據(jù)庫,運(yùn)維文章來源地址http://www.zghlxwxcb.cn/news/detail-858535.html

到了這里,關(guān)于Linux--進(jìn)程間的通信-共享內(nèi)存的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【Linux】進(jìn)程間通信——管道/共享內(nèi)存

    【Linux】進(jìn)程間通信——管道/共享內(nèi)存

    進(jìn)程間通信( Inter-Process Communication,簡稱IPC )是指不同進(jìn)程之間進(jìn)行數(shù)據(jù)交換和共享信息的機(jī)制和技術(shù)。在操作系統(tǒng)中,每個(gè)進(jìn)程都是獨(dú)立運(yùn)行的,有自己的地址空間和數(shù)據(jù),因此進(jìn)程之間需要一種機(jī)制來進(jìn)行通信,以便彼此協(xié)調(diào)工作、共享數(shù)據(jù)或者進(jìn)行同步操作。 進(jìn)程間

    2024年02月16日
    瀏覽(25)
  • 【Linux】進(jìn)程間通信之共享內(nèi)存

    【Linux】進(jìn)程間通信之共享內(nèi)存

    共享內(nèi)存比管道快哦~ 文章目錄 前言 一、共享內(nèi)存的實(shí)現(xiàn)原理 二、實(shí)現(xiàn)共享內(nèi)存的代碼 總結(jié) 共享內(nèi)存區(qū)是最快的IPC形式。一旦這樣的內(nèi)存映射到共享它的進(jìn)程的地址空間,這些進(jìn)程間數(shù)據(jù)傳遞不再涉及到內(nèi)核,換句話說是進(jìn)程不再通過執(zhí)行進(jìn)入內(nèi)核的系統(tǒng)調(diào)用來傳遞彼此的

    2024年02月03日
    瀏覽(22)
  • Linux 共享內(nèi)存mmap,進(jìn)程通信

    Linux 共享內(nèi)存mmap,進(jìn)程通信

    進(jìn)程間通信是操作系統(tǒng)中重要的概念之一,使得不同的進(jìn)程可以相互交換數(shù)據(jù)和進(jìn)行協(xié)作。其中,共享內(nèi)存是一種高效的進(jìn)程間通信機(jī)制,而內(nèi)存映射(mmap)是實(shí)現(xiàn)共享內(nèi)存的一種常見方法。 存儲映射 I/O 是 一個(gè)磁盤文件 與 存儲空間中的一個(gè)緩沖區(qū)相映射 。于是, 當(dāng)從緩

    2024年02月13日
    瀏覽(26)
  • 進(jìn)程間通信--共享內(nèi)存詳解【Linux】

    進(jìn)程間通信--共享內(nèi)存詳解【Linux】

    本文詳細(xì)講解了共享內(nèi)存的原理和使用,并且通過實(shí)例代碼角度來深度理解共享內(nèi)存,下面就讓我們開始吧。 數(shù)據(jù)傳輸:一個(gè)進(jìn)程需要將它的數(shù)據(jù)發(fā)送給另一個(gè)進(jìn)程 資源共享:多個(gè)進(jìn)程之間共享同樣的資源。 通知事件:一個(gè)進(jìn)程需要向另一個(gè)或一組進(jìn)程發(fā)送消息,通知它(

    2024年02月02日
    瀏覽(26)
  • (26)Linux 進(jìn)程通信之共享內(nèi)存(共享儲存空間)

    (26)Linux 進(jìn)程通信之共享內(nèi)存(共享儲存空間)

    共享內(nèi)存是System V版本的最后一個(gè)進(jìn)程間通信方式。 共享內(nèi)存,顧名思義就是允許兩個(gè)不相關(guān)的進(jìn)程訪問同一個(gè)邏輯內(nèi)存,共享內(nèi)存是兩個(gè)正在運(yùn)行的進(jìn)程之間共享和傳遞數(shù)據(jù)的一種非常有效的方式。不同進(jìn)程之間共享的內(nèi)存通常為同一段物理內(nèi)存。進(jìn)程可以將同一段物理內(nèi)

    2024年01月16日
    瀏覽(24)
  • 【hello Linux】進(jìn)程間通信——共享內(nèi)存

    【hello Linux】進(jìn)程間通信——共享內(nèi)存

    目錄 前言: 1. System V共享內(nèi)存 1. 共享內(nèi)存的理解 2. 共享內(nèi)存的使用步驟 3. 共享內(nèi)存的使用 ????????1. 共享內(nèi)存的創(chuàng)建 ????????查看共享內(nèi)存 ????????2. 共享內(nèi)存的釋放 ????????3. 共享內(nèi)存的掛接 ????????4. 共享內(nèi)存的去掛接 4. 共享內(nèi)存的使用示例 1. 兩進(jìn)

    2024年02月01日
    瀏覽(34)
  • 【Linux】進(jìn)程間通信——system V共享內(nèi)存

    【Linux】進(jìn)程間通信——system V共享內(nèi)存

    目錄 ?寫在前面的話 System V共享內(nèi)存原理 System V共享內(nèi)存的建立 代碼實(shí)現(xiàn)System V共享內(nèi)存 創(chuàng)建共享內(nèi)存shmget() ftok() 刪除共享內(nèi)存shmctl() 掛接共享內(nèi)存shmat() 取消掛接共享內(nèi)存shmdt() 整體通信流程的實(shí)現(xiàn) ???????? 上一章我們講了進(jìn)程間通信的第一種方式 --- 管道,這一章我

    2024年02月14日
    瀏覽(29)
  • 【Linux】進(jìn)程間通信 -- system V共享內(nèi)存

    【Linux】進(jìn)程間通信 -- system V共享內(nèi)存

    共享內(nèi)存區(qū)是最快的IPC形式。一旦這樣的內(nèi)存映射到共享它的進(jìn)程的地址空間,這些進(jìn)程間數(shù)據(jù)傳遞不再涉及到內(nèi)核,換句話說是進(jìn)程不再通過執(zhí)行進(jìn)入內(nèi)核的系統(tǒng)調(diào)用來傳遞彼此的數(shù)據(jù) 理解: 進(jìn)程間通信,是專門設(shè)計(jì)的,用來IPC 共享內(nèi)存是一種通信方式,所有想通信的進(jìn)程

    2024年02月16日
    瀏覽(29)
  • Linux學(xué)習(xí)記錄——?? 進(jìn)程間通信(2)共享內(nèi)存

    Linux學(xué)習(xí)記錄——?? 進(jìn)程間通信(2)共享內(nèi)存

    system是一套標(biāo)準(zhǔn),獨(dú)立于文件系統(tǒng)之外,是系統(tǒng)專門為通信而設(shè)計(jì)出來的內(nèi)核模塊,稱之為system V的IPC通信機(jī)制。 共享內(nèi)存的主要做法也是讓兩個(gè)毫不相關(guān)的進(jìn)程看到同一份資源。 進(jìn)程的地址空間內(nèi),棧和堆區(qū)之間有個(gè)共享區(qū),堆是向上增長,棧是向下增長,重合的那個(gè)地方

    2023年04月24日
    瀏覽(19)
  • 【Linux】進(jìn)程間通信之共享內(nèi)存/消息隊(duì)列/信號量

    【Linux】進(jìn)程間通信之共享內(nèi)存/消息隊(duì)列/信號量

    共享內(nèi)存是通過讓不同的進(jìn)程看到同一個(gè)內(nèi)存塊的方式。 我們知道,每一個(gè)進(jìn)程都會(huì)有對應(yīng)的PCB-task_struct ,獨(dú)立的進(jìn)程地址空間,然后通過頁表將地址映射到物理內(nèi)存中。此時(shí)我們就可以讓OS在內(nèi)存中申請一塊空間,然后將創(chuàng)建好的內(nèi)存空間映射到進(jìn)程的地址空間中,兩個(gè)需

    2024年02月05日
    瀏覽(28)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包