I want the parent process to take the arguments to main() and send the characters in them one at a time to the child process through a pipe starting with argv[1] and continue through the rest of the arguments.(one call to write for each character).
I want the child process to count the characters sent to it by the parent process and print out the number of characters it received from the parent. The child process should not use the arguments to main() in any way whatsoever.
What am i doing wrong? do i need to use exec()?
output that isnt correct:
~ $ gc a03
gcc -Wall -g a03.c -o a03
~ $ ./a03 abcd ef ghi
child: counted 12 characters
~ $
here is the program..
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int 开发者_JAVA技巧argc, char *argv[])
{
int length = 0;
int i, count;
int fdest[2]; // for pipe
pid_t pid; //process IDs
char buffer[BUFSIZ];
if (pipe(fdest) < 0) /* attempt to create pipe */
printf("pipe error");
if ((pid = fork()) < 0) /* attempt to create child / parent process */
{
printf("fork error");
}
/* parent process */
else if (pid > 0) {
close(fdest[0]);
for(i = 1; i < argc; i++) /* write to pipe */
{
write(fdest[1], argv[i], strlen(argv[1]));
}
wait(0);
} else {
/* child Process */
close(fdest[1]);
for(i = 0; i < argc; i++)
{
length +=( strlen(argv[i])); /* get length of arguments */
}
count = read(fdest[0], buffer, length);
printf("\nchild: counted %d characters\n", count);
}
exit(0);
}
You said that "the child process should not use the arguments to main() in any way whatsoever". However, I see that your child process is using argc
. Doesn't this defeat your restriction?
You also say that you want "one call to write for each character". Your current implementation uses one call to write for each argument, not each character. Was this a typo? If not, you will want to use something more like this:
char nul='\0', endl='\n';
for (a=1; a < argc; ++a) {
for (c=0; c < strlen(argv[a]); ++c) {
write(fdest[1], &argv[a][c], 1);
}
write(fdest[1], &nul, 1);
}
write(fdest[1], &endl, 1);
This will write one character at a time, with each argument as a NULL-terminated string and a newline character at the end. The newline is only there to serve as a marker to indicate that there is no more data to send (and is safe to use since you won't be passing in a newline in a CLI argument).
The child process will just need to be a loop that reads incoming bytes one by one and increments a counter if the byte is not '\0'
or '\n'
. When it reads the newline character, it breaks out of the input processing loop and reports the value of the counter.
You have an error here:
write(fdest[1], argv[i], strlen(argv[1]));
You should take strlen(argv[i])
rather, or you're telling write()
to read past the space of argv[i] and invoke undefined behavior.
Note that you're only calling read() once. By the time you're calling read(), perhaps only one of the argv[]s have been written by the parent. Or 2. Or any number of them.
The problem is here
write(fdest[1], argv[i], strlen(argv[1]));
Notice that this is strlen of argv[1]
, it should be argv[i]
. You are actually referencing past the end of argv[2]
and argv[3]
in this loop
You are effectively writing strlen("abcd") * 3 characters which is 12 chars
In here:
for(i = 1; i < argc; i++) /* write to pipe */
{
write(fdest[1], argv[i], strlen(argv[1]));
}
strlen(argv[1])
should be in fact strlen(argv[i])
精彩评论