VS2019 C ++(1.5)に基づくクロスプラットフォーム(Linux)開発-共有メモリ

I.はじめに

        以前のパイプライン学習では、名前付きパイプを使用して2つの.fifoファイルを生成しました。ユーザーがテクノロジーを理解していない場合、このファイルが役に立たないと思われる場合は、名前付きパイプを削除する可能性があります。さらに、パイプ(名前付きパイプまたは無名パイプ)が保持できる最大データ(65535バイト)が制限されているため、パイプにデータを書き込み続けます。この容量を超えると、パイプは次のようになる可能性があります。破損しています。(水道管が運ぶことができる水の量が限られているように、一定の水圧を超えると破裂する可能性があります)、要約すると、パイプは誤って削除されやすく、パイプの容量は上限。次に、次のステップは共有メモリを含みます。

2.共有メモリの概要

        共有メモリは、プロセスのアドレス空間に表示されるプロセス用にIPCによって作成された特別なアドレス範囲です。他のプロセスは、同じ共有メモリセグメントを独自のアドレス空間に「リンク」できます。以下に示すように

①上図の共有メモリは、AまたはBのいずれかのプロセスで作成できます。ただし、プロセスには属しておらず(AにもBにも属していない)、オペレーティングシステム自体に属しています。

②AプロセスとBプロセスの両方が、mallocによって割り当てられたかのように共有メモリアドレスにアクセスできます。

③プロセスAがこの共有メモリにデータを書き込む場合、変更は、ここのプロセスBなど、同じ共有メモリにアクセスできる他のプロセスによってすぐに確認されます。

        それは実際には共有自転車と共有充電の宝物として想像することができます。まず、どちらもユーザーのものではありません。次に、誰もがそれを使用する権利があります。最後に、前のユーザーがそれを壊し、2番目のユーザーがたまたまそれを使用した場合、その状態は前回の状態で壊れました。具体的には、前のユーザーが使用していた共有パワーバンクが電力の30%を使用している場合、後者のユーザーがすぐに使用すると、電力の70%しか使用できなくなります。パワーバンクは充電されていません

        簡単に言えば、共有には次の3つの特徴があります。これはあなたのものではない、誰でも使用できる、後者の人は前者の操作結果を確実に見ることができるということです。

        共有メモリの概念に戻ります。つまり、このメモリはどのプロセスにも属していません。すべてのプロセスがこのメモリを使用できます。プロセスがメモリを変更すると、他のプロセスが操作の結果を確認できます。

ipcsコマンドを使用して、共有メモリ、メッセージキュー、およびセマフォを表示できます。信号とパイプは特定のプロセス空間に属しますが、これら3つはオペレーティングシステム自体に属し、プロセスが存在するかどうかは関係ありません。つまり、これら3つのことはプロセスから独立しています。プロセスが開いていない場合でも、共有メモリは存在できます(下の図を参照)。

ipcrm-mshmid指定されたIDの共有メモリを削除します

ipcm -aは、作成されたすべての共有メモリ、セマフォなどを削除します(ルートを除く)

 3.共有メモリ機能

1.shmget関数-作成

役割:共有メモリの作成に使用されます

原型:int shmget(key_t key、size_t size、int shmflg);

パラメータの説明:

  • キー:共有メモリセグメントの名前
  • サイズ:共有メモリサイズ
  • shmflg:9つの許可フラグ(読み取り、書き込み、実行-0777)で構成され、使用法はファイルの作成時に使用されるモードフラグと同じですが、umask(0)は必須ではありません。

戻り値:共有メモリが正常に作成された場合は、負でない整数、つまり共有メモリの識別コード(shm_id)を返します。失敗した場合は、「-1」を返します。 

:この関数には2つの意味があります。存在しない場合は作成し、存在する場合(キーで判断)は動作しません。

2、shmat関数-接続

機能:共有メモリセグメントが作成されたばかりの場合、プロセスはまだそれにアクセスできません。この共有メモリセグメントへのアクセスチャネルを確立するには、それを独自のプロセスのアドレス空間に接続する必要があります(自転車を共有するなど)。支払うためにコードをスキャンした後に使用します)

原型:void * shmat(int shm_id、const void * shm_addr、int shmflg);

パラメータの説明:

  • shm_id:shmgetによって返される共有メモリID
  • shm_addr:現在のプロセスに接続されているときに共有メモリが配置されるアドレス
  • shmflgは、ビットごとにOR演算されるフラグのセットです。その2つの可能な値はSHM_RNDとSHM_RDONLYです

戻り値:呼び出しが成功した場合は、共有メモリの最初のバイトを指すポインタを返します。失敗した場合は、「-1」を返します(void *は、接続するだけなので、任意のタイプを格納できることを意味します。それがどんなタイプかわかりません。)

3、shmdt関数-切断

機能:共有メモリを現在のプロセスから分離します(共有自転車の返却アクションなど)

プロトタイプ:int shmdt(const void * shm_addr);

パラメータの説明:shm_addr:shmatによって返されるアドレスポインタ

戻り値:操作が成功した場合は「0」を返し、失敗した場合は「-1」を返します。

共有メモリを残すことは、それを削除することを意味するのではなく、現在のプロセスが共有メモリにアクセスできなくなるだけです。

4.shmctl関数-削除

機能:共有メモリの制御機能(データの共有や上書きが可能で、削除する必要がないため、通常は使用しません)

原型:int shmctl(int shm_id、int command、struct shmid_ds * buf);

パラメータの説明:

  • shm_id:shmgetによって返される共有メモリ識別コード
  • コマンド:実行するアクション(3つの値:IPC_STAT、IPC_SET、IPC_RMID)
  • buf:共有メモリのモード状態とアクセス権を保持するデータ構造を指します

戻り値:操作が成功した場合は「0」を返し、失敗した場合は「-1」を返します。

 メモリ操作:

  • memsetは通常、新しく適用されたメモリを初期化します(空-bzero関数)
  • memcpyメモリコピー、データをコピーするだけで、元のデータは空になりません

4.例

        2つのアプリケーションを作成します。1つは読み取り用、もう1つは書き込み用です。

1.コード

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

//写端

typedef struct student
{
	char stuid[10];
	char name[20];

}STU;
int main()
{
	void* shmaddr = NULL;
	int shmid = 0;

	STU stu1 = { "1001","zqw"};
	//创建
	shmid = shmget((key_t)1001,2048,IPC_CREAT|0777);

	if (shmid == -1)
	{
		perror("shmget  error");
	}
	else
	{
		//连接共享内存 获取到共享内存的首地址shmaddr
		shmaddr = shmat(shmid,NULL,0);

		//写入数据  = 内存拷贝
		memcpy(shmaddr, &stu1,sizeof(STU));

		/*cout <<"res_stu  id" << res_stu.stuid<< endl;
		cout << "res_stu  name" << res_stu.name << endl;*/

		//断开共享内存的连接
		shmdt(shmaddr);
	}

	return 0;
}

//读端

typedef struct student
{
	char stuid[10];
	char name[20];

}STU;
int main()
{
	void* shmaddr = NULL;
	int shmid = 0;

	STU res_stu = { 0 };
	//创建
	shmid = shmget((key_t)1001, 2048, IPC_CREAT | 0777);

	if (shmid == -1)
	{
		perror("shmget  error");
	}
	else
	{
		//连接共享内存 获取到共享内存的首地址
		shmaddr = shmat(shmid, NULL, 0);

		//读取数据  = 内存拷贝
		memcpy(&res_stu, shmaddr, sizeof(STU));

		cout << "读端  id = " << res_stu.stuid << endl;
		cout << "读端  name = " << res_stu.name << endl;

		//断开共享内存的连接

		shmdt(shmaddr);
	}

	return 0;
}

2.実行結果 

  • 読み取り側ではデータの変更やクリアなどが行われないため、単なるコピーであり、共有メモリ内のデータはそのまま残り、複数回の読み取り結果は同じです。
  • プロセスが終了しても、共有メモリはまだ存在します。これは、共有メモリがプロセスではなくオペレーティングシステムによって直接管理されていることを示しています。
  • 共有メモリは十分に使用できます。作成後、手動で削除するまでメモリを占有します。

 ソースを示してください

VS2019 C ++(1.5)に基づくクロスプラットフォーム(Linux)開発-共有メモリ

おすすめ

転載: blog.csdn.net/hml111666/article/details/123697406