4

C を使用して、共有メモリをセットアップしようとしています。私のコードは次のようになります:

key_t key = ftok("SomeString", 1);
static int *sharedval;
int shmid = shmget(key, sizeof(int), S_IRUSR | S_IWUSR); // less permissions
sharedval = (int *) shmat(shmid, NULL, 0);
*sharedval = 0;

ただし、その最後の行を 2 番目に実行すると、セグメンテーション違反が発生します。デバッグ時に、「sharedval」を出力すると、メモリ アドレスが取得されます。おそらく、取得したメモリ内の場所です。したがって、私がしなければならないことは*sharedval、それを評価するために使用することだけだと思いますが、どうやらそうではありません。共有メモリから読み取るにはどうすればよいですか? 正しい方向へのプッシュは素晴らしいでしょう。ありがとう!

編集:

another.anon.coward の出力:

$ ./a.out 
ftok: No such file or directory
shmget: No such file or directory
Trying shmget with IPC_CREAT
shmget success
shmat success
Segmentation fault: 11
4

4 に答える 4

7

あなたの場合の問題は、指定されたキーに関連付けられたメモリセグメントがないことです。その場合、IPC_CREATフラグを渡してメモリ セグメントを作成する必要があります。エラーメッセージの確認にshmgetご利用ください。perror次のコードを試すことができます

    #include <stdio.h> //For perror
    ...

    key_t key = ftok("SomeString", 1);
    if ( 0 > key )
    {
       perror("ftok"); /*Displays the error message*/
       /*Error handling. Return with some error code*/
    }
    else /* This is not needed, just for success message*/
    {
       printf("ftok success\n");
    }

    static int *sharedval;
    int shmid = shmget(key, sizeof(int), S_IRUSR | S_IWUSR | IPC_CREAT);
    if ( 0 > shmid )
    {
        perror("shmget"); /*Displays the error message*/
    }
    else /* This is not needed, just for success message*/
    {
       printf("shmget success\n");
    }

    sharedval = (int *) shmat(shmid, NULL, 0);
    if ( 0 > sharedval )
    {
       perror("shmat"); /*Displays the error message*/
       /*Error handling. Return with some error code*/
    }
    else /* This is not needed, just for success message*/
    {
       printf("shmat success\n");
    }
    *sharedval = 0;
    ...
于 2011-09-21T09:24:24.063 に答える
2

最新のプログラムで共有メモリを実行する正しい方法は、mmapand を使用することMAP_SHAREDです。通常のファイルまたは で作成された名前付き共有メモリ オブジェクトのいずれかを使用できますshm_open

于 2011-09-21T06:32:52.940 に答える
2

問題は、ftok が任意の文字列ではなく、fstat に渡すことができる既存のファイルを必要とすることです。マニュアルページから:

key_t ftok(c​​onst char* パス名, int proj_id)

ftok() 関数は、指定されたパス名 (既存のアクセス可能なファイルを参照する必要があります) で指定されたファイルの ID を使用します ...

簡単に修正するには、次を試してください。

int main(int argc, char* argv[])
{
  key_t key = ftok(argv[0], 1);
  ...
}

これは、ftok から ENOENT (No such file or directory) エラーが発生する理由も説明しています。

于 2012-08-08T14:32:18.423 に答える
1

上記のように、コードにエラー チェックがありません。たとえば、shmat がエラーを示す方法は、-1 を返すことです。これは、ポインターとして表示されると long int のように見えます。これにより、ここで何が起こっているかがわかります。

具体的には、File Token の略である ftok() は、Linux ファイル システム上の有効なファイルへのパスを取得して、ファイルの inode 番号から共有メモリ ID を取得する必要があることに注意してください (ファイルの内容は調べません)。現在のディレクトリに SomeString というファイルがない限り、これがこの呼び出しが失敗する理由です。

最後になりましたが、使用している SySV API ではなく、POSIX 共有メモリ API を使用することを強くお勧めします。詳細については、shm_open(3) (http://linux.die.net/man/3/shm_open) を参照してください。

于 2011-09-21T06:37:23.717 に答える