1.共有メモリの概要
1.共有メモリは、複数のプロセスによって共有される物理メモリの一部です。
2.すべてのユーザースペースプロセスが共有メモリを操作する場合、プロセス間のデータ通信を実現するために、共有メモリを独自の仮想メモリスペースにマップし、マップされた仮想メモリスペースアドレスを介して共有メモリを操作する必要があります。
3.共有メモリは、プロセス間でデータを共有するための最速の方法であり、効率的なIPCメカニズムです。
、、 API
1.共有メモリを作成します
int shmget(key_t key、size_t size、int shmflag);
パラメータ:
key:ユーザーが指定した共有メモリのキー値。
size:共有メモリのサイズ。
shmflag:IPC_CREAT、IPC_EXCL、0777およびその他の権限の組み合わせ
戻り値:成功、カーネル内の共有メモリの識別IDを返し、失敗、-1を返します。
2.共有メモリ制御
int shmctl(int shmid、int cmd、struct shmid_ds * buf);
パラメータ:
shmid:共有メモリID
cmd:
IPC_STAT共有メモリ属性を取得します
IPC_SETは共有メモリ属性を設定します
IPC_RMIDは共有メモリを削除します
buf:共有メモリ属性へのポインタ
戻り値:成功した場合は0を返し、エラーの場合は-1を返します
3.共有メモリマッピング
void * shmat(int shmid、char * shmaddr、int shmflag);
パラメータ:
shmid:共有メモリID
shmaddr:プロセスの仮想メモリ空間にマップされたアドレス。通常は0に設定され、システムによって割り当てられます。
shmflag:shmaddrが0に設定されている場合、shmflagも0に設定されます
戻り値:成功した場合は共有メモリから仮想メモリ空間にマップされたアドレスを返し、失敗した場合は-1を返します。
注:子プロセスは、親プロセスによって作成された共有メモリを継承せず、すべてのユーザーによって共有されますが、子プロセスは、親プロセスによってマップされたアドレスを継承します。
4.共有メモリのマップを解除します
int shmdt(char * shmaddr);
戻り値:失敗した場合は-1を返します。
3、コードの練習
親プロセスは共有メモリを作成し、親プロセスは共有メモリにデータを書き込みます。書き込み後、子プロセスに通知し、子プロセスは共有メモリからデータを読み取ります。
詳細:1。親プロセスが共有メモリへの書き込みを完了する前に、子プロセスは待機状態にあります。このとき、通知とブロックはパイプラインの特性によって一時的にシミュレートされます(後でセマフォに置き換えられます)。
2.子プロセスは、親プロセスによって作成されたパイプを継承するため、2つのプロセスが使い果たされると、パイプは破棄されます。
3.子プロセスは、親プロセスの共有メモリから仮想メモリにマップされたアドレスのみを継承し、共有メモリは1つのセグメントのみであるため、2つのプロセスが共有メモリを1回破棄するだけで十分ですが、共有メモリのマッピング削除する必要があります。
tell.cとtell.hを作成して、2つのプロセスの情報をパイプラインのフィーチャクラスと同期します。
#include <stdio.h>
#include <unistd.h>
#include "tell.h"
int fd[2];
//管道初始化
void init()
{
if(pipe(fd) < 0)
{
printf("pipe create error\n");
}
}
//利用管道进行等待
void wait_pipe()
{
char c;
//利用管道默认是阻塞的特性
if(read(fd[0],&c,1) < 0)
{
printf("pipe read error\n");
}
}
//利用管道进行通知
void notify_pipe()
{
char c = 'c';
if(write(fd[1],&c,1) < 0)
{
printf("pipe write error\n");
}
}
//销毁管道
void destory_pipe()
{
close(fd[0]);
close(fd[1]);
}
共有メモリへのプロセス間アクセスを実装する
#include <stdio.h>
#include "tell.h"
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
/* 父进程创建共享内存,父进程向共享内存中写数据,
*子进程从共享内存中读数据.
* */
int main(void)
{
//父进程创建共享内存,大小1024
int shmId = shmget(IPC_PRIVATE,1024,IPC_CREAT|IPC_EXCL|0777);
if(shmId < 0)
{
printf("share mem create error\n");
return -1;
}
//初始化管道
init();
pid_t pid = fork();
if(pid > 0)
{//parent process
//将共享内存映射到父进程虚拟内存空间中
int *p = (int *)shmat(shmId,0,0);
if(p == (int *) (-1))
{
printf("parent process shmat error\n");
return -1;
}
//向共享内存中写入数据
*p = 100;
*(p+1) = 200;
//通知数据已经写好了
notify_pipe();
//父进程共享内存结束映射
shmdt((char *)p);
//父进程创建的pipe,子进程也会继承,所以父子进程都有读端和写段两个管道,
//用完了都需要将其销毁
destory_pipe();
//等待回收子进程
wait(0);
}else if(pid == 0)
{//child parent
//等待共享内存写好数据
wait_pipe();
//子进程将共享内存映射到自己虚拟空间中
int *p = (int *)shmat(shmId,0,0);
if(p == (int *)-1)
{
printf("child process shmat error\n");
return -1;
}
//读共享内存
printf("share mem contex:start:%d,end:%d\n",*p,*(p+1));
//子进程共享内存结束映射
shmdt((char *)p);
//子进程也要销毁管道
destory_pipe();
//共享内存不需要继承,只有一份,所以,在子进程或者父进程删除一次就行
shmctl(shmId,IPC_RMID,NULL);
}
return 0;
}
試験結果: