How to pass arguments to processes created by fork() - c

I want to create copies of a process using fork() in C.
I cant figure out how to pass arguments to the copies of my process.
For example,I want to pass an integer to the process copies.
Or I what to do, if I have a loop in which I call fork() and want to pass a unique value to processes (e.g. 0...N)
for (int i = 0; i < 4; ++i) {
fork();
// pass a unique value to new processes.
}

The nice part about fork() is that each process you spawn automatically gets a copy of everything the parent has, so for example, let's say we want to pass an int myvar to each of two child processes but I want each to have a different value from the parent process:
int main()
{
int myvar = 0;
if(fork())
myvar = 1;
else if(fork())
myvar = 2;
else
myvar = 3;
printf("I'm %d: myvar is %d\n", getpid(), myvar);
return 0;
}
So doing this allows each process to have a "copy" of myvar with it's own value.
I'm 8517: myvar is 1
I'm 8518: myvar is 2
I'm 8521: myvar is 3
If you didn't change the value, then each fork'd process would have the same value.

Local and global variables are inherently preserved across a fork(), so there's no need to "pass arguments". If you're calling a function in the forked process, you can do something like:
pid_t pid = fork();
if (pid == 0) {
funcToCallInChild(argument);
exit(0);
}

I'm late to respond, but here is how I do it:
const char *progname = "./yourProgName";
const char *argument1 = "arg1";
const char *argument2 = "arg2";
if (fork() == 0)
{
// We are the child process, so replace the process with a new executable.
execl(progname, progname, argument1, argument2, (char *)NULL);
}
// The parent process continues from here.
First, you fork() the process to create a new process. It still has the same memory space as the old one. fork() returns for both parent and child processes. If fork() returns zero, you are the child process. The child process then uses execl() to replace the process memory with one from a new file.
Notice that progname is given twice to execl(). The first is what execl() will actually try to run, the second is argv[0]. You must provide both or the argument count will be off by one. Progname must contain all the required path information to find the desired executable image.
I give two arguments in this example, but you can pass as many as you want. it must be terminated with NULL, and I think you have to cast it as (char *) like I show.
This approach gives you a fully independent process with arguments and a unique pid. It can continue running long after the parent process terminates, or it may terminate before the parent.

You can use clone() (which is actually used by fork() itself). It lets you pass an arg to your entry function.
http://linux.die.net/man/2/clone

See the exec() family of functions.
EDIT: If you're trying to initialize copies of the same program as the base process, just continue using variables as suggested by duskwuff.

Related

fork ( ) - C programming

I'm having issues working out where a good starting point for this is,
I have made dot points on what I exactly need to do but am unsure if this is entirely possible.
I have a file that I want to run multiple instances of
I want a new ID assigned to each process for the file
I need to assign a char eg. 'A' that was given through argv[1] to a process
If there is already a process with the char given, print to stderr
So far,
what I am thinking is, having something like the function below. But i'm really not too sure,
any help would be awesomeness.
int createProcess(char *argv[]){
//argv[1] is given 'A'
//fork()
//getPID()
//assign PID to 'A'
}
I think you are looking for a combination of fork and execl. You can fork to create multiple instances and then replace one of the forked process with another process by using exec(In your case it is the same process). Through execl you can give command line arguments. You may need to use sprintf in the exec'd process and sscanf in the original process. I guess this is enough hint.
I have a file that I want to run multiple instances of
To do that you have two options :
1. You can use multiple fork() system call to duplicate new child processes and open the file in those processes.
2. You can have multiple threads in your program that open the same file.
But looking at the next three dots, fork() is the choice to go with.
I want a new ID assigned to each process for the file
When you duplicate processes using fork() each process gets its own unique process Id(pid).
I need to assign a char eg. 'A' that was given through argv[1] to a process
For this you need to use one of the many calls in the "exec" family.By using "exec"
you can also pass the command line parameters to the newly created processes.
This cannot be done by fork because fork is used to duplicate the current process, whereas if you want to create a totally new process you must use exec calls.
Edit :
In order to get the command line parameters being passed to a process, you need to
know its process id and then you can look for a directory with its name same as the pid
inside the /proc file system( not mounted on actual device ). When you find the directory
you will get the parameters passed to it in a file named "cmdline".
For more detail you can read about "/proc" file system.
You will need to create multiple forking (preferably iteratively) and index your children.* One way to do that is to let the original parent loop, and only let that process do the fork. The original parent loops k times, only creating one child process per iteration. On the created child, you do stuff only the current child process will, such as assign an identifier (such as the loop counter), perform exec, and exit after the child performs everything so it does not go to the next iteration to fork to create grandchild.
Please note that the call fork() is a syscall that causes the original process (now called parent process) to create a duplicate (called child process), as well as return an int value for the parent process only.
One thing you need to observe is that the forked processes are identical with only two exceptions: the value returned by fork() and the process pid (child usually have higher pid). The value returned on the parent is the child's PID. The value on the child process is always zero. Identifying returned value of fork() is the only way to identify it the process is a parent or child.
I have a file that I want to run multiple instances of
You may need to use a combination of fork() and exec. It is not clear which type of file you want to run. Are you reading from a file, writing from a file, or executing a file?
I want a new ID assigned to each process for the file
The PID itself is a new unique ID at the time a new process is created. However, you can use a counter so that only the parent can create multiple child processes, each with a unique ID.
I need to assign a char eg. 'A' that was given through argv[1] to a process
argv[1] is a string (char array), not a char.
If there is already a process with the char given, print to stderr
It is possible that you can keep track of all identifier chars on the original parent.
Here is some sample C code where only the parent creates the forking:
int main() {
for (int k = 1; k <= 16; k++) {
int r = fork();
if (r == 0) { // kth CHILD
printf("[%d] %d\n", getpid(), k);
exit(0);
}
else if (r > 0) {
int status;
wait(&status);
printf("[%d] P\n", getpid());
}
else return 1;
}
return 0;
}
If I understand what you want correctly is to "assign" different chars to different instances of the forked process.
You can do something like this:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[]){
char chr = *argv[1];
pid_t res;
res = fork();
if (!res)
chr++;
printf("%c \n", chr);
return 0;
}

How system function in C works

I have read that system function make use of execl, fork and wait functions internally. So, I tried to simulate working of system without using it. But I am not able to achieve the same working.
When we call a program using system function the code below(after) system() function call also executes. So to simulate system function i wrote this code below:
int main()
{
printf("In controller Start: %d\n\n",getpid());
system("./prog1");
printf("Forking New Process %d\n\n",fork());
printf("Process Id: %d\n\n",getpid());
execl("./infinite",0);
printf("In controller End\n\n");
return 0;
}
In the above code after running "infinite" program the last line does not get printed.
i.e. printf("In controller End\n\n");
What to do in order to print the last line and also execute the "infinite" program without using system function.
It would be great if someone can explain the step by step working of system function like which function is called by system first and so on.
Why execution is not continuing to last line like it must have did if we made a simple function call other than execl.
Foot notes:-
infinite: is a binary file created using C code.
The last line doesn't get printed because it is never executed. The execl function never returns if everything went okay, instead it replaces your program with the one in the call.
I highly recommend you read the manual pages for fork and execl.
In short, fork splits the current process into two, and returns differently depending on if it returns to the parent or the child process. In the child process you then does your exec call, while the parent process continues to do what it wants. The parent must however wait on the child process to finish, or the child process will become what is called a "zombie" process.
In your code, both the parent and the child processes calls exec.
this is basis of fork
/*previous code*/
if((cpid=fork())<0){
printf("\n\tFORK ERROR");
exit(1);
}
if(cpid==0){ /*SON*/
/*CODE FOR SON-your `execl("./infinite",0);` goes here*/
}else{ /*FATHER*/
/*CODE FOR FATHER-your `printf("In controller End\n\n");` */
}
dont forget that when making a fork memory and variables are copied to the SON pid
In your example you do the same thing in both the parent and the child process. You have to check the return value of fork, which indicates if you are in the parent or the child, and then exec in the child, while you wait in your main process.
When you call fork(), both the parent and child process continue executing the same code from that point, but the return value of fork() is different for each. Generally you would do some conditional logic based on that return value.
I would imagine that system() does something like this:
int childpid = fork();
if (childpid) {
/* This is the parent */
wait( childpid );
} else {
/* This is the child */
execl( program_name );
}
Since execl() replaces the current executable with a new one, the child will run that executable then end. The parent will wait for the child to complete then continue.
You are not performing any kind of conditional statement based on the return value of fork. If you don't make sure that one process does the exec and one does something else then both will do the same thing.
You usually want to check against 0 and then execute the program you want to run. 0 signals that everything went ok and you are in the child process.
int main()
{
int pid;
printf("In controller Start: %d\n\n",getpid());
system("./prog1");
pid = fork();
printf("Forking New Process %d\n\n",pid);
printf("Process Id: %d\n\n",getpid());
if (pid == 0) { /* Son process : execute the command */
execl("./infinite",0);
} else { /* Original process : keep working */
printf("In controller End\n\n");
return 0;
}
}

C: printf (with fork())

In the next code:
int i = 1;
fork();
i=i*2;
fork();
i=i*2;
fork();
i=i*2;
printf("%d\n", i);
Why 8,8,8,8,8,8,8,8 is printed, and not 1,2,2,4,4,8,8,8? fork() duplicate the process, and print the i before each fork. What I miss?
Given the code shown, you should be seeing eight lots of 6 (you wrote i = i + 2; instead of i = i * 2; for the last computation.
Since each process follows the same code path, each process will produce the same result.
To get the result you expected, you'd have to track whether each fork() yielded the parent or child process:
int i = 1;
if (fork())
{
i=i*2;
if (fork())
{
i=i*2;
if (fork())
i=i*2; // + --> *
}
}
printf(|%d\n", i);
I'm assuming there are no problems with the fork() operation. It is also interesting to note that you could invert any or all of the conditions and end up with the same result.
Because fork continues to execute the code as it goes downwards. So each of the processes will run through the i = i * 2 each time as they spawn off more children. Making it what you get and not what you expected (i.e. it doesn't jump to the end of the block once forked).
Info on fork: http://www.csl.mtu.edu/cs4411/www/NOTES/process/fork/create.html
Each new process gets a copy of the stack of the parent, so immediately after calling fork(), both parent and child have the same value for i -- but they don't have the same stack, just a copy... so changing i's value in one process has no effect on the other.
If you want two parallel pieces of code to share the same memory, either use threads (and memory that's in the heap, not on the stack), or use an explicit shared memory region.

working of fork in c language [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 11 years ago.
Now I have a problem in understanding the working of fork() system call.
I write a code which is following :
#include<stdio.h>
int main()
{
int a, b;
b=fork();
printf("\n the value of b = %d",b);
}
The output of this code is following :
Now I don't understand why the output is like this ?
After that i just add a line to my code and output is completely different.
my code is following:
int main()
{
int a, b;
b=fork();
When i run the code the output is following
2389my name is manish
the value of b = 0
Now I'm totally confused about the working of fork() call.
My question are following:
How fork() works?
Where the control goes after the fork() call?
Can any body explain why the outputs of codes written in problem?
Why the output of b occurring at different places means in first code
the output of b = 2260 is just before the output b = 0 while the value of b = 2389 is not just before the b = 0?
Please explain me the working of fork in the code written in the problem so that I can learn it properly .
It might help to first understand why the word fork was used to name this function. Ever heard of a "fork on the road?" At a fork, the process has to split paths.
First there is a single process executing normally until you reach the fork call. When fork is called, a new process is created, which is identical in virtually every way as the original process, except for the return value of the fork function. The newly created process is called the child process, and hence the process that spawned it is referred to as the parent process.
Since you'd want to perform different tasks for each branch of the fork, it necessitates that you be able to distinguish the child process from the parent process. That's where the return value of fork comes in: fork returns the process id (pid) of the child (the newly created process) to the parent; it returns 0 to the child. Also, should the execution of fork go wrong, the return value is -1.
In your code, you don't distinguish between the child and parent process, so both processes run the entire code that follows after the fork call.
//what the child process looks like after fork is called
int main()
{
int a, b;
b=fork(); // <-- current line of execution: 0 is returned to b
printf("\nmy name is manish\n");
printf("\n my name is anil\n");
printf("\n the value of b = %d",b);
}
// what the parent process looks like after fork is called
int main()
{
int a, b;
b=fork(); // <-- current line: child process id is returned
printf("\nmy name is manish\n");
printf("\n my name is anil\n");
printf("\n the value of b = %d",b);
}
As you can see, both processes have the same code following the fork, hence the output is repeated. Perhaps if you want the parent process to output Manish and the child to output Anil, then you can do something like:
int main()
{
pid_t b; // note that the actual return type of fork is
// pid_t, though it's probably just an int typedef'd or macro'd
b = fork();
if (b == -1) perror("Fork failed");
else if (b > 0) {
printf("My name is Manish\n"); // parent process
else
printf("My name is Anil\n"); // child process
printf("The value of b is %d\n", b);
return 0;
}
Finally, the last comment that must be made is that in your code, the output appears to have been executed first by one process in its entirety and then the other process in its entirety. That may not always be the case. For example, the operating system might allow the parent to execute the 'manish' output, then make this process wait, and handing the cpu over to the child process, which then executes 'manish'. However, the child process may continue and execute 'anil' and 'b' outputs, completing execution of the child process and thus returning execution back to the parent process. Now the parent finishes its execution by outputting 'anil' and 'b' itself. The final output of running this program may look something like:
my name is manish // executed by parent
my name is anil // child
the value of b = 0 // child
my name is anil // parent
the value of b = 2244 // parent
manish.yadav#ws40-man-lin:~$
Take a look at the man page for fork.
Also look at waitpid for proper handling of child processes by parent processes so you don't create zombies.
Edit: In response to your questions in the comments, I'll answer how you can simply run each process consecutively.
int main()
{
pid_t pid;
int i;
for (i=0; i<NUM_PROCESSES; i++)
{
pid = fork();
if (pid == -1)
{
perror("Error forking");
return -1;
}
else if (pid > 0)
{
// parent process
waitpid(-1, NULL, 0); //might want to look at man page for this
// it will wait until the child process is done
}
else
{
// do whatever each process needs to do;
// then exit()
doProcess(i);
exit(0);
}
}
// do anything else the parent process needs to do
return 0;
}
Of course, isn't the best code, but it's just to illustrate the point. The big idea here is the waitpid call, which causes the parent process to wait until the child process it just forked to terminate. After the child prcoess completes, the parent continues after the waitpid call, starting another iteration of the for loop and forking another (the next) process. This continues until all child process have executed sequentially and execution finally returns to the parent.
Fork creates a copy of your current process.
Both the original and the copy continue executing from the point at which fork() was called.
Because your code is executed twice, your print statements are also evaluated twice. In the copied process, the value of b is 0. In the original process, the value of b is the process ID of the copied process.
Once your processes start running concurrently, they will be scheduled independently by your operating system and thus you have no guarantees about when they will actually be run.
Forking is implemented by the OS. It basically creates a child process and starts running it after the fork().
The parent process receives the process id of the file process: b=fork(); b has the process id. The child process get a pid of zero.
(and 4) Because both process can either run in parallel or be time sliced, your output will vary.
You may want to check this out: http://en.wikipedia.org/wiki/Fork_(operating_system)
You'd better start from this.
Here you find explanation and code example.

Functionality of fork()

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.
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 sprintfing 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.
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
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.

Resources