C 中通过 FIFO 管道的指针结构

structure with pointer through FIFO pipe in C

我正在尝试使用一台服务器和一台客户端设置一个 FIFO 管道。

client.c

#include<stdio.h> 
#include<fcntl.h>
#include<stdlib.h>
#include<string.h>

typedef struct buffer {
     int pid;
     char *buffer;
 } my_buffer;

/*
void removefifo() {
unlink("fifo_server");
unlink("fifo_client");
}
*/

main(int argc, char *argv[]) {
    if (argc != 2) {
    fprintf(stderr, "usa: %s text \n", argv[0]);
    return EXIT_FAILURE;
    }

 FILE *file1;
 int fifo_server,fifo_client;
 char *buf_in;
 buf_in = malloc(20*sizeof(char));

 //send PID and content
 my_buffer * buf_out;
 buf_out = (my_buffer *)malloc(sizeof(my_buffer));
 buf_out->pid = getpid();
 buf_out->buffer = (char *) calloc(20,sizeof(char));
 strcpy(buf_out->buffer,argv[1]);

 fifo_server=open("fifo_server",O_RDWR);
 if(fifo_server < 0) {
  printf("Error in opening file");
  exit(-1);
  }

 printf("buffer has PID %d and content %s \n",buf_out->pid,buf_out->buffer);


 write(fifo_server,buf_out,sizeof(struct buffer));

 fifo_client=open("fifo_client",O_RDWR);

 if(fifo_client < 0) {
  printf("Error in opening file");
  exit(-1);
  }


 read(fifo_client,buf_in,10*sizeof(char));
 printf("\n * Reply from server: %s * \n",buf_in);
 close(fifo_server);
 close(fifo_client);

}

server.c

#include<stdio.h> 
#include<fcntl.h>
#include<stdlib.h>
#include<string.h>
#define FIFO_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) //0666

typedef struct buffer {
     int pid;
     char *buffer;
 } my_buffer;




int main()
{
int fifo_server,fifo_client;
char *buf_out;
int i;

int file1,file2;

my_buffer * buf_in;
buf_in = (my_buffer *)malloc(sizeof(my_buffer));
buf_in->buffer = (char *) calloc(20,sizeof(char));
buf_out = malloc(20*sizeof(char));

//create fifo-server with p-flag
file1 = mkfifo("fifo_server",FIFO_MODE); 
if(file1<0) {
 printf("FIFO_SERVER already exists \n");
 }

fifo_server = open("fifo_server",O_RDWR);
if(fifo_server<1) {
 printf("Error opening file");
 }
read(fifo_server,buf_in,sizeof(struct buffer)); //read PID and content
if(fifo_server<1) {
 printf("Error opening file");
 }

printf("pid %d \n",buf_in->pid);
printf("content %s \n",buf_in->buffer);

//write
strcpy(buf_out,buf_in->buffer);
for (i = 0; buf_in->buffer[i] != '[=11=]'; i++) {
    buf_out[i] = toupper(buf_in->buffer[i]);
}

//create fifo-client with p-flag
file2 = mkfifo("fifo_client",FIFO_MODE); 
if(file2<0) {
 printf("FIFO_CLIENT already exists \n");
 }


fifo_client = open("fifo_client",O_RDWR);
write(fifo_client,buf_out,10*sizeof(char)); 
printf("\n Data sent to client \n");


close(fifo_server);
close(fifo_client);

}

我先启动服务器,再启动客户端。特别是,当我 运行 客户端

./client "the fox"
buffer has PID 14491 and content the fox 

服务器正确显示 PID 但在打印 buf_in-> 缓冲区时崩溃。

./server 
pid 14491 
Errore di segmentazione

还望多多指教

您的 struct buffer 在其成员中包含一个指针。这很好,但您需要认识到,无论指向什么,如果有的话,是 不是 的一部分 struct,并且指针本身充其量是 在管道的另一端无效。您有两个主要选择:

  1. 给你的struct一个数组成员而不是指针成员:

    typedef struct buffer {
        int pid;
        char buffer[20];
    } my_buffer;
    
  2. 在编写数据时要更加小心。例如:

    unsigned buf_size = strlen(buf_out.buffer);
    write(fifo_client, &buf_out.pid, sizeof(buf_out.pid));
    write(fifo_client, &buf_size, sizeof(buf_size));
    write(fifo_client, buf_out.buffer, buf_size);
    

后者自然要搭配相应的读取机制

听起来不错,但固定缓冲区大小的问题是传输的字符串的一小部分或真正的字符串到达​​服务器后不需要的字符。