3

私はコマンドを理解しようとしていますpipe(2)、例えば:

int pipefd[2];
if (pipe(pipefd) == -1) {
    perror("pipe");
    exit(EXIT_FAILURE);
}

shared memory匿名パイプ(父と息子の関係)用に、を含む2つのファイル記述子を取得したいと思います。

たとえば、これは父と息子のプロセス間の簡単な話です:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <sys/wait.h>  
#include <unistd.h>    
#include <string.h>   
#define SHMSIZE 16
int main() {
   int shmid;
   char *shm;

   if(fork() == 0)   // child first

   {

      shmid = shmget(2009, SHMSIZE, 0);
      shm = shmat(shmid, 0, 0);
      char *s = (char *) shm;
      *s = '\0';
      int i;

      // child enters the input that would be stored in the shared memory
      for(i=0; i<3; i++) {
         int n;
         printf("Enter number<%i>: ", i);
         scanf("%d", &n);

         // convert the input into a c-string
         sprintf(s, "%s%d", s, n);
      }
      strcat(s, "\n");

      // display the contents of the shared memory
      printf ("I'm the child process , and I wrote:%s\n",shm);

      // detaches the shared memory segment
      shmdt(shm);
   }


   else   // parent

   {

       // get the segment
      shmid = shmget(2009, SHMSIZE, 0666 | IPC_CREAT);

      // attaching the segment to the father
      shm = shmat(shmid, 0, 0);

      // father waits for the son the finish
      wait(NULL);

      // father displays what the son wrote
      printf ("I'm the father , and my child wrote :%s\n",shm) ;

      // detaches the shared memory segment
      shmdt(shm);

      shmctl(shmid, IPC_RMID, NULL);
   }
   return 0;
}

出力は非常に単純です:

Enter number<0>: 123
Enter number<1>: 567
Enter number<2>: 789
I'm the child process , and I wrote:123567789

I'm the father , and my child wrote :123567789

これは私の実装であり、 :shm_pipe_pipe()の代わりになります。pipe(2)

int shm_pipe_pipe(int spd[2])
{
    spd[0] = shmget(2009, SHMSIZE, 0);
    spd[1] = shmget(2009, SHMSIZE, 0666 | IPC_CREAT);

     if (spd[0] == -1 || spd[1] == -1)
         return -1;
     return 1;

}

私の質問は:

  1. fd[0]私はそれが読み取りと書き込みに使用されることを理解してfd[1]いますが、それらは正確に何を保持していますか?住所?

  2. 上で書いた関数が機能shm_pipe_pipeしていないようですが、何が問題になっていますか?

ありがとう`

4

1 に答える 1

8
  1. あなたの最初の質問に答えてください、彼らはファイル記述子を持っています。それらはアドレスではありません。これらはテーブルへのインデックスです。このテーブルには、実際にはカーネルによって解釈されるアドレスが含まれています(記述子がディスクファイルの場合はファイルシステム、ネットワークソケットの場合はネットワークスタックなど)。ファイルのユーザーに実際のアドレスが与えられることはありません。実際のアドレスを含むテーブルへのインデックスのみがユーザーに提供されます。このテーブルの構造は非常に複雑で、サブシステムによって異なります。しかし、基本的な概念は比較的同じです。

次の画像はディスクファイルに有効です。

このイメージはディスクファイルに有効です

2つの独立したプロセスの場合:

2つの独立したプロセス

パイプの場合..

これがPipeの仕組みであり、2つのファイル記述子だけです。

これはファイル記述子テーブルの一般的なビューです FDT

  1. pipefd2番目の質問は、によって返された値からファイル記述子配列にデータを入力しようとしているようですshmget()

からman 2 shmget

shmget()は、引数キーの値に関連付けられた共有メモリセグメントの識別子を返します。キーの値がIPC_PRIVATEであるか、キーがIPC_PRIVATEでなく、キーに対応する共有メモリセグメントが存在せず、IPC_CREATが指定されている場合、サイズがPAGE_SIZEの倍数に切り上げられたサイズの値に等しい新しい共有メモリセグメントが作成されます。 shmflgで。

shmget()が何をするかを理解することは重要です。切り上げたサイズ(usnigシステムのPAGE_SIZE)を要求します。メモリのこのセグメントは、キーによって識別されます。したがって、カーネルはキーvlaueテーブルを維持します。このテーブルには、共有メモリ領域のアドレスも含まれています。ここで、を呼び出すときにshmat()、を使用してこのテーブルにクエリを実行するshmidと、返されたアドレスがプロセスのアドレス空間に添付されます。

したがって、shmidによって返されるのshmget()は、システムによって維持されるキーと値のペアのテーブルのエントリであり、によって使用されるファイル記述子とは関係ありませんpipe()

結論は次のとおりです。

そのように実装することはできませんpipepipeそれ自体の実際の実装を見てみませんか?

http://sourceware.org/git/?p=glibc.git;a=blob;f=io/pipe.c;h=07a37ae778046e56c13e62fd2a2fa678f5546424;hb=HEAD

そのファイルには何も役に立ちませんが、otherを呼び出すだけなので__pipe。gitリポジトリのクローンを作成し、cscopeを使用しての実際の実装を見つけることができますpipe

于 2012-07-18T10:58:52.913 に答える