问题
System information: I am running 64bit Ubuntu 10.10 on a 2 month old laptop.
Hi everyone, I've got a question about the fork()
function in C. From the resources I'm using (Stevens/Rago, YoLinux, and Opengroup) it is my understanding that when you fork a process, both the parent and child continue execution from the next command. Since fork()
returns 0
to the child, and the process id of the child to the parent, you can diverge their behavior with two if statements, one if(pid == 0)
for the child and if(pid > 0)
, assuming you forked with pid = fork()
.
Now, I am having the weirdest thing occur. At the beginning of my main function, I am printing to stdout
a couple of command line arguments that have been assigned to variables. This is this first non assignment statement in the entire program, yet, it would seem that every time I call fork
later in the program, these print statements are executed.
The goal of my program is to create a "process tree" with each process having two children, down to a depth of 3, thus creating 15 total children of the initial executable. Each process prints it's parent's process ID and its process ID before and after the fork.
My code is as follows and is properly commented, command line arguments should be "ofile 3 2 -p"
(I haven't gotten to implementing -p/-c
flags yet":
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char *argv[])
{
if(argc != 5)//checks for correct amount of arguments
{
return 0;
}
FILE * ofile;//file to write to
pid_t pid = 1;//holds child process id
int depth = atoi(argv[2]);//depth of the process tree
int arity = atoi(argv[3]);//number of children each process should have
printf("%d%d", depth, arity);
ofile = fopen(argv[1], "w+");//opens specified file for writing
int a = 0;//counter for arity
int d = 0;//counter for depth
while(a < arity && d < depth)//makes sure depth and arity are within limits, if the children reach too high(low?) of a depth, loop fails to execute
//and if the process has forked arity times, then the loop fails to execute
{
fprintf(ofile, "before fork: parent's pid: %d, current pid: %d\n", getppid(), getpid());//prints parent and self id to buffer
pid = fork(); //forks program
if(pid == 0)//executes for child
{
fprintf(ofile, "after fork (child):parent's pid: %d, current pid: %d\n", getppid(), getpid());//prints parent's id and self id to buffer
a=-1;//resets arity to 0 (after current iteration of loop is finished), so new process makes correct number of children
d++;//increases depth counter for child and all of its children
}
if(pid > 0)//executes for parent process
{
waitpid(pid, NULL, 0);//waits on child to execute to print status
fprintf(ofile, "after fork (parent):parent's pid: %d, current pid: %d\n", getppid(), getpid());//prints parent's id and self id to buffer
}
a++;//increments arity counter
}
fclose(ofile);
}
When I run gcc main.c -o ptree
then ptree ofile 3 2 -p
, the console is spammed with "32"
repeating seemingly infinitely, and the file ofile
is of seemingly proper format, but far far too large for what I think my program should be doing.
Any help would be greatly appreciated.
回答1:
I am not sure why the fputs
to stdout
would be executed for the children, and don't have a Unix box to hand to verify/test.
However, the following jumps out:
int depth = *argv[2];//depth of the process tree
int arity = *argv[3];//number of children each process should have
You are taking the ASCII codes of the first character in argv[2]
and argv[3]
as your depth
and arity
, so your code is trying to spawn 50^51
processes instead of 2^3
.
What you want is:
int depth = atoi(argv[2]);//depth of the process tree
int arity = atoi(argv[3]);//number of children each process should have
Once you fix this, bleh[0] = depth
and its twin will also need correcting.
edit Although this is not a problem right now, you're cutting it pretty close with the length of some of the things you're sprintf
ing into obuf
. Make some of the messages just a little bit longer and Kaboom! At the very least you want to use snprintf
or, better yet, fprintf
into the file directly.
edit I've just realised that fork
, being an OS function, most probably isn't aware of internal buffering done by C I/O functions. This would explain why you get duplicates (both parent and child get a copy of buffered data on fork
). Try fflush(stdout)
before the loop. Also fflush(ofile)
before every fork
.
回答2:
You have 2 errors in your code :
1)
int depth = *argv[2];//depth of the process tree
int arity = *argv[3];//number of children each process should have
With this code you are getting the first char of the strings argv[2] and argv[3]. A correct code must be like that :
int depth = atoi(argv[2]);
int arity = atoi(argv[3]);
2)
bleh[0] = depth;
fputs(bleh, stdout);
bleh[0] = arity;
fputs(bleh, stdout);
You can do something like that bleh[0] = (char) depth;
but you'll just keep the first byte of your integer and its not that you want to do i guess, if you want to print the whole integer, simply use :
printf("%d\n%d", depth, arity);
I just tryied your code with those modifications and it seems to work well :)
Anhuin
回答3:
You can't print out numbers using that code at the start of your function. It's probably invoking undefined behavior by passing a non-string to fputs()
. You should use sprintf()
(or, even better, snprintf()
) to format the number into the string properly, and of course make sure the buffer is large enough to hold the string representation of the integers.
Also, you seem to be emitting text to the file, but yet it is opened in binary mode which seems wrong.
来源:https://stackoverflow.com/questions/4459685/functionality-of-fork