0

server.c と client.c の 2 つの C ファイルがあります。サーバーは fifo ファイルを作成し、入力を待って常に読み込む必要があります。クライアントは PID を取得し、その PID を fifo に書き込みます。これは、最初に起動するサーバー ファイルです。

int main(){
  int fd;
  int fd1;
    int bytes_read;
    char * buffer = malloc(5);
    int nbytes = sizeof(buffer);

    if((fd = mkfifo("serverfifo",0666)) == -1) printf("create fifo error");
    else printf("create fifo ok");

    if ((fd1 = open("serverfifo",O_RDWR)) == -1) printf("open fifo error");
    else{
        printf("open fifo ok"); 
        while(1){
            bytes_read = read(fd,buffer,nbytes);
            printf("%d",bytes_read);
            }
        }

return(0);
}

そして私のクライアントファイル:

int main(){

    int fd;
    int pid = 0;
    char *fifo;
    int bytes;

    if ((pid = getpid()) == 0)  printf("pid error");
    char pid_s[sizeof(pid)];
    sprintf(pid_s,"%d",pid); 


   if ((fd = open ("serverfifo",O_RDWR)) == -1)printf("open fifo error");
   else {
    printf("open fifo ok");

        bytes = write(fd,pid_s, sizeof(pid_s));
        printf("bytes = %d",bytes);

   }

    close(fd);
return(0);
}

私が得ている2つの主な問題は次のとおりです。pidをファイルに書き込むと、書き込んだバイト数が返されるため、問題ないように見えますが、fifoファイルのプロパティを確認すると、0バイトと表示されます。2 番目の問題は、読み取りが機能しないことです。表示される前にprintfを実行すると、実行されず、読み取りが何も返されず、フリーズします。サイトには同様の投稿がたくさんあることに気づきましたが、役立つものは何も見つかりませんでした。CodeBlocks で Ubuntu と GCC コンパイラを使用しています。

4

2 に答える 2

3

ここには多くのことが間違っています

char pid_s[sizeof(pid)];
sprintf(pid_s,"%d",pid); 

sizeof(pid)文字列表現ではなく、pid 値のサイズを返します。つまりsizeof(int)、アーキテクチャに応じて 4 または 8 になります。次に、印刷に進みます。これが機能する場合は、運が良ければ機能します (64 ビット マシンを使用している場合)。正しい方法は、それを行うことを選択した場合、適切な大きさのバッファーを割り当て、snprintf を使用してオーバーフローしないようにすることです。PID は 5 桁に収まるので、次のようになります。

char pid_s[8];
snprintf(pid_s, sizeof(pid_s), "%d", pid);

もちろん、この手順をすべてスキップして、代わりに pid の raw バイトを送信することもできます。

write(fd, (void*)&pid, sizeof(pid))

サーバーで同様の間違いを犯します。

char * buffer = malloc(5);
int nbytes = sizeof(buffer);

sizeof(buffer)再び 4 または 8 を返しますが、5 バイトを割り当てました。(malloc を使用して) ヒープに割り当てたい場合、これを行う正しい方法は次のとおりです。

char* buffer = malloc(8);
int nbytes = 8;

または、スタックに割り当てることもできます。

char buffer[8];
int nbytes = sizeof(buffer);

sizeof は魔法のようなものです。配列を渡すと、この場合は配列のサイズ (8*1) が返されます。

読み込み中は 5 バイトを読み込みますが、これは十分ではない可能性が高く (以前のバグにより 8 バイトを書き込んだため)、終了しません。あなたはこのように読むべきです

int pid;
read(fd, (void*)&pid, sizeof(pid));

また、実際に文字列を読み書きする場合は、次のようにします。

// client
char pid_s[8];
snprintf(pid_s, sizeof(pid_s), "%d", pid);
write(fd, pid_s, sizeof(pid_s));

// server
char pid_s[8];
read(fd, pid_s, sizeof(pid_s));

また、 read は書き込まれたものよりも少ない数を返す可能性があり、読み続けるには再度呼び出す必要があることに注意してください...

于 2012-12-18T15:30:09.410 に答える
0

さて、このコードには多くの間違いがあります... まず第一に、 sizeof はそのように機能していません。なぜ pid をシリアル化するのですか?

これは間違っています :

char pid_s[sizeof(pid)];

123456 は int であり、サイズ 4 のこの配列には収まりません。3 文字しか印刷できません...

また、pid をシリアル化しようとしているため、最悪の場合を想定して '\0' に 10 + 1 を書き込まない限り、予想される読み取りサイズがわかりません...

于 2012-12-18T15:28:07.723 に答える