• ベストアンサー

複数の共有メモリの作成

同じPC内に複数の共有メモリを作ろうとしています。自分の考えでは共有メモリを作成するときに shmget(key_t key, int size, int shmflg) のkeyを変えれば複数の共有メモリを作れると思ったのですがうまくいきません。ちなみにkeyは key = ftok(const char *pathname, int proj_id); で取得していて、pathnameとproj_idを変えればkey_tの値も変わり、複数の共有メモリが確保できると思ったのですが・・・。 また、ipcsで確認したところできた共有メモリのキーが0xffffffffになっているのも気になりました。普通は0x00000000になるべきなんでしょうか?

  • hy123
  • お礼率40% (4/10)

質問者が選んだベストアンサー

  • ベストアンサー
  • pareopara
  • ベストアンサー率100% (7/7)
回答No.4

#3です。 > ftok():No such file or directory 「ファイルかディレクトリがない」というメッセージです。 ftok()でこのメッセージに関係するところといったらファイル名が思いつきませんか? > ("host"のところを'host'に変更) いえいえ違います! ' 'で文字列を指定していることが間違っているという指摘です。 proj_idはint型なので文字列"abc"でなく、文字'a'としないと駄目ということです。 " "と' 'で囲む意味と違いを考えてください。 # × int a = "abc"; # × int a = 'abc'; # ○ int a = 'a'; もちろん、int型なので > (#define PROJ_CHAR 7としました) は、間違いではありません。 >int ftok ( string pathname, string proj ) プラットフォームによる違いです。第二引数がchar型という環境もあります。 で、いろいろと思考錯誤が入ったと思いますが、質問当初に頭をリセットしてください。 key = ftok(KEYFILE_PATH, PROJ_CHAR); がどうなれば良いかというと key = ftok("host", 'a'); の形になれば良いです。 これで「ftok():No such file or directory」のエラーが出るようであれば、ファイルの置かれている場所へのパスが通ってないということなので、ファイルを見つけられるようにパス指定を変えれば良いだけです。 実行形式mainと同じ場所にhostファイルがあるなら、"./host"とするとか、フルパス指定にするとかです。

hy123
質問者

お礼

やっと理解できました。 丁寧に解説していただいてありがとうございます。

その他の回答 (3)

  • pareopara
  • ベストアンサー率100% (7/7)
回答No.3

現状はftok()が失敗して-1を返してきていると思われます。 毎回key=-1でshmget()していれば同じ結果になるのは当然ですよね。 まずはkeyの値を確認してみてください。 その後、#2さんが気にされている箇所を修正してみては如何でしょうか。 # int型に渡すので文字列は間違いということは分かりますよね? # 定義をじっくり見てください。文字列が''で囲まれています。だからといって # 早まって""に直さないでください。 # 要は'a'みたいに文字を定義してください。

hy123
質問者

補足

えと結果から言うと全然うまくいきませんでした。 まず今まで指摘されたことを直しました。 いままではエラーのときの対応をしていなかったのでkeyの指定のところにエラーの対応を入れました。 key = ftok(KEYFILE_PATH, PROJ_CHAR) if(key == -1){ perror("ftok()"); return 1; } それでまず第二引数をint型に直したところ (#define PROJ_CHAR 7としました) 問題なくコンパイルが通ったのでいけるかなと思い実行してみると ftok():No such file or directory このエラーはどういうエラーなのでしょうか? またこの状態でpareoraraさんが指摘されていた文字列指定のところを直したところ ("host"のところを'host'に変更) 警告:複数文字からなる文字定数 警告:引数1個の'ftok'を渡しますにより、キャストなしで整数からポインタを作りました とでて、実行したところ ftok():Bad address と出てしまいました。ここでいう整数からポインタを作るとはどういう意味なのでしょうか? また、自分で色々調べたところftokには int ftok ( string pathname, string proj ) という引数指定があるようなのですがこれは key_t ftok(const char *pathname, int proj_id); とは全く別のものなのでしょうか? 多々質問してしまって申し訳ありません。ご指導お願いします。

  • terra5
  • ベストアンサー率34% (574/1662)
回答No.2

>複数作るときはftokの引数を変えているだけなんですがこれではだめなのでしょうか? 具体的に何を指定したか書いてください。 >実際に実行すると一つ目はうまくいくのですが二つ目になると Can't Access to the shared memory と出てしまいます。 具体的にどうやっていますか。 単一プログラム中で shm_initialize()を複数呼び出している、別プログラムでパラメタを変えて複数起動している、同一のプログラムを二つ起動している等。 使い方を誤解されているのかも。 ざっと見たところ key = ftok(KEYFILE_PATH, PROJ_CHAR); ですが、多分 key_t ftok(const char *pathname, int proj_id); なのに、 #define PROJ_CHAR (char) 'dbhost' が気になります。

hy123
質問者

補足

返信遅れてしまってすみません。 えっと使い方なんですが前に載せたプログラム(shm.h shm.c main.c)を違うディレクトリにおいてftokの引数であるpathnameとproj_idだけを変えて使おうとしています。(つまりpathnameとproj_idの部分だけが違うプログラムを違うディレクトリにおいて複数の共有メモリを作ろうとしています) >ざっと見たところ key = ftok(KEYFILE_PATH, PROJ_CHAR); ですが、多分 key_t ftok(const char *pathname, int proj_id); なのに、 #define PROJ_CHAR (char) 'dbhost' が気になります。 確かに・・。ここはint型にしたほうがいいですよね。 でもint型にしても出来ませんでした・・・。 それで今、ftokを使わずにkeyを無理やり自分で設定したら複数できました・・・。(key = 1とか無理やりkeyを決める) でもこれってまずいですよね?

  • terra5
  • ベストアンサー率34% (574/1662)
回答No.1

OSは? うまくいかないとは、どういう状態か? 詳しく具体的に。 考え方自体はあっているように思えますので、実際のコードに何か問題があるように思えます。 また、shmgetだけでは共有メモリ・セグメントの識別子を返すだけですから、これだけでは使用可能な共有メモリができていないことは分ってますよね?

hy123
質問者

補足

OSはRedhatlinux8です。ソースは以下のような感じです。shm.cで初期化、アクセス、消去の関数を作って cc -o main main.c shm.c でコンパイルして使っています。 複数作るときはftokの引数を変えているだけなんですがこれではだめなのでしょうか?実際に実行すると一つ目はうまくいくのですが二つ目になると Can't Access to the shared memory と出てしまいます。 -----SHM.h---------------- #ifndef __SHM_H__ #define __SHM_H__ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/msg.h> #define SHM PARAM KEY 0x1000 #define KEYFILE_PATH "host" #define PROJ_CHAR (char) 'dbhost' #define FIN (255) struct SHM_PARAM{ int shd_param_id; int status; int a; int b; int c; }; #endif /* __SHM_H__ */ extern int shm_initialize(key_t shm_key, int shm_size, int *shrd_id, int *shm_ptr); extern int shm_access(key_t shm_key, int shm_size, int *shrd_id, int *shm_ptr); extern int erase_shm(struct SHM_PARAM *pram_ptr); -------SHM.c------ #include "shm.h" int shm_initialize( key_t shm_key, /*共有メモりの為のキーワード*/ int shm_size, /*共有メモりのサイズ*/ int *shrd_id, /*共有メモりIDへのポインタ*/ int *shm_ptr) /*共有メモりの先頭アドレスへのポインタ*/ { /*現状態へのアクセス*/ *shrd_id = shmget(shm_key, shm_size, IPC_CREAT|0666); if(*shrd_id < 0){ printf("[shm_initialize]:Can't Access to the shared memory!!\n"); return -1; } *shm_ptr = (int)shmat( *shrd_id, NULL, 0); memset((void*)*shm_ptr, 0, shm_size); /*終了*/ return ( *shrd_id); } int shm_access( key_t shm_key, int shm_size, int *shrd_id, int *shm_ptr) { *shrd_id = shmget(shm_key, shm_size, 0444); if( *shrd_id < 0){ printf("Can't Access to the shared memory!!\n"); return (-1); } *shm_ptr = (int)shmat( *shrd_id,(const void*)NULL, 0); return ( *shrd_id); } int erase_shm(struct SHM_PARAM *param_ptr) { shmctl(param_ptr->shd_param_id, IPC_RMID, 0); return (0); } ---main.c--- #include "shm.h" int shd_param_id; /*共有メモりのID*/ struct SHM_PARAM *param_ptr; /*共有パラメータへのポインタ*/ key_t key; int main(int argc, char **argv) { int i; key = ftok(KEYFILE_PATH, PROJ_CHAR); shm_initialize(key, sizeof(struct SHM_PARAM), &shd_param_id, (int *)¶m_ptr); param_ptr->shd_param_id = shd_param_id; printf("Memory attaced at %x \n", (int)param_ptr); printf("a=%d\n",param_ptr->a); printf("b=%d\n",param_ptr->b); printf("c=%d\n",param_ptr->c); //erase_shm(param_ptr); // param_ptr->status = FIN; return 0; }

関連するQ&A

  • 動的メモリ確保の外部関数

    画像処理関係のプログラムを作成しているのですが(C言語で)、動的にメモリ確保をすることが頻繁にあります。 そこで、どんな型(int,char,double,etc..)の場合でもメモリ確保できるような、1つの外部関数を作成したいと考えています。 例えば、 int Memory(引数) { 型宣言; int型の動的メモリ確保; char型の動的メモリ確保; double型の動的メモリ確保; return 0; } イメージでは、上のような感じです。 もしかして、このような考えは、不可能でしょうか? どなたか良いアドバイスがあれば、ご教授ください。 よろしくお願いします。

  • C++の文字列バッファの幅は4の倍数になる?

    VisualC++でテストを行ってみたのですが、たとえば、 const char* sa = "a"; cout << (int)sa[1] << " "; cout << (int)sa[2] << " "; cout << (int)sa[3] << " "; というような処理を書くと、表示される結果は必ず "0 0 0" となります。 また、 const char* sa = "a"; const char* sb = "bb"; const char* sc = "ccc"; const char* sd = "dddd"; const char* se = "eeeee"; .... のように文字列を定義しメモリの中身を見ると、各文字列が必ず4の倍数の幅で取得され、余りの部分には0が確保されているらしく、上記の場合ですと、メモリの内容が sa -> a000 sb -> bb00 sc -> ccc0 sd -> dddd0000 se -> eeeee000 という風に確保されているようなのですが、これは正式なC++の仕様なのでしょうか? もし正しい仕様であれば、それが明記されているサイト、資料等を教えていただければありがたいです。 もしくはそうでない場合、上記のようにならない(たとえば sa[3] != 0 となる)具体的な条件、再現方法を教えて頂きたいです。 宜しくお願いします。

  • 共有メモリについて

    shmget関数のサイズ指定について質問があります。 共有メモリ上にキー番号「1234」で作られている状態で、 以下の関数(サイズ指定ありなし)を呼び出した際の違 いは何なのでしょうか? 単純にキー1234にアタッチしたいだけなら、サイズ0指定を 使用するのでしょうか? shmget(1234,0,IPC_ALLOC) shmget(1234,sizeof(int),IPC_ALLOC)

  • 動的メモリの確保の仕方を教えて下さい。

    プログラミングの初心者なのですが、現在256x256x100のバイナリファイルを読み込もうとしているのですが、下のように書くとエラーになってしまいます。動的メモリの確保を行えば、上手くいくと思うのですが。。どなたか教えて頂けないでしょうか?どうぞよろしくお願いします。 const short int SIZE=256; const short int SLICE=100; signed short int matrix[SLICE][SIZE][SIZE]; for(int i=0; i<SLICE; i++){ for(int j=0;j <SIZE; j++){ for(int k=0;k<SIZE; k++){ fin.read((char*) &matrix[i][j][k],sizeof(signed short int)); cout<< matrix[i][j][k]<<endl; } } }

  • new と malloc によるメモリの動的確保について

    初めて投稿させて頂きます。よろしくお願い致します。 現在、以下のような、2次元配列による動的なメモリの確保を意図して、コードをC/C++にて記述しています。 (コンパイラはMINGW32のg++ 3.4.5) //mallocによるメモリ動的確保 data = (char **)malloc(num * sizeof(char*)); for(i=0; i<rowNum; i++){ data[i] = (char *)malloc(sizeof(char)*256); } //newによるメモリ動的確保 data = new char*[rowNum]; for(i=0; i<rowNum; i++){ data[i] = new char; } C++で書くのならば、 「mallocによるメモリ確保は辞め、newによるメモリ確保をしなさい」 という指摘が、書籍でもwebでもありましたので、 両方書き、両者を比べているのですが、理由がイマイチ分かりません。 10万行ほどのテキストデータで実験させてみたのですが、 mallocによる記述の方が、動作が数秒速いようなのです。 それで、new やmalloc で実際何をやっているのか、コードを見ようと思ったのですが、 newでは、 void* operator new(std::size_t) throw (std::bad_alloc); void* operator new[](std::size_t) throw (std::bad_alloc); void* operator new(std::size_t, const std::nothrow_t&) throw(); void* operator new[](std::size_t, const std::nothrow_t&) throw(); inline void* operator new(std::size_t, void* __p) throw() { return __p; } inline void* operator new[](std::size_t, void* __p) throw() { return __p; } というnewファイルの記述で行き詰まり、 malloc は malloc_allocator.hというファイルで行き詰りました。 以上を踏まえて、 1)そもそも、上記のメモリ動的確保記述はスマートな書き方なのか 2)実際に、newやmallocは、どういった手法でメモリ領域を確保しているのか 以上の2点について、ご教授下さい。よろしくお願い致します。

  • c++11での文字列リテラルの特殊化について

    c++11言語でのテンプレート部分特殊化についての質問です。 コメントアウト部分は出力結果です template<class T> struct VT { static const int type = 1;}; template<class T,int N> struct VT< T[N] > { static const int type = 2;}; template<class T,int N> struct VT< const T[N] > { static const int type = 3;}; template<class T> struct VT< T* > { static const int type = 4;}; template<class T> struct VT< const T*const > { static const int type = 5;}; #include<iostream> #include<typeinfo> int main(){ std::cout<<"A:"<< VT< char >::type << std::endl; // A:1 std::cout<<"B:"<< VT< char[10] >::type << std::endl; // B:2 std::cout<<"C:"<< VT< char* >::type << std::endl; // C:4 std::cout<<"D:"<< VT< char const [1] >::type << std::endl; // D:3 std::cout<<"E:"<< VT< decltype("") >::type << std::endl; // E:1 std::cout<<"G:"<< typeid( char const [1] ).name() << std::endl;// G:char const [1] std::cout<<"H:"<< typeid( "" ).name() << std::endl;// H:char const [1] } 型名を直接記述したD,G、文字列リテラルを記述したE,H。 コンパイラ毎の差はあれど、GとHの型名は同じものが表示されます。 ですが、[D:3] [E:1]と値は違い、別の特殊化テンプレートが使われています。 この部分が分かりません。 また、配列リテラル、文字列リテラルに対し部分特殊化テンプレートを宣言する方法などありましたら、ご教示お願いします。

  • メモリ動的確保について

    こんにちはです。 メモリの動的確保なのですが、 typedef struct DATA{ char name[256]; char pass[256]; int money; }BANK; void insert(BANK *p,int max); int main(){ int i; size_t st; BANK *person; person = (struct DATA *)malloc(sizeof(struct DATA)); //person = (struct DATA *)malloc(5); if(person == NULL){ printf("確保失敗\n"); exit(-1); } //memset(person,'\0',sizeof(struct DATA)); と、言う風に、記載ソースは途中ですがメモリをとりました。 mallocの後ろの部分ですが、sizeof(struct DATA)と5ではどうちがうのでしょう??2通りともコンパイルエラーはないです。 5は動的に最大5までとるって事はわかるのですが、struct DATAの方はいくつとるのです??いくつもで入力次第です? そして、動的したのにたいしてmemsetしたら実行エラー(コンパイルは通りました)おきました。動的にたいしてmemはダメなのでしょうか? アドバイスいただけたらありがたいです。宜しくお願いいたします。

  • 共有メモリでのデータ読み書きについて

    Linuxで共有メモリを複数プロセスで読み書きする場合について質問させて頂きます。 CPUは32ビットで、共有メモリ上の、int(32ビット)の領域を 複数のプロセスで読み書きする場合を想定した場合、 セマフォ等でロックした方が良いのでしょうか? または、CPUが1命令で読み書きすることが可能 (と思っていますが、違っていればご指摘お願い致します)なので、 セマフォ等のロックをかけなくても、問題はないものなのでしょうか? 割りと良くありそうな疑問だと思ったのですが、 ウェブで調べた限りでは該当する質問はありませんでしたので、 質問させて頂きました。 ご回答宜しくお願い致します。

  • 三次元配列の動的メモリの確保?

    const int SLICE=2; const int SIZE=256; signed short int *matrix=new signed short int[SLICE][SIZE][SIZE]; for(int i=0; i<SLICE; i++){ for(int j=0; j<SIZE; j++){ for(int k=0; k<SIZE; k++){ fin.read((char*) &matrix[SLICE][SIZE][SIZE],sizeof(signed short int)); } } } delete[] data; 三次元データを読み込むために、三次元配列を使って読み込もうとしたのですが、上手く読み込めません。 三行目の所で、error C2440: '初期化中' : 'short (*)[256][256]' から 'short *' に変換できません。 七行目の所で、error C2109: 配列または、ポインタでない変数に添字が使われました。 というエラーがでます。動的メモリの確保の仕方がまずいのでしょうか? どなたか教えて頂けますでしょうか?よろしくお願いします。

  • プログラミングカテゴリ見つかりませんでした…C言語

    プログラミングカテゴリ見つかりませんでした…C言語勉強中なのですが…参考書の以下の書き方がよくわかりません。 int strncomp(const char *s1,const char *s2,size_t n) このsize_tってどういう意味なのでしょうか? 教えていただけると助かります

専門家に質問してみよう