linux c学習ノート----共有メモリ(shmget,shmat,shmdt,shmctl)
詳細
shmgetint shmget(key_t key, size_t size, int flag);key:識別子のルールsize:共有ストレージセグメントのバイト数flag:読み書き権限戻り値:共有ストレージのidを正常に返し、失敗して-1 key_を返すt key---------------------------------------------key共有メモリを識別するキー値:0/IPC_PRIVATE. キーの値がIPC_の場合PRIVATEでは、関数shmget()が新しい共有メモリを作成します.keyの値が0の場合、パラメータshmflgにIPC_が設定されています.PRIVATEというフラグは、同じように新しい共有メモリを作成します.
IPC(InterProcess Communication)の通信モードでは、メッセージキューを使用しても共有メモリを使用しても、信号量を使用しても、IPCのオブジェクトごとに一意の名前があり、キー(key)と呼ばれます.「キー」を使用すると、プロセスは使用するオブジェクトを識別できます.「キー」とIPCオブジェクトの関係は、ファイル名のファイルと同じであり、ファイル名によって、プロセスはファイル内のデータを読み書きすることができ、複数のプロセスは1つのファイルを共有することができる.一方、IPCの通信モードでは、「キー」の使用により、1つのIPCオブジェクトが複数のプロセスで共有できるようにする.LinuxシステムのすべてのシステムVのIPCオブジェクトを表すデータ構造は、ipc_を含む.perm構造で、システムVのIPCオブジェクトの参照識別子を検索するためのIPCオブジェクトのキー値が含まれています.「キー」を使用しないと、プロセスはIPCオブジェクトにアクセスできません.なぜなら、IPCオブジェクトはプロセス自体が使用するメモリに存在しないからです.通常、自分のプログラムが他のプログラムと一意のキー値を予め約束することを望んでいますが、実際には、自分のプログラムが共有メモリのキー値を選択できないため、常に可能な行ではありません.そこでkeyをIPC_に設定PRIVATE、これにより、オペレーティングシステムはキーを無視し、新しい共有メモリを確立し、キー値を指定し、この共有メモリIPC識別子IDを返します.この新しい共有メモリの識別子IDを他のプロセスに伝えると、共有メモリを確立した後、子供を派遣したり、ファイルやパイプに書き込んだりすることで実現できます.int size(単位バイトByte)------------------------------------------------------------------sizeは共有メモリを構築する長さです.すべてのメモリ割り当て操作はページ単位です.したがって、プロセスが1バイトしかないメモリを1枚しか申請しない場合、メモリも1ページ(i 386マシンのデフォルトサイズPACE_SIZE=4096バイト)割り当てられ、新しく作成された共有メモリのサイズは、実際にはsizeというパラメータから調整されたページサイズである.すなわちsizeが1~4096の場合、実際に申請された共有メモリサイズは4 K(1ページ)である.4097~8192では、実際に申請された共有メモリサイズは8 K(2ページ)である.int shmflg----------------------------------------------------shmflgは主にいくつかの標識と関係がある.有効なのはIPCを含むCREATとIPC_EXCL、それらの機能はopen()のO_とCREATとO_EXCL相当です. IPC_CREAT共有メモリが存在しない場合は、共有メモリを作成します.そうしないと、操作が開きます. IPC_EXCLは、共有メモリが存在しない場合にのみ、新しい共有メモリが確立されます.そうしないとエラーが発生します.IPCを単独で使用する場合CREAT、shmget()関数は、既存の共有メモリのオペレータを返すか、新しい共有メモリの識別子を返します.IPC_をCREATとIPC_EXCLフラグを一緒に使用すると、shmget()は新しい共有メモリの識別子を返します.共有メモリが既に存在する場合は、-1を返します.IPC_EXELマーク自体はあまり意味はありませんが、IPC_とCREATフラグは、既存のオブジェクトを開くのではなく、結果として得られるオブジェクトが新規であることを保証するために一緒に使用されます.ユーザーの読み取りおよび書き込み許可についてSHM_を指定します.RとSHM_W,(SHM_R>3)および(SHM_W>3)は読み出しおよび書き込み許可のセットであり、(SHM_R>6)および(SHM_W>6)はグローバル読み出しおよび書き込み許可である.なお、パラメータにはチェックとして|0666を付ける必要があり、一部のLinuxシステムでは、このチェックを付けないと共有空間の値(Ubuntuなど)をスムーズに取得できない場合がある.また、2つの一般的なパラメータがあります.一般的には、S_IRUSH | S_IWUSR .この2つのパラメータは非常によく使われるため、プログラマーは一般的にこのような操作をします.IRUSR | S_IWUSR | IPC_CREATはこれで3番目のパラメータを直接PERMで表すことができます!戻り値-----------------------------------------------------------共有メモリの識別子を正常に返しました.-1を正常に返さず、errnoはエラーの原因を格納します.EINVALパラメータsizeはSHMMINより小さいかSHMMAXより大きい.EEXISTはkeyによる共有メモリを事前に確立しているが、既に存在する.EIDRMパラメータkeyによる共有メモリが削除されました.ENOSPCは、システムで許可されている共有メモリの最大値(SHMALL)を超えています.ENOENTパラメータkeyが指す共有メモリは存在せず、パラメータshmflgもIPC_を設定していない.CREATビット.EACCESには権限がありません.ENOMEMコアメモリが不足しています.struct shmid_ds----------------------------------------------- shmid_dsデータ構造は、新規の共有メモリを表す.shmget()が新しい共有メモリを作成すると、共有メモリを参照できるshmid_が返されます.dsデータ構造の識別子.include/linux/shm.h 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 */ };struct ipc_perm--------------------------------------------IPCオブジェクトごとにstruct ipcを共有するpermのデータ構造は、ipc操作がIPCオブジェクトにアクセスできるかどうかを決定するために権限情報を格納する. struct ipc_perm { __kernel_key_t key; __kernel_uid_t uid; __kernel_gid_t gid; __kernel_uid_t cuid; __kernel_gid_t cgid; __kernel_mode_t mode; unsigned short seq; };//----------------------------------------shmatvoid *shmat(int shmid, const void *addr, int flag);shmid:共有ストレージのidaddr:一般的に0で、カーネルによって選択された最初の使用可能なアドレスに接続されていることを示します.そうでない場合、flagにSHM_が指定されていない場合RNDは、flagがSHM_である場合にaddrで指定されたアドレスに接続されるRND、アドレスはflagを整頓する:前述のように、一般的に0の戻り値である:成功すれば、共有メモリセグメントアドレスを返し、エラー戻り-1共有メモリの実行方式は、1つのメモリセグメントを共通とマークすることであり、この場合、各プロセスは、このセグメントをプロセス自体の仮想アドレスにマッピングすることができる.共有メモリを確立するにはshmgetシステムによって呼び出すことができ、shmgetが実行されると、コアプログラムは指定されたサイズの空間を保持すると同時に、この共有メモリに関するすべてのデータ、例えばセグメントの長さ、セグメントのアクセス権、セグメント確立者のプロセス識別コードなどはshmid_と呼ばれるdsの構造.現在、共有メモリは確立されているが、接続できない場合、shmatシステム呼び出しにより共有メモリのベースアドレスを指すポインタを得る必要があり、このポインタにより、一般的なメモリを操作するように共有メモリを取り出すことができる.shmdtは、接続された共有メモリから離れるために逆の動作を行う.shmdtint shmdt(void *addr);addr:共有ストレージセグメントのアドレスで、以前shmatを呼び出したときの戻り値shmdtは関連shmid_を使用します.ds構造におけるshm_nattchカウンタ値マイナス1
プロセスがメモリセグメントを共有する必要がなくなった場合、shmdt()システム呼び出しを呼び出してこのセグメントをキャンセルしますが、これはカーネルから実際に削除するのではなく、関連するshmid_ds構造のshm_nattchドメインの値は1を減らし、この値が0の場合、カーネルは物理的にこの共有セグメントを削除します.
shmctlint shmctl(int shmid,int cmd,struct shmid_ds*buf)shmid:共有ストレージセグメントのidcmd:一部のコマンド
IPC_STATが共有メモリを取得した状態IPC_SET共有メモリの状態を変更IPC_RMID共有メモリの削除
IPC_RMIDコマンドは実際にカーネルからセグメントを削除するのではなく、このセグメントを削除とマークするだけで、実際の削除は最後のプロセスがこの共有セグメントを離れたときに発生します.共有メモリは、プログラムが終了するにつれて自動的に消去されず、shmctl削除を呼び出すか、自分で手でコマンドを叩いて削除するか、システムに永遠に残っていることに注意してください.
例:
このプログラムは、親プロセスが共有メモリにパラメータを書き込む、サブプロセスがコンテンツを読み出す.最後にipを使います
crmは資源を解放する.まずipcsでIDを探し出してからipcrm shm IDで削除する.
shmgetint shmget(key_t key, size_t size, int flag);key:識別子のルールsize:共有ストレージセグメントのバイト数flag:読み書き権限戻り値:共有ストレージのidを正常に返し、失敗して-1 key_を返すt key---------------------------------------------key共有メモリを識別するキー値:0/IPC_PRIVATE. キーの値がIPC_の場合PRIVATEでは、関数shmget()が新しい共有メモリを作成します.keyの値が0の場合、パラメータshmflgにIPC_が設定されています.PRIVATEというフラグは、同じように新しい共有メモリを作成します.
IPC(InterProcess Communication)の通信モードでは、メッセージキューを使用しても共有メモリを使用しても、信号量を使用しても、IPCのオブジェクトごとに一意の名前があり、キー(key)と呼ばれます.「キー」を使用すると、プロセスは使用するオブジェクトを識別できます.「キー」とIPCオブジェクトの関係は、ファイル名のファイルと同じであり、ファイル名によって、プロセスはファイル内のデータを読み書きすることができ、複数のプロセスは1つのファイルを共有することができる.一方、IPCの通信モードでは、「キー」の使用により、1つのIPCオブジェクトが複数のプロセスで共有できるようにする.LinuxシステムのすべてのシステムVのIPCオブジェクトを表すデータ構造は、ipc_を含む.perm構造で、システムVのIPCオブジェクトの参照識別子を検索するためのIPCオブジェクトのキー値が含まれています.「キー」を使用しないと、プロセスはIPCオブジェクトにアクセスできません.なぜなら、IPCオブジェクトはプロセス自体が使用するメモリに存在しないからです.通常、自分のプログラムが他のプログラムと一意のキー値を予め約束することを望んでいますが、実際には、自分のプログラムが共有メモリのキー値を選択できないため、常に可能な行ではありません.そこでkeyをIPC_に設定PRIVATE、これにより、オペレーティングシステムはキーを無視し、新しい共有メモリを確立し、キー値を指定し、この共有メモリIPC識別子IDを返します.この新しい共有メモリの識別子IDを他のプロセスに伝えると、共有メモリを確立した後、子供を派遣したり、ファイルやパイプに書き込んだりすることで実現できます.int size(単位バイトByte)------------------------------------------------------------------sizeは共有メモリを構築する長さです.すべてのメモリ割り当て操作はページ単位です.したがって、プロセスが1バイトしかないメモリを1枚しか申請しない場合、メモリも1ページ(i 386マシンのデフォルトサイズPACE_SIZE=4096バイト)割り当てられ、新しく作成された共有メモリのサイズは、実際にはsizeというパラメータから調整されたページサイズである.すなわちsizeが1~4096の場合、実際に申請された共有メモリサイズは4 K(1ページ)である.4097~8192では、実際に申請された共有メモリサイズは8 K(2ページ)である.int shmflg----------------------------------------------------shmflgは主にいくつかの標識と関係がある.有効なのはIPCを含むCREATとIPC_EXCL、それらの機能はopen()のO_とCREATとO_EXCL相当です. IPC_CREAT共有メモリが存在しない場合は、共有メモリを作成します.そうしないと、操作が開きます. IPC_EXCLは、共有メモリが存在しない場合にのみ、新しい共有メモリが確立されます.そうしないとエラーが発生します.IPCを単独で使用する場合CREAT、shmget()関数は、既存の共有メモリのオペレータを返すか、新しい共有メモリの識別子を返します.IPC_をCREATとIPC_EXCLフラグを一緒に使用すると、shmget()は新しい共有メモリの識別子を返します.共有メモリが既に存在する場合は、-1を返します.IPC_EXELマーク自体はあまり意味はありませんが、IPC_とCREATフラグは、既存のオブジェクトを開くのではなく、結果として得られるオブジェクトが新規であることを保証するために一緒に使用されます.ユーザーの読み取りおよび書き込み許可についてSHM_を指定します.RとSHM_W,(SHM_R>3)および(SHM_W>3)は読み出しおよび書き込み許可のセットであり、(SHM_R>6)および(SHM_W>6)はグローバル読み出しおよび書き込み許可である.なお、パラメータにはチェックとして|0666を付ける必要があり、一部のLinuxシステムでは、このチェックを付けないと共有空間の値(Ubuntuなど)をスムーズに取得できない場合がある.また、2つの一般的なパラメータがあります.一般的には、S_IRUSH | S_IWUSR .この2つのパラメータは非常によく使われるため、プログラマーは一般的にこのような操作をします.IRUSR | S_IWUSR | IPC_CREATはこれで3番目のパラメータを直接PERMで表すことができます!戻り値-----------------------------------------------------------共有メモリの識別子を正常に返しました.-1を正常に返さず、errnoはエラーの原因を格納します.EINVALパラメータsizeはSHMMINより小さいかSHMMAXより大きい.EEXISTはkeyによる共有メモリを事前に確立しているが、既に存在する.EIDRMパラメータkeyによる共有メモリが削除されました.ENOSPCは、システムで許可されている共有メモリの最大値(SHMALL)を超えています.ENOENTパラメータkeyが指す共有メモリは存在せず、パラメータshmflgもIPC_を設定していない.CREATビット.EACCESには権限がありません.ENOMEMコアメモリが不足しています.struct shmid_ds----------------------------------------------- shmid_dsデータ構造は、新規の共有メモリを表す.shmget()が新しい共有メモリを作成すると、共有メモリを参照できるshmid_が返されます.dsデータ構造の識別子.include/linux/shm.h 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 */ };struct ipc_perm--------------------------------------------IPCオブジェクトごとにstruct ipcを共有するpermのデータ構造は、ipc操作がIPCオブジェクトにアクセスできるかどうかを決定するために権限情報を格納する. struct ipc_perm { __kernel_key_t key; __kernel_uid_t uid; __kernel_gid_t gid; __kernel_uid_t cuid; __kernel_gid_t cgid; __kernel_mode_t mode; unsigned short seq; };//----------------------------------------shmatvoid *shmat(int shmid, const void *addr, int flag);shmid:共有ストレージのidaddr:一般的に0で、カーネルによって選択された最初の使用可能なアドレスに接続されていることを示します.そうでない場合、flagにSHM_が指定されていない場合RNDは、flagがSHM_である場合にaddrで指定されたアドレスに接続されるRND、アドレスはflagを整頓する:前述のように、一般的に0の戻り値である:成功すれば、共有メモリセグメントアドレスを返し、エラー戻り-1共有メモリの実行方式は、1つのメモリセグメントを共通とマークすることであり、この場合、各プロセスは、このセグメントをプロセス自体の仮想アドレスにマッピングすることができる.共有メモリを確立するにはshmgetシステムによって呼び出すことができ、shmgetが実行されると、コアプログラムは指定されたサイズの空間を保持すると同時に、この共有メモリに関するすべてのデータ、例えばセグメントの長さ、セグメントのアクセス権、セグメント確立者のプロセス識別コードなどはshmid_と呼ばれるdsの構造.現在、共有メモリは確立されているが、接続できない場合、shmatシステム呼び出しにより共有メモリのベースアドレスを指すポインタを得る必要があり、このポインタにより、一般的なメモリを操作するように共有メモリを取り出すことができる.shmdtは、接続された共有メモリから離れるために逆の動作を行う.shmdtint shmdt(void *addr);addr:共有ストレージセグメントのアドレスで、以前shmatを呼び出したときの戻り値shmdtは関連shmid_を使用します.ds構造におけるshm_nattchカウンタ値マイナス1
プロセスがメモリセグメントを共有する必要がなくなった場合、shmdt()システム呼び出しを呼び出してこのセグメントをキャンセルしますが、これはカーネルから実際に削除するのではなく、関連するshmid_ds構造のshm_nattchドメインの値は1を減らし、この値が0の場合、カーネルは物理的にこの共有セグメントを削除します.
shmctlint shmctl(int shmid,int cmd,struct shmid_ds*buf)shmid:共有ストレージセグメントのidcmd:一部のコマンド
IPC_STATが共有メモリを取得した状態IPC_SET共有メモリの状態を変更IPC_RMID共有メモリの削除
IPC_RMIDコマンドは実際にカーネルからセグメントを削除するのではなく、このセグメントを削除とマークするだけで、実際の削除は最後のプロセスがこの共有セグメントを離れたときに発生します.共有メモリは、プログラムが終了するにつれて自動的に消去されず、shmctl削除を呼び出すか、自分で手でコマンドを叩いて削除するか、システムに永遠に残っていることに注意してください.
例:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define PERM S_IRUSR|S_IWUSR
int main(int argc,char **argv){
int shmid;
char *p_addr,*c_addr;
if(argc!=2){
fprintf(stderr,"Usage:%s
\a",argv[0]);
exit(1);
}
if((shmid=shmget(IPC_PRIVATE,1024,PERM))==-1){
fprintf(stderr,"Create Share Memory Error:%s
\a",strerror(errno));
exit(1);
}
if(fork()){
p_addr=shmat(shmid,0,0);
memset(p_addr,'\0',1024);
strncpy(p_addr,argv[1],1024);
exit(0);
}else{
c_addr=shmat(shmid,0,0);
printf("Client get %s",c_addr);
exit(0);
}
}
このプログラムは、親プロセスが共有メモリにパラメータを書き込む、サブプロセスがコンテンツを読み出す.最後にipを使います
crmは資源を解放する.まずipcsでIDを探し出してからipcrm shm IDで削除する.