Reputation: 7423
I posted a question previously about using fork() and pipes in C . I changed the design a little bit so that it reads a regular txt file and sorts the words in the file. So far, this is what I came up with:
for (i = 0; i < numberOfProcesses; ++i) {
// Create the pipe
if (pipe(fd[i]) < 0) {
perror("pipe error");
exit(1);
}
// fork the child
pids[i] = fork();
if (pids[i] < 0) {
perror("fork error");
} else if (pids[i] > 0) {
// Close reading end in parent
close(fd[i][0]);
} else {
// Close writing end in the child
close(fd[i][1]);
int k = 0;
char word[30];
// Read the word from the pipe
read(fd[i][0], word, sizeof(word));
printf("[%s]", word); <---- **This is for debugging purpose**
// TODO: Sort the lists
}
}
// Open the file, and feed the words to the processes
file_to_read = fopen(fileName, "rd");
char read_word[30];
child = 0;
while( !feof(file_to_read) ){
// Read each word and send it to the child
fscanf(file_to_read," %s",read_word);
write(fd[child][1], read_word, strlen(read_word));
++child;
if(child >= numberOfProcesses){
child = 0;
}
}
where numberOfProcesses
is a command-line argument. So what it does is that it reads each word in the file and send it to a process. This however, does not work. When I print the word in the child process, it doesn't give me the correct output. Am I writing/reading the words correctly to/from the pipes?
Upvotes: 0
Views: 1418
Reputation: 74098
In the parent, you write strlen()
bytes, which might be less than 30 bytes. In the child, however, you always try to read 30 bytes. You also must NUL-terminate the word, otherwise you might see garbage or a runaway string in your printf()
statement.
In the child, you must either parse and split the input at word boundary or use stdio as @JonathanLeffler proposed. When you use stdio, you get all this buffering and word reading for free.
int n;
char word[31];
/* Read the word from the pipe */
n = read(fd[i][0], word, sizeof(word) - 1);
if (n == -1) {
perror("read");
/* do error handling */
} else {
word[n] = 0;
printf("[%s]", word);
}
Upvotes: 1
Reputation: 3684
Are the words being printed in the wrong order or interleaved? The thing is that when you write a word to a pipe, you are expecting the process handling that pipe to be scheduled immediately and to print the word. Then you expect the main process to run again and the next word to be written to the next pipe etc.
But that is not guaranteed to happen. Your main loop might write all of the words to all of the pipes before any of the other processes is scheduled. Those processes might not be scheduled in the order you expect. And the printf calls might interfere with each other so that their output becomes interleaved.
If you really want to do what you set out to, then Posix threads would be better. If you just wanted to learn something about using multiple processes, then I guess you have :-)
Upvotes: 1