【Linux】SystemV共有メモリ

序文

コンテンツ

System Vは、かつてAT&T System Vとも呼ばれていましたが、Unixオペレーティングシステムの多くのバージョンの1つです。

System Vには、メッセージキュー、共有スペース、セマフォの3つの高レベルのプロセス間通信メカニズムが導入されています。

共有メモリはプロセス間通信の最速の方法です。その理由は、通信するプロセスpcbのアドレス空間の共有領域が同時に物理メモリの一部にマップされ、その上のデータが直接であるためです。仮想アドレスを介して検出およびアクセスされます。これらのプロセス間データ転送不再涉及到内核的系统接口的调用

共有メモリを申請した後、プロセス1とプロセス2はそれぞれ、対応する共有メモリをそれぞれのアドレス空間に接続し、正常に通信できます。

パイプベースのプロセス間通信の場合、読み取りや書き込みなどのシステムインターフェイスを呼び出す必要があります。書き込み側は最初にカーネルのファイルバッファにデータを書き込み、読み取り側はバッファから読み取ります。これらの操作はすべてシステムインターフェイスを呼び出します。

つまり、プロセスは、カーネルに入るシステムコールを実行することによって、互いのデータを渡さなくなります。

ここに画像の説明を挿入

1.共有メモリのデータ構造

struct shmid_ds {
    
    
	struct ipc_perm shm_perm; /* operation perms */
	int shm_segsz; /* size of segment (bytes) */
	__kernel_time_t shm_atime; /* last attach time */
	__kernel_time_t shm_dtime; /* last detach time */
	__kernel_time_t shm_ctime; /* last change time */
	__kernel_ipc_pid_t shm_cpid; /* pid of creator */
	__kernel_ipc_pid_t shm_lpid; /* pid of last operator */
	unsigned short shm_nattch; /* no. of current attaches */
	unsigned short shm_unused; /* compatibility */
	void *shm_unused2; /* ditto - used by DIPC */
	void *shm_unused3; /* unused */
};

2.共有メモリ機能

  • 共有メモリを作成する
int shmget(key_t key, size_t size, int shmflg);

パラメータ
キー:共有メモリセグメントの名前
サイズ:共有メモリのサイズ
shmflg:9つのパーミッションフラグで構成され、それらの使用法はファイルの作成時に使用されるモードフラグと同じです
戻り値:負でない整数を正常に返します、つまり、共有メモリメモリの識別コード。失敗する
と、shmflgで-1が返されます。
ここに画像の説明を挿入

  • キーの生成キー
    はftok関数によって取得され、共有メモリの一意の識別コードを返しますshmid
key_t ftok(const char *pathname, int proj_id);
  • 共有メモリセグメントをプロセスアドレス空間に接続します
void *shmat(int shmid, const void *shmaddr, int shmflg);

パラメータ
shmid:共有メモリ識別子
shmaddr:接続のアドレスを指定します
shmflg:その2つの可能な値はSHM_RNDとSHM_RDONLYで、通常は0に設定されます
戻り値:ヒープ上のスペースを開くmallocと同様に、ポインタを正常に返します;失敗-1を返します

  • 共有メモリからプロセスアドレス空間をアンバインドします
int shmdt(const void *shmaddr);

パラメータ
shmaddr:shmatによって返されるポインタ
戻り値:成功した場合は0、失敗した場合は-1
注:現在のプロセスから共有メモリセグメントを切り離しても、共有メモリセグメントを削除することにはなりません。
プロセス時にipcリソースは解放されません。終了しますが、プロセスに従います。カーネルは、シャットダウンするか、systeminterfacefree
コマンドを使用して共有メモリを解放します。ipcrm shmid

  • 共有メモリの制御に使用されます
int shmctl(int shmid, int cmd, struct shmid_ds *buf);

パラメータ
shmid:shmget
cmdによって返される共有メモリ識別コード:実行するアクション(3つの可能な値があります)
buf:共有メモリのモードステータスとアクセス権を保存するデータ構造を指します
戻り値:成功は0を返し、失敗は戻ります-1
ここに画像の説明を挿入

3.コマンドラインビュー共有メモリ

ipcs -m

ここに画像の説明を挿入
shmid:共有メモリ番号
所有者:作成者
perms:許可
バイト:サイズ
nattch:接続されているプロセスの数
ステータス:「dest」が表示され、共有メモリセグメントが削除されたことを示しますが、それを使用しているユーザーはまだいます。フィールドがSHM_DESTに設定されている場合、メモリのこのセグメントのモード「dest」が表示されます。

4.実験:サーバーとクライアントの通信

実験現象
ここに画像の説明を挿入

  • common.h
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#define PATH_NAME  "/root/class101/linux/lesson20/sharememory" 
#define PROJ_ID 18733213
#define SIZE 4097
  • server.c
#include "common.h"
int main() {
    
    
  key_t key = ftok(PATH_NAME, PROJ_ID);
  if(key == -1) {
    
    
    perror("ftok");
    return 1;
  }

  printf("key: %x\n", key);

  int shmid = shmget(key, SIZE, IPC_CREAT|IPC_EXCL|0644);

  if(shmid == -1) {
    
    
    perror("shmget");
    return 2;
  }

  printf("shmid: %d\n", shmid);
  sleep(5);


  char* start = (char*)shmat(shmid, NULL, 0);
  if(start == (void*)-1) {
    
    
    perror("shmat");
    return 3;
  }
  printf("shmat success...\n");
  sleep(5);
  while(1) {
    
    
    printf("%s\n", start);
    sleep(1);
  }


  shmdt(start);
  sleep(5);
  shmctl(shmid, IPC_RMID, NULL);
  return 0;
}
  • client.c
#include "common.h"
int main(){
    
    
  
  key_t key = ftok(PATH_NAME, PROJ_ID);
  if(key == -1) {
    
    
    perror("ftok");
    return 1;
  }

  int shmid = shmget(key, SIZE, IPC_CREAT);
  if(shmid == -1) {
    
    
    perror("shmget");
    return 2;
  }

  sleep(5);
  char* start = (char*)shmat(shmid, NULL, 0);
  if(start == (void*)-1) {
    
    
    perror("shmat");
    return 3;
  }
  sleep(5);


  char ch = 'A';
  while(ch<='Z') {
    
    
    start[ch-'A'] = ch;
    ch++;
    sleep(1);
  }

  shmdt(start);
  printf("%x\n", key);
  return 0;
} 
  • Makefile
CC=gcc
all: server client
server: server.c
	$(CC) -o $@ $^
client: client.c
	$(CC) -o $@ $^
.PHONY: clean
clean: 
	rm -f server client

サーバーは無限ループで印刷するため、最終的に共有メモリを手動で解放する必要があります。
ここに画像の説明を挿入

ipcrm -m 327680

5.メモ/繰り返し

1.共有メモリ機能

共有メモリ共有メモリ生命周期随OS
操作。共有メモリはすべてのプロセス間通信で使用されます。共有メモリを作成するための推奨サイズは4KBの整数倍です。それ以外の場合、システムは4KBに従って調整されます。不提供任何同步与互斥双方彼此独立
速度最快的

二、キー対シュミット

key:ユーザー層によって生成される一意のキー値です。コア機能は一意性を区別することであり、IPCリソースの操作には使用できません
。shmid:システムから返されるIPCリソース識別子であり、操作に使用されます。 IPCリソース。

  • 複数のプロセスが同じ共有メモリを確実に認識できるようにするにはどうすればよいですか?
    キーによる独自の区別
  • AとBが同じキーを使用するようにするにはどうすればよいですか?
    key_t ftok(const char * pathname、int proj_id)

3.システムインターフェース

システムでは、ipcを表示するコマンドはipcs

所有ipc资源都是随内核はい、プロセスの終了時にインターフェイスが解放/ OSの再起動を要求されない限り、プロセスの終了時に自動的に解放されることはありません。

コマンドリリースipc

ipcrm -m shmid

第四に、ルーチン

//キーを作成します

key_t ftok(pathname, proj_id);

//共有メモリを作成します

int shmid = shmget(key, SIZE, IPC_CREAT  | IPC_EXCL | 0644);

//共有メモリフックプロセス

char* start = shmat(shmid, NULL, 0);

//リンクを解除します

shmdt(start);

//解放されました

shmctl(shmid, IPC_RMID, NULL);

おすすめ

転載: blog.csdn.net/m0_52640673/article/details/123280222