This code below is supposed to execute external programs passed as arguments to the main
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
int main(int argc ,char* argv[])
{
int e =0;
int* f=&e;
printf("%p\n",f);
pid_t p ;
for(int i=1;i<argc;i++)
{
p=fork();
wait(NULL);
if(p==0)
{
printf("\n---------------------\n");
execvp(argv[i],&argv[i]);
printf("erreur \n");
(*f)=(*f)+1;
printf("%d\n",*f);
printf("%p\n",f);
exit();
}
}
if(p>0)
{
printf("erreurs: %d \n",*f );
}
return 0;
}
The program also aims to show how many errors occured. However, the variable e=0 remains 0 even if the pointer *f pointing to its address was incremented inside the child fork.
How do I fix this problem?
When you call fork the process is duplicated. The parent and the child each have their own private memory maps, their own set of all variables. It's not possible for one process to change the value of another process variables.
If you want to share data between two processes you should use other inter-process communication methods, like for example shared memory.
Related
I am trying to understand the fork() concept and there's is one thing I can't seem to understand.
In the following code - why does the parent still print i=0 even when child process changes it to 5?
The wait(NULL) blocks parent process until child finishes first.
int main(int argc, char *argv[]) {
int i = 0;
if (fork() == 0) {
i = 5;
} else {
wait(NULL);
printf("i = %d\n", i);
}
return 0;
}
Can somebody explain why my assumption is incorrect?
Variables are not shared between processes. After the call to fork, there are two completely separate processes. fork returns 0 in the child, where the local variable is set to 5. In the parent, where fork returns the process ID of the child, the value of i is not changed; it still has the value 0 set before fork was called. It's the same behavior as if you had two programs run separately:
int main(int args, char *argv[]) {
int i=0;
printf("i = %d\n", i);
return 0;
}
and
int main(int argc, char *argv[]) {
int i = 0;
i = 5;
return 0;
}
Processes are not threads! When you fork, you create a full cloned process, with independant memory allocation that simply contains same values (except for the result of the fork call) at the time of the fork.
If you want a child to update some data in the parent process, you will need to use a thread. A thread shares all static and dynamic allocated memory with its parent, and simply has independant automatic variables. But even there, you should use static allocation for i variable:
int i = 0;
int main(int argc, char *argv[]) {
...
When you fork the child process gets a copy of the address space of the parent address space, they don't share it, so when the child changed i the parent won't see it.
This copying of the address space it typically done using copy on write to avoid allocating memory that will never change.
I understand that both parent and child in fork() are two separated processes, but I was trying to understand the behavior of a static variable when it's declared and initialized in the child. Consider this code please:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
static int z = 99;
void main(){
int x=99;
int pid;
pid = fork();
switch(pid){
case -1: printf("fork failed.");break;
case 0: printf("I am the Child[PID=%d].\n",getpid());
static int y=99;
x++;y++;z++;
printf("x=%d, y=%d, z=%d\n",x,y,z);break;
default: wait(NULL);
//int y = 99;
printf("Child has finished. I am the parent[PID=%d].\n",getpid());
printf("x=%d, y=%d, z=%d\n",x,y,z);
}
}
Output:
Why in parent printf statement the value of y is 99? although that the parent waited for the child to finish, and in the child the value of y is changed to 100 "y++" after it was set to 99.
This is because y exists in two separate processes, i.e. two separate virtual address spaces. Changing one process won't affect the other process.
Compare this with threads, where threads share the same process, i.e. the same virtual address space, change will be seen by all threads.
Static variables are initialized at load time (compile time), not at run time. In the fork(), the memory image is copied, including these initialized static vaiables. The child performs the increment, the parent not.
#include<stdio.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/types.h>
#include<string.h>
#include<sys/stat.h>
#define SIZE 100
void main()
{
int shmid,status;
pid_t pid;
int i;
char *a,*b,d[100];
shmid=shmget(IPC_PRIVATE,SIZE,S_IRUSR | S_IWUSR);
pid=fork();
if(pid==0)
{
b=(char *) shmat(shmid,NULL,0);
printf("enter");
printf("%c",*b);
shmdt(b);
}
else
{
a=(char *) shmat(shmid,NULL,0);
printf("enter a string");
scanf("%s",&d);
strcpy(a,d);
shmdt(a);
}
}
I was trying to pass a string from the parent process to the child process. But before scanning the value into "d" the program switches to the child process. How should I correct this logical error? And how should I pass this string "d" to the child process?
After call to fork was made you never know which process will execute first. You must simply assert your code handles properly interprocess communication, whatever happens now.
You can use pipe(2) or shared memory to pass data between different processes on same host.
#include <unistd.h>
int pipe(int pipefd[2]);
But you can also read data into global variable before call to fork. Fork will create a copy of global data in new process.
Shared memory using shmget example.
Fork is a system call and it creates two processes one is called the parent and the other is called the child!
To enable them to communicate you need to apply interprocess communication techniques
You could use
1.Pipes
2.FIFO-also known as Named pipes
3.Shared Memory
4.Message Queue
5.Semaphore
Everything you need to know to use them is mentioned here!The sample codes are written after the description
I have to create a program that:
ask for a number
create a child process (using vfork)
calculate the square root (in the child process)
show the square root from the parent process
Here is my code
#include <stdio.h>
#include <sys/types.h>
#include <math.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
double n=0;
printf("Number: "); //ask number
scanf("%d", &n);
pid_t pid = vfork(); //create child process
if (pid==0)//if child process
{
printf("Child process started\n");
n = sqrt(n);//calculate square root
}
else//parent process
{
printf("Returnning to parent process\n");
printf("Square Root: %d",n);
}
return 0;
}
But my code doesnt work, can anyone help me?
Why would you expect it to work? Doing anything but exec or _exit after vfork results in explicitly undefined behavior. See:
vfork() system call
And some further discussion of the horrors of vfork:
http://ewontfix.com/7/
http://www.openwall.com/lists/musl/2012/12/31/16
In case it's interesting, here is a list of possible problems with your program (manifestations of the UB):
printf in the child could horribly corrupt the parent's stdio state.
n could be stored permanently in a register, in which case there's no way the parent could see the changes made by the child
The compiler can see that n is uninitialized in the else branch, so it need not generate any code to read it at all (this branch unconditionally invoked UB by accessing an object whose value is indeterminate).
You're calculating the square root in the child, but trying to print it in the parent. The parent has no idea what the square root is. If you want the parent to print the square root, then you'll need to communicate that value from the child back to the parent process somehow. It seems more likely that you're supposed to print the square root in the child process.
int main(int argc, char **argv) { int n=0;
pid_t pid = vfork(); //create child process
if (pid==0)//if child process
{
printf("Child process started\n");
scanf("%d",&n);
n = sqrt(n);//calculate square root
_exit(23);
}
else//parent process
{
printf("Returnning to parent process\n");
printf("Square Root: %ld",n);
}
return 0; }
I have studied that during a fork, the data and code segment of the parent process gets duplicated into the child process.
Kindly see the program below.
int main()
{
int a = 5;
pid_t pid;
pid = fork();
if(pid == 0)
{
printf("In child a = %d",a);
}
else
{
printf("In parent a = %d",a);
}
return 0;
}
Here a is in the stack segment of parent process as it is declared inside the function, main(). The child process should only get copy of the code and data segment of the parent process and not the stack during fork(). But when I run the program, I can see that the child process is able to access the variable 'a' also. Thats means somehow the stack of parent process is also copied into the child process.
Kindly tell me the reason for this and correct me if my understanding is wrong.
You should check the docs again. fork creates an "exact copy of the calling process". Admittedly, there are a lot of exceptions, but the stack is not one of them.
Also, if the stack wasn't duplicated, the very common idiom (also used in your code) of checking the return value (almost always a stack variable) from fork would fail. There wouldn't be a stack position for pid unless the stack (including stack pointer) was duplicated.
That isn't a good test - as Matthew has pointed out, fork() gives you an exact copy of the parent process, including the stack (else the child would be unable to return from this function).
A better test is to modify 'a' in the parent and observe it in the child, like this:
#include <stdio.h>
#include <unistd.h>
int main()
{
int a = 5;
pid_t pid;
pid = fork();
if (pid == 0)
{
sleep(5);
printf("In child a = %d\n",a);
}
else
{
a++;
printf("In parent a = %d\n",a);
}
return 0;
}
and the result is correct:
pandora:~/tmp$ cc -o x x.c
pandora:~/tmp$ ./x
In parent a = 6
pandora:~/tmp$ In child a = 5