3

私がこれを行うとき:

myProgram.h
myProgram.c

    struct PipeShm
    {
    // all my fields
    // more 
    // ...

    };



    struct PipeShm myPipe = { /* initialization for all fields */ };
    struct PipeShm * sharedPipe = &myPipe;

void func()
{
 sharedPipe = mmap (NULL, sizeof * sharedPipe, PROT_READ | PROT_WRITE,MAP_SHARED | MAP_ANONYMOUS, -1, 0);

}

mmapポインターをコードから任意のメソッドからsharedPipe呼び出した場合、すべてのプロセスは、構造体と共有した正確な共有メモリを共有しますか?main()myProgrammyPipe

myPipeそれとも、作成された新しい子供ごとに、自分 の新しい子供がいるでしょうか?

よろしく

編集:

これは、コメントと回答を読んだ後です。変更が行われ、割り当てた後にのみセグメントの値を初期化します。

#include "my_pipe.h"

struct PipeShm * sharedPipe = NULL;



int shm_pipe_init()
{
    if (!sharedPipe)
    {
        int myFd = shm_open ("/myregion", O_CREAT | O_TRUNC | O_RDWR, 0600);

        if (myFd == -1)
            error_out ("shm_open");

        // Allocate some memory in the region - We use ftruncate, write(2) would work just as well
        int retAlloc = ftruncate (myFd, sizeof * sharedPipe);
        if (retAlloc < 0)
            error_out("ftruncate");


        sharedPipe = mmap (NULL, sizeof * sharedPipe,
                PROT_READ | PROT_WRITE,MAP_SHARED | MAP_ANONYMOUS, myFd, 0);

        if (!sem_init (&sharedPipe->semaphore, 1, 0))
        {
            sharedPipe->init = TRUE;
            sharedPipe->flag = FALSE;
            sharedPipe->ptr1 = NULL;
            sharedPipe->ptr2 = NULL;
            sharedPipe->status1 = -10;
            sharedPipe->status2 = -10;
            sharedPipe->semaphoreFlag = FALSE;
            sharedPipe->currentPipeIndex = 0;

        }
        else
            perror ("shm_pipe_init");
    }
    return 1;   // always successful
}

ただし、問題は継続します。共有メモリはプロセス間であまり共有されていないようです。

int main()
{
    int spd, pid, rb;
    char buff[4096];

    fork();
    shm_pipe_init();

        // more
        return 0;
}

私はまだ出力を取得します。これは、1 つのプロセスのみが実行されているような動作をシミュレートします (複数の出力ではなく、プロセス間の競合状態に応じて、1 つまたは2つのみを取得します)。

4

3 に答える 3

7

このプログラムを何度も呼び出すつもりなら、答えは「いいえ」です。マッピングの作成後に fork する場合、答えは「はい」です。

匿名マッピングには、基になるファイルがありません。したがって、匿名マッピングを作成するプロセスには、特に必要な既存のマッピングを指定する方法がありません (また、これは意図した使用法ではありません。新しい独立したものを取得する必要があります)。したがって、最初のケースには「いいえ」です。

共有マッピングを使用すると、同じマッピングを所有するすべてのプロセスが同じ物理メモリにアクセスできます。つまり、forkマッピングを作成した後forkは、ほとんど通常の方法で動作し、プロセスが所有するすべてのページをコピー オン ライトとしてマークしますが、マッピング内のページは除きます。親と子の両方がマップされたページを保持し、ポインターを介して同じ物理メモリにアクセスできます (ちなみに、これはページにも同じ仮想アドレスがあることを意味します。これは通常、信頼できるものではありません。ファイルをマッピングするときにオンになりますが、この場合、OS はこれが事実であることを確認する以外に選択肢がありません)。

マンページは、匿名マッピングと共有マッピングの組み合わせ、または正確に何が起こるかについてあいまいなままですが、TLPI の 49.7 章では次のように明示的に言及されていますMAP_SHARED|MAP_ANONYMOUS

[...] fork() の呼び出しが続くと、fork() によって生成された子がマッピングを継承するため、両方のプロセスがメモリ領域を共有します。

したがって、2 番目のケースでは「はい」です。

Re: 投稿を編集しました
順序が間違っています:

fork();
shm_pipe_init();

これは最初に分岐してから、共有メモリを初期化します。これは、プロセスごとに個別に共有 (共有可能として読み取ります。プロセスが再び fork した場合、将来共有される可能性がありますが、魔法のように親と逆共有することはありません!) マッピングを作成するだけです。

次に、各プロセスに 1 つずつ、それぞれの子プロセスと孫プロセス (存在する場合) によって共有される2 つのマッピングがありますが、目的を達成するためには何も役に立ちません。それらが「共有」されているという事実は重要ではありません。それらは異なるマッピングであり、それぞれの他のプロセスには知られていません。

最初にマッピングを作成してからフォークします。これにより、両方のプロセスが実際に所有/共有し、意図した目的に使用できる1 つの共有マッピングが作成されます。

(さらに、あなたの の使い方forkは厳密に間違っているわけではありませんが、少し奇妙です... 通常は戻り値をチェックすることになっているので、どちらが親でどちらが子であるかがわかりますfork。もちろん、親と子は常に 100% 同一であり、失敗を気にしないので、それがまったく問題にならない場合は、それで問題ありません。通常、通常は知りたいと思いますが)。

于 2012-07-31T11:59:23.123 に答える
2

ポインター への変更はに影響sharedPipeないため、それぞれに固有の値がありますmyPipe

于 2012-07-31T11:08:41.297 に答える
2

ここで正確に何をしているのかを見てみましょう

struct PipeShm myPipe = { /* initialization for all fields */ };

PipeShmこれにより、構造体がグローバル変数として割り当てられます

struct PipeShm * sharedPipe = &myPipe;

これにより、以前に作成された構造体へのポインターが作成されます。

sharedPipeこれで、以前に割り当てた構造体の代わりに、返されるものmmap(おそらく共有メモリの領域へのアドレス) へのポインターを変更しています (注:myPipeまだ存在します - 指していないだけです)。

sharedPipe = mmap (NULL, sizeof * sharedPipe, PROT_READ | PROT_WRITE,MAP_SHARED | MAP_ANONYMOUS, -1, 0);

私が見る限り、あなたは へのアクセスも試みていませんsharedPipe。これで、基本的にグローバル変数共有メモリのセクションができました (どちらも未使用のように見えます)。

これは、あなたが何をしようとしているのかよくわからないところです。

共有メモリにアクセスしたい場合は、リターンsharedPipe後にポインターを逆参照する必要がありmmapます (そうであれば、グローバル変数のポイントは何でしたか?)。

グローバル変数にアクセスしたい場合は、次のようにアクセスするだけですmyPipe(そうであれば、何mmapの目的でしたか?)。

両方にアクセスしたい場合は、上記の組み合わせを使用します (そうであれば、何をする必要がありましたstruct PipeShm * sharedPipe = &myPipe;か?)

于 2012-07-31T11:47:48.263 に答える