欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Linux之進(jìn)程間通信(共享內(nèi)存【mmap實(shí)現(xiàn)+系統(tǒng)V】)

 更新時(shí)間:2023年03月23日 15:37:31   作者:Dutkig  
這篇文章主要介紹了Linux之進(jìn)程間通信(共享內(nèi)存【mmap實(shí)現(xiàn)+系統(tǒng)V】),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

共享內(nèi)存

  • 共享內(nèi)存可以說(shuō)是最有用的進(jìn)程間通信方式,也是最快的IPC形式,兩個(gè)不同的進(jìn)程A、B共享內(nèi)存的意思就是:同一塊物理內(nèi)存被映射到進(jìn)程A、B各自的進(jìn)程地址空間,進(jìn)程A可以同時(shí)看到進(jìn)程B對(duì)共享內(nèi)存中數(shù)據(jù)的更新,反之亦然。
  • 由于個(gè)多個(gè)進(jìn)程共享同一塊內(nèi)存區(qū)域,必然需要某種同步機(jī)制、互斥鎖和信號(hào)量都可以。

好處: 效率高,進(jìn)程可以直接讀寫(xiě)內(nèi)存,而不需要復(fù)制任何數(shù)據(jù),而管道、消息隊(duì)列等通信方式,則需要在內(nèi)核和用戶空間進(jìn)行四次數(shù)據(jù)復(fù)制。

并且只有在解除映射時(shí),共享內(nèi)存的內(nèi)容才會(huì)寫(xiě)會(huì)文紀(jì)念

共享內(nèi)存通過(guò)內(nèi)核對(duì)象,使得不同的進(jìn)程在自己的虛擬地址空間上分配一塊空間映射到相同的物理內(nèi)存空間上,這塊物理內(nèi)存空間對(duì)于映射到上面的每個(gè)進(jìn)程而言都是可以訪問(wèn)的。(臨界資源)

共享內(nèi)存就是允許兩個(gè)不相關(guān)的進(jìn)程訪問(wèn)同一個(gè)邏輯內(nèi)存。

共享內(nèi)存是在兩個(gè)正在運(yùn)行的進(jìn)程之間共享和傳遞數(shù)據(jù)的一種非常有效的方式。

不同進(jìn)程之間共享的內(nèi)存通常安排為同一段物理內(nèi)存。

進(jìn)程可以將同一段共享內(nèi)存連接到它們自己的地址空間中,所有進(jìn)程都可以訪問(wèn)共享內(nèi)存中的地址,就好像它們是由用C語(yǔ)言函數(shù)malloc()分配的內(nèi)存一樣。

而如果某個(gè)進(jìn)程向共享內(nèi)存寫(xiě)入數(shù)據(jù),所做的改動(dòng)將立即影響到可以 訪問(wèn)同一段共享內(nèi)存的任何其他進(jìn)程。

mmap()及其相關(guān)的系統(tǒng)調(diào)用

mmap是linux操作系統(tǒng)提供給用戶空間調(diào)用的內(nèi)存映射函數(shù),很多人僅僅只是知道可以通過(guò)mmap完成進(jìn)程間的內(nèi)存共享和減少用戶態(tài)到內(nèi)核態(tài)的數(shù)據(jù)拷貝次數(shù),但是并沒(méi)有深入理解mmap在操作系統(tǒng)內(nèi)部是如何實(shí)現(xiàn)的,原理是什么

mmap()系統(tǒng)調(diào)用使得進(jìn)程之間可以通過(guò)映射同一個(gè)普通文件實(shí)現(xiàn)內(nèi)存共享。普通文件被映射到進(jìn)程地址空間后,進(jìn)程可以訪問(wèn)普通內(nèi)存一樣對(duì)文件進(jìn)行訪問(wèn),不必再調(diào)用read和write操作。 

注意: mmap并不是完全為了IPC而設(shè)計(jì)的,只是IPC的一種應(yīng)用方式,它本身提供了一種像訪問(wèn)普通內(nèi)存一樣的訪問(wèn)對(duì)普通文件進(jìn)行操作的方式。

通過(guò)使用帶有特殊權(quán)限集的虛擬內(nèi)存段來(lái)實(shí)現(xiàn)。對(duì)這類(lèi)虛擬內(nèi)存段的讀寫(xiě)會(huì)使操作系統(tǒng)去讀寫(xiě)磁盤(pán)文件中與之對(duì)應(yīng)的部分。

mmap 函數(shù)創(chuàng)建一個(gè)指向一段內(nèi)存區(qū)域的指針,該內(nèi)存區(qū)域與可以通過(guò)一個(gè)打開(kāi)的文件描述符訪問(wèn)的文件的內(nèi)容相關(guān)聯(lián)

解釋如下:

mmap()

#include <sys/mman.h>

void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);

可以通過(guò)傳遞 offset 參數(shù)來(lái)改變經(jīng)共享內(nèi)存段訪問(wèn)的文件中數(shù)據(jù)的起始偏移值。

打開(kāi)的文件描述符由 fd 參數(shù)給出。

可以訪問(wèn)的數(shù)據(jù)量(即內(nèi)存段的長(zhǎng)度)由 length 參數(shù)設(shè)置。

可以通過(guò) addr 參數(shù)來(lái)請(qǐng)求使用某個(gè)特定的內(nèi)存地址。如果它的取值是零,結(jié)果指針就將自動(dòng)分配。這是推薦的做法,否則會(huì)降低程序的可移植性,因?yàn)椴煌到y(tǒng)上的可用地址范圍是不一樣的。

prot 參數(shù)用于設(shè)置內(nèi)存段的訪問(wèn)權(quán)限。它是下列常數(shù)值的按位或的結(jié)果

  • PROT_READ 內(nèi)存段可讀。
  • PROT_WRITE 內(nèi)存段可寫(xiě)。
  • PROT_EXEC 內(nèi)存段可執(zhí)行。
  • PROT_NONE 內(nèi)存段不能被訪問(wèn)。

flags 參數(shù)控制程序?qū)υ搩?nèi)存段的改變所造成的影響:

mmap()用于共享內(nèi)存的量和兩種方式如下:

使用普通文件提供的內(nèi)存映射,適用于任何進(jìn)程間,使用該方式需要先打開(kāi)或者創(chuàng)建一個(gè)文件,再調(diào)用ngmmap,典型調(diào)用代碼如下:

fd = open(name.falg.mode);
if(fd < 0)
ptr = mmap(NULL,len.PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);

使用特殊文件提供的內(nèi)存映射,適用于具有親緣關(guān)系的進(jìn)程之間,由于父子進(jìn)程特殊的親緣關(guān)系,在父進(jìn)程中先調(diào)用mmap,調(diào)用fork,那么在代用fork之后,子進(jìn)程可以繼承父進(jìn)程匿名映射后的地址空間,同樣也繼承mmap返回的地址,這樣父子進(jìn)程就可以通過(guò)映射區(qū)域進(jìn)行通信了。(注意:一般來(lái)說(shuō),子進(jìn)程單獨(dú)維護(hù)從父進(jìn)程繼承而來(lái)的一些變量,而mmap()返回的地址由父子進(jìn)程共同維護(hù))【具體使用實(shí)現(xiàn)敬請(qǐng)期待博主整理】

munmap()

用于解除內(nèi)存映射,取消參數(shù)start所指的映射內(nèi)存的起始地址,參數(shù)length則是欲取消的內(nèi)存大小,當(dāng)進(jìn)程結(jié)束或者利用exec相關(guān)函數(shù)來(lái)執(zhí)行其他程序時(shí),映射內(nèi)存會(huì)自動(dòng)解除,但關(guān)閉對(duì)應(yīng)的文件描述符時(shí)不會(huì)解除映射。

#include <sys/mman.h>

int munmap(void *addr, size_t length);

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

與信號(hào)量一樣,在Linux中也提供了一組函數(shù)接口用于使用共享內(nèi)存,而且使用共享共存的接口還與信號(hào)量的非常相似,而且比使用信號(hào)量的接口來(lái)得簡(jiǎn)單。它們聲明在頭文件 sys/shm.h 中。 

1.獲取或創(chuàng)建內(nèi)核對(duì)象,并且制定共享內(nèi)存的大?。ㄏ到y(tǒng)分配物理空間是,按照頁(yè)進(jìn)行分配)

int shmget(key_t key, int size, int flag);

只是創(chuàng)建內(nèi)核對(duì)象,并申請(qǐng)物理空間

  • key_t key:與信號(hào)量的semget函數(shù)一樣,程序需要提供一個(gè)參數(shù)key(非0整數(shù)),它有效地為共享內(nèi)存段命名,不同的進(jìn)程通過(guò)相同的key值來(lái)訪問(wèn)同一塊共享內(nèi)存
  • int size:size以字節(jié)為單位指定需要共享的內(nèi)存容量
  • int flag:falg是權(quán)限標(biāo)志,它的作用與open函數(shù)的mode參數(shù)一樣,如果要想在key標(biāo)識(shí)的共享內(nèi)存不存在時(shí),創(chuàng)建它的話,可以與IPC_CREAT做或操作。共享內(nèi)存的權(quán)限標(biāo)志與文件的讀寫(xiě)權(quán)限一樣,舉例來(lái)說(shuō),0644,它表示允許一個(gè)進(jìn)程創(chuàng)建的共享內(nèi)存被內(nèi)存創(chuàng)建者所擁有的進(jìn)程向共享內(nèi)存讀取和寫(xiě)入數(shù)據(jù),同時(shí)其他用戶創(chuàng)建的進(jìn)程只能讀取共享內(nèi)存。

返回值

  • shmget()函數(shù)成功時(shí)返回一個(gè)與key相關(guān)的共享內(nèi)存標(biāo)識(shí)符(非負(fù)整數(shù)),用于后續(xù)的共享內(nèi)存函數(shù)。
  • 調(diào)用失敗返回-1.

2.分配自己虛擬地址空間映射到共享內(nèi)存的物理空間上

void *shmat(int shmid,const void *addr, int flag);
  • shmid:shmid是由shmget()函數(shù)返回的共享內(nèi)存標(biāo)識(shí)。
  • void *addr:addr指定共享內(nèi)存連接到當(dāng)前進(jìn)程中的地址位置,通常為NULL,表示讓系統(tǒng)來(lái)選擇共享內(nèi)存的地址。
  • int flag:flag是一組標(biāo)志位,通常為0。

調(diào)用成功時(shí)返回一個(gè)指向共享內(nèi)存第一個(gè)字節(jié)的指針,如果調(diào)用失敗返回-1.

3.斷開(kāi)當(dāng)前進(jìn)程與共享內(nèi)存的映射

不使用刪除而使用斷開(kāi)的原因是因?yàn)椋阂苍S還存在其他的進(jìn)程會(huì)繼續(xù)使用這塊共享內(nèi)存

int shmdt(const void *addr);

4.操作共享內(nèi)存的方法

int shmctl(int shmid, int cmd, struct shmid_t *buf);
  • int shmid:shmid是shmget()函數(shù)返回的共享內(nèi)存標(biāo)識(shí)符。
  • int cmd:command是要采取的操作,它可以取下面的三個(gè)值 :

IPC_STAT:把shmid_ds結(jié)構(gòu)中的數(shù)據(jù)設(shè)置為共享內(nèi)存的當(dāng)前關(guān)聯(lián)值,即用共享內(nèi)存的當(dāng)前關(guān)聯(lián)值覆蓋shmid_ds的值。

IPC_SET:如果進(jìn)程有足夠的權(quán)限,就把共享內(nèi)存的當(dāng)前關(guān)聯(lián)值設(shè)置為shmid_ds結(jié)構(gòu)中給出的值

IPC_RMID:刪除共享內(nèi)存段

  • struct shmid_t *buf:buf是一個(gè)結(jié)構(gòu)指針,它指向共享內(nèi)存模式和訪問(wèn)權(quán)限的結(jié)構(gòu)

因?yàn)橛羞B接計(jì)數(shù)器,除非最后一個(gè)進(jìn)程與該共享段斷開(kāi)連接,則刪除該共享段。否則,并不會(huì)真正刪除該共享段,但是共享內(nèi)存的內(nèi)核對(duì)象會(huì)被立即刪除,不能使用shmat方法與該段連接。 

一個(gè)進(jìn)程調(diào)用該方法刪除后,不會(huì)影響之前已經(jīng)和該共享存儲(chǔ)段連接的進(jìn)程

下面我們利用共享內(nèi)存來(lái)進(jìn)行一個(gè)簡(jiǎn)單的測(cè)試:

完成下面的過(guò)程,

成功在共享內(nèi)存中讀到了數(shù)據(jù)

 

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<unistd.h>

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

#include"sem.h"

#define READSEM 1
#define WRITESEM 0

int main()
{
	int shmid = shmget((key_t)1234,128,0664 | IPC_CREAT);
	assert(shmid != -1);

	char *ptr = (char*)shmat(shmid,NULL,0);
	assert(ptr != (char*)-1);
	
	int initVal[] = {1,0};
	int semid = SemGet(1234,intVal,2);
	assert(semid != -1);
	
	//A進(jìn)程寫(xiě)
	while(1)
	{
		SemP(semid,WRITESEM);
		printf("Input:");
		
		fgets(ptr,127,stdin);
		
		SemV(semid,READSEM);
		
		if(strncmp(ptr,"end",3) == 0)
		{
			break;
		}
	}
	
	shmdt(ptr);
	exit(0);
}
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<unistd.h>

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

#include"sem.h"

#define READSEM 1
#define WRITESEM 0

int main()
{
	int shmid = shmget((key_t)1234,128,0664 | IPC_CREAT);
	assert(shmid != -1);

	char *ptr = (char*)shmat(shmid,NULL,0);
	assert(ptr != (char*)-1);
	
	int initVal[] = {1,0};
	int semid = SemGet(1234,intVal,2);
	assert(semid != -1);
	
	//B進(jìn)程讀
	while(1)
	{
		SemP(semid,READSEM);
		
		if(strncmp(ptr,"end",3) == 0)
		{
			break;
		}
		
		int i = 0;
		for(;i < strlen(ptr) - 1;i++)
		{
			printf("%c",toupper(ptr[i]));
			fflush(stdout);
			sleep(1);
		}
		printf("\n");
		SemV(semid,WRITESEM);
	}
	
	shmdt(ptr);
	exit(0);
}

從上面的代碼中我們可以看出: 

共享內(nèi)存是最快的IPC,在通信過(guò)程中少了兩次數(shù)據(jù)的拷貝。(相較于管道)

命令管理共享內(nèi)存

  • 查看 ipcs -m
  • 刪除 ipcrm -m shmid

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 阿里云云服務(wù)器Linux系統(tǒng)掛載數(shù)據(jù)盤(pán)圖文教程

    阿里云云服務(wù)器Linux系統(tǒng)掛載數(shù)據(jù)盤(pán)圖文教程

    這篇文章主要介紹了阿里云云服務(wù)器Linux系統(tǒng)掛載數(shù)據(jù)盤(pán)圖文教程,阿里云服務(wù)器一般需要購(gòu)買(mǎi)額外的數(shù)據(jù)盤(pán),本文就講解如何掛載使用額外的數(shù)據(jù)盤(pán),需要的朋友可以參考下
    2014-09-09
  • linux中chmod命令用法詳解

    linux中chmod命令用法詳解

    在本篇文章里小編給大家分享了關(guān)于linux中chmod命令用法和相關(guān)知識(shí)點(diǎn),需要的朋友們跟著學(xué)習(xí)下。
    2019-04-04
  • Ubuntu16.04安裝clion全過(guò)程及步驟詳解

    Ubuntu16.04安裝clion全過(guò)程及步驟詳解

    這篇文章主要介紹了Ubuntu16.04安裝clion全過(guò)程及步驟詳解,clion是一款JetBrains 推出的全新的 C/C++ 跨平臺(tái)集成開(kāi)發(fā)環(huán)境,在Ubuntu系統(tǒng)下使用方便,下面給大家分享操作步驟,需要的朋友可以參考下
    2020-08-08
  • 分享三種Apache配置虛擬主機(jī)的方式

    分享三種Apache配置虛擬主機(jī)的方式

    這篇文章主要為大家分享了三種Apache配置虛擬主機(jī)的方式,感興趣的小伙伴們可以參考一下
    2016-04-04
  • Linux之進(jìn)程的虛擬地址空間,邏輯地址和物理地址,進(jìn)程管理命令

    Linux之進(jìn)程的虛擬地址空間,邏輯地址和物理地址,進(jìn)程管理命令

    這篇文章主要介紹了Linux之進(jìn)程的虛擬地址空間,邏輯地址和物理地址,進(jìn)程管理命令,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • linux下安裝nginx(圖文教程)

    linux下安裝nginx(圖文教程)

    本篇文章主要介紹了linux下安裝nginx,Nginx是一款輕量級(jí)的Web服務(wù)器。有需要的朋友可以了解一下。
    2016-11-11
  • Linux下apache如何限制并發(fā)連接和下載速度

    Linux下apache如何限制并發(fā)連接和下載速度

    在Linux下限值A(chǔ)pache的并發(fā)連接數(shù)和下載速度需要用到一款A(yù)pache的擴(kuò)展模塊mod_limitipconn,下面我們就來(lái)討論mod_limitipconn的安裝使用方法
    2014-11-11
  • linux操作之清空文件方式

    linux操作之清空文件方式

    這篇文章主要介紹了linux操作之清空文件方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • Linux服務(wù)器配置—搭建NFS服務(wù)器步驟

    Linux服務(wù)器配置—搭建NFS服務(wù)器步驟

    本文介紹linux服務(wù)器配置之如何搭建NFS服務(wù)器,供大家學(xué)習(xí)參考
    2013-02-02
  • Nagios的安裝與使用詳細(xì)教程

    Nagios的安裝與使用詳細(xì)教程

    Nagios是一款開(kāi)源的電腦系統(tǒng)和網(wǎng)絡(luò)監(jiān)視工具,能有效監(jiān)控Windows、Linux和Unix的主機(jī)狀態(tài),交換機(jī)路由器等網(wǎng)絡(luò)設(shè)置,打印機(jī)等,接下來(lái)通過(guò)本文給大家介紹Nagios的安裝與使用詳細(xì)教程,需要的朋友參考下
    2016-02-02

最新評(píng)論