Reputation: 7576
I'm trying to send an array of structs through a pipe. I have a struct:
typedef struct visitordata {
char name[80];
char email[80];
int id;
char reg_time[9];
}visitordata;
Then I do
//...
//ds is the number of struct entries to be stored
visitordata* V;
V = (visitordata*)malloc(ds * sizeof(visitordata));
pid_t child = fork();
if(child < 0) {
perror("Fork error");
exit(1);
}
else if (child > 0) { //parent process
write(pipefd[1], &V, sizeof(V));
close(pipefd[1]);
fflush(NULL);
pause();
sleep(1);
pause();
kill(child,SIGTERM);
waitpid(child, &status, 0);
}
else { //child process
visitordata* data;
close(pipefd[1]);
read(pipefd[0], &data, sizeof(data));
close(pipefd[0]);
flush(NULL);
for (i = 0; i < ds; ++i) {
printf("Received: %s\r\n", data[i].name);
}
kill(getppid(), SIGUSR1);
pause();
}
But then, if I have two rows for input, the Received part only prints out one row with the string "free" (which I think comed from the username on the server: freeze@server:
) and then Received:
without anything else. What am I doing wrong?
EDIT
Updated the code as per suggestions:
visitordata* V;
V = (visitordata*)malloc(ds * sizeof(visitordata));
pid_t child = fork();
if(child < 0) {
perror("Fork error");
exit(1);
}
else if (child > 0) { //parent process
write(pipefd[1], V, ds * sizeof(V));
close(pipefd[1]);
fflush(NULL);
pause();
sleep(1);
pause();
kill(child,SIGTERM);
waitpid(child, &status, 0);
}
else { //child process
visitordata* data;
data = (visitordata*)malloc(ds * sizeof(visitordata));
close(pipefd[1]);
read(pipefd[0], data, ds * sizeof(data));
close(pipefd[0]);
flush(NULL);
for (i = 0; i < ds; ++i) {
printf("Received: %s\r\n", data[i].name);
}
kill(getppid(), SIGUSR1);
pause();
}
Now my output is like this:
Received: 0▒:▒0▒:▒
Received:
EDIT 2
Updated
read(pipefd[0], data, ds * sizeof(data));
and
write(pipefd[1], V, ds * sizeof(V));
to
read(pipefd[0], data, ds * sizeof(visitordata));
and
write(pipefd[1], V, ds * sizeof(visitordata));
Now my output is:
Received: 0Tɢ0Tɢ
Received:
Upvotes: 1
Views: 8226
Reputation: 1
read()
and write()
read and write up to the number of bytes requested. Per the POSIX standard for write()
:
The
write()
function shall attempt to writenbyte
bytes from the buffer pointed to bybuf
to the file associated with the open file descriptor,fildes
....
RETURN VALUE
Upon successful completion, these functions shall return the number of bytes actually written to the file associated with
fildes
. This number shall never be greater thannbyte
. Otherwise, -1 shall be returned and errno set to indicate the error.
Your code never checks the results of write - you merely hope it works. To ensure the entire requested number of bytes is written, you need something like this:
size_t bytesToWrite = ds * sizeof(visitordata);
size_t totalWritten = 0;
for ( ;; )
{
ssize_t bytesWritten = write( pipefd[1], V + totalWritten,
bytesToWrite - totalWritten );
if ( bytesWritten <= 0 )
{
break;
}
totalWritten += bytesWritten;
}
You need to handle read()
similarly.
Upvotes: 2
Reputation: 212979
You are passing incorrect parameters to both write
and read
. You need to pass a pointer to the actual data, and the length of the data in bytes.
So:
write(pipefd[1], &V, sizeof(V));
should be:
write(pipefd[1], V, ds * sizeof(visitordata)); // note: 2 fixes here
and similarly:
read(pipefd[0], &data, sizeof(data));
should be:
read(pipefd[0], data, ds * sizeof(visitordata)); // note: 2 fixes here also
data
pointer is not initialised (it's just a wild pointer). Change:
visitordata* data;
to:
visitordata* data = malloc(ds * sizeof(visitordata));
Upvotes: 0
Reputation: 65
This smells:
write(pipefd[1], &V, sizeof(V));
Maybe this is better:
write(pipefd[1], V, sizeof(V));
The receving part is also problematic. Where do allocate a buffer for it? visitordata* data;
Upvotes: -1