タグ「define」を含む投稿[1件]
SharedMemory(共有メモリ)であるmmapの使い方が整理出来つつあります。
検証はこれからですが、理解出来たところをオレメモとして書いておきます。
あくまで「オレメモ」です。間違いアリアリでよろしくお願いします。
なお、mmapには様々な用法あるらしい。下記はプロセス間の共有メモリに限った使い方です。
/* mmapを使うためのライブラリ */
#include <sys/mman.h>
/* 共有メモリにテキストを代入する */
char *st; // 扱うデータの型でmmapのポインタを設定
int msize = 4096;
st = mmap( NULL, msize, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0 ); // ここまでやってからfork()でプロセスを分ける
*st = 'TEST'; // mmapに「TEST」が代入される(変数をポインタで扱う方法で扱える)
/* 使用後は共有メモリを解放する */
munmap( st, msize );
mmapの引数
1つ目(addr/NULL):mmapを定義するメモリアドレスを設定する項目だが、NULLにしておけばOSが決めてくれる。
2つ目(size/msize):確保するメモリサイズの指定。ページメモリのサイズの倍数にするベシというご意見と、欲しいメモリサイズを指定すればOSが調整してくれるというご意見など色々ある。変数の型からsizeofで得る方法(sizeof(int)など)を使われている方もいる。
3つ目(prot/PROT_READ | PROT_WRITE):読み書きモードを設定する。この書き方だと読み書き両方可能にする。
4つ目(flag/MAP_ANON | MAP_SHARED):MAP_ANONはファイルをマッピングせずに使う指定(共有メモリとして使うだけならこれでいい)、MAP_SHAREDはプロセス間で共有するという指定。
5つ目(fd/-1):ファイルディスクリプタの指定だが、上記でMAP_ANONにしているので-1で無しとする。
6つ目(offset/0):スタートアドレスからどれくらいずらしたところを使うか。
共有メモリは読み書きのタイミングをマネージしれくれませんので、何かしらの管理をしないといけません。
参考:ページメモリのサイズを取得する
#include <unistd.h>
#include <stdio.h>
long page_size = sysconf( _SC_PAGESIZE );
ついでにpipeも。
ただし、ここではpipe2(Linux固有)を使います。pipeの上位互換で引数でノンブロッキングの設定が出来るからです。通常のpipeはパイプが空の場合に有効なデータが取り出せるまで待ってしまいますがO_NONBLOCKを設定すると待ちません。
なお、以前の書き込みでpipeは単純なスタックと書きましたが、Queue程マネジメントされていないFIFOです。訂正します。
/* pipeを使うためのライブラリ */
#define _GNU_SOURCE // よくわからないけど必要なおまじない?
#include <fcntl.h> // O_*(ここではO_NONBLOCK) 定数の定義の取得
#include <unistd.h> // pipeの本体を呼ぶ
/* pipeの定義 */
int pipefd[2]; // ファイルディスクリプタとしてint配列を用いる 変数の名前は任意
if( pipe2( pipefd, O_NONBLOCK ) < 0 ) { // ファイルディスクリプタとする配列とノンブロッキングのフラグを引数にする
// pipe2の戻り値が-1なら設定エラー
}
/* pipeへの書き込み */
char *st = "TEST";
write( pipefd[1], st, strlen( st ) ); // strlenは<string.h>が必要。成功なら書き込んだバイト数、失敗なら-1が戻る。
/* pipeからの読み出し */
char buf[128];
read( pipefd[0], &buf, sizeof( buf ) ); // パイプが空の場合はEOFを得るか戻り値が0になると思われる。成功なら読み取ったしたバイト数、失敗なら-1が戻る。
/* pipeを閉じる(fork()して読み出し側書き込み側に分かれる場合はfork()した後に使わない側を閉じて運用する。もちろん終了する際にはすべて閉じる) */
close( pipefd[0] ); // 読み出しを閉じる
close( pipefd[1] ); // 書き込みを閉じる
int配列pipefdは[0]が読み出し[1]が書き込みになるファイルディスクリプタ。
#define MEMREAD 0
#define MEMWRITE 1
などとして使うとわかりやすいかも。
OSに寄りますが、スタック長は65536バイトが一般的らしい。
pipeは読み書きのタイミングをマネージしてくれます。
どちらもファイルを読み書きする手法を応用していますので、ファイルの読み書きの仕方を勉強しなおしてから取り組むとわかりやすいかもしれません。
#C言語
検証はこれからですが、理解出来たところをオレメモとして書いておきます。
あくまで「オレメモ」です。間違いアリアリでよろしくお願いします。
なお、mmapには様々な用法あるらしい。下記はプロセス間の共有メモリに限った使い方です。
/* mmapを使うためのライブラリ */
#include <sys/mman.h>
/* 共有メモリにテキストを代入する */
char *st; // 扱うデータの型でmmapのポインタを設定
int msize = 4096;
st = mmap( NULL, msize, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0 ); // ここまでやってからfork()でプロセスを分ける
*st = 'TEST'; // mmapに「TEST」が代入される(変数をポインタで扱う方法で扱える)
/* 使用後は共有メモリを解放する */
munmap( st, msize );
mmapの引数
1つ目(addr/NULL):mmapを定義するメモリアドレスを設定する項目だが、NULLにしておけばOSが決めてくれる。
2つ目(size/msize):確保するメモリサイズの指定。ページメモリのサイズの倍数にするベシというご意見と、欲しいメモリサイズを指定すればOSが調整してくれるというご意見など色々ある。変数の型からsizeofで得る方法(sizeof(int)など)を使われている方もいる。
3つ目(prot/PROT_READ | PROT_WRITE):読み書きモードを設定する。この書き方だと読み書き両方可能にする。
4つ目(flag/MAP_ANON | MAP_SHARED):MAP_ANONはファイルをマッピングせずに使う指定(共有メモリとして使うだけならこれでいい)、MAP_SHAREDはプロセス間で共有するという指定。
5つ目(fd/-1):ファイルディスクリプタの指定だが、上記でMAP_ANONにしているので-1で無しとする。
6つ目(offset/0):スタートアドレスからどれくらいずらしたところを使うか。
共有メモリは読み書きのタイミングをマネージしれくれませんので、何かしらの管理をしないといけません。
参考:ページメモリのサイズを取得する
#include <unistd.h>
#include <stdio.h>
long page_size = sysconf( _SC_PAGESIZE );
ついでにpipeも。
ただし、ここではpipe2(Linux固有)を使います。pipeの上位互換で引数でノンブロッキングの設定が出来るからです。通常のpipeはパイプが空の場合に有効なデータが取り出せるまで待ってしまいますがO_NONBLOCKを設定すると待ちません。
なお、以前の書き込みでpipeは単純なスタックと書きましたが、Queue程マネジメントされていないFIFOです。訂正します。
/* pipeを使うためのライブラリ */
#define _GNU_SOURCE // よくわからないけど必要なおまじない?
#include <fcntl.h> // O_*(ここではO_NONBLOCK) 定数の定義の取得
#include <unistd.h> // pipeの本体を呼ぶ
/* pipeの定義 */
int pipefd[2]; // ファイルディスクリプタとしてint配列を用いる 変数の名前は任意
if( pipe2( pipefd, O_NONBLOCK ) < 0 ) { // ファイルディスクリプタとする配列とノンブロッキングのフラグを引数にする
// pipe2の戻り値が-1なら設定エラー
}
/* pipeへの書き込み */
char *st = "TEST";
write( pipefd[1], st, strlen( st ) ); // strlenは<string.h>が必要。成功なら書き込んだバイト数、失敗なら-1が戻る。
/* pipeからの読み出し */
char buf[128];
read( pipefd[0], &buf, sizeof( buf ) ); // パイプが空の場合はEOFを得るか戻り値が0になると思われる。成功なら読み取ったしたバイト数、失敗なら-1が戻る。
/* pipeを閉じる(fork()して読み出し側書き込み側に分かれる場合はfork()した後に使わない側を閉じて運用する。もちろん終了する際にはすべて閉じる) */
close( pipefd[0] ); // 読み出しを閉じる
close( pipefd[1] ); // 書き込みを閉じる
int配列pipefdは[0]が読み出し[1]が書き込みになるファイルディスクリプタ。
#define MEMREAD 0
#define MEMWRITE 1
などとして使うとわかりやすいかも。
OSに寄りますが、スタック長は65536バイトが一般的らしい。
pipeは読み書きのタイミングをマネージしてくれます。
どちらもファイルを読み書きする手法を応用していますので、ファイルの読み書きの仕方を勉強しなおしてから取り組むとわかりやすいかもしれません。
#C言語