Read / Write through a pipe in C

2019-01-28 10:02发布

I started today working with pipe() and fork() and exec() in C, and I now have a problem:

The main program, creates two pipes and forks. The child process does an exec() to another program that now is only a test program which reads from stdin, communicates with its parent and writes through stdout ther results. The main program is supposed to recive data, communicate with a SQLite 3 database and return data using pipes. This part of the problem is solved, the pipes are open and closed properly and there's communication.

Then the problem is, in the child process (the one which is called with exec()) in a certain point, I have this:

printf("Strid sent: %s\n", strid);
write(4,strid,sizeof(strid));

printf("Str sent: %s\n", str);
write(4,str,sizeof(str));

And the parent should be reading properly with this part:

read(select[0],strid, sizeof(strid));
printf("Strid recived: %s\n",strid);
int id = atoi(strid);
printf("Id recived: %d\n",id);

read(select[0],buffer, sizeof(buffer));
printf("Buffer recived: %s\n",buffer);

But what I recive whith those printf is:

Strid sent: 1
Str sent: start
Strid recived: 1
Id recived: 1
Buffer recived: 7� (and other strange characters)

As you can see, the problem is in the receiving of the second command (and that part is copied as is, there's no other code into it).

I have to say too that "buffer" variable, which recives str, is declared as char buffer[20] and has not been used before the read()

Thank you in advance!

标签: c fork pipe
2条回答
太酷不给撩
2楼-- · 2019-01-28 10:47

pipes don't keep track of 'boundaries' between writes. So if you have multiple writes on the pipe, all the data from those writes might come back in response to a single read. So if you send a string (for example) followed by an integer, and you attempt to read the string into a buffer, it will get both the string and the following integer integer into the buffer, looking like garbage on the end of the string, and the size returned by read will be larger.

In addition, if the pipe is getting full, a write might not write all the data you asked it to -- it might write only as much as can fit for now, and you'll have to write the rest later.

so ALWAYS check the return values of your read and write calls and be prepared to deal with getting less than (or more for read) than you expect.

查看更多
时光不老,我们不散
3楼-- · 2019-01-28 10:54

After read, you need to add terminating 0 byte at the end, before printing, something like

int len = read(select[0], buffer, sizeof(buffer) - 1);
if (len < 0) {
    perror("read error");
} else {
    buffer[len] = 0;
    printf("Buffer recived: %s\n", buffer);
}

So, imporant thing, read through man page of read, or actually man page of any function before you use it...

Alternatively, use some stdio.h function, which adds string terminating 0 themselves, probably fgets if reading line by line is ok.

查看更多
登录 后发表回答