C Programming vfork return value - c

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; }

Related

Junk values after scanf child process

my scanf statement, in a child process, does not work properly:
int main(int argc, char **argv)
{
int operando, operatore;
pid2 = fork();
if (pid2 == 0) { // Figlio 2
printf("Inserisci due numeri: ");
scanf("%d%d", &operando, &operatore); //even though I " %d%d"...
printf("Operando is %d and operatore is %d\n", operando, operatore);
}
return 0;
}
This is the output:
error
How do I fix?
See this question for an explanation of what is happening in your program: Child process cannot read after the exiting of parent process. The most important part:
The terminal is controlled by the foreground process group. When the shell invokes the parent, it makes the parent the leader of the foreground process group. The child inherits that group and has access to the terminal.
However, when the parent exits, the shell takes back control of the terminal and becomes the leader of the foreground process group. The child is no longer in the foreground process group, so it has no access to the terminal.
To get your program to work as expected, add a wait call in the parent process to ensure the parent process does not exit until the child process has completed thus keeping the terminal available for the child.
For example:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int argc, char **argv)
{
int operando, operatore;
pid_t pid2 = fork();
if (pid2 == 0) { // Figlio 2
printf("Inserisci due numeri: ");
scanf("%d%d", &operando, &operatore); //even though I " %d%d"...
printf("Operando is %d and operatore is %d\n", operando, operatore);
} else if (pid2 > 0) {
wait(NULL);
}
return 0;
}
Note, some other general improvements to consider:
Always check the return value of function calls. scanf in particular should be checked before using the results in the printf. Similarly the fork return value should be checked for error.
The call to scanf() failed. The code could have known this if it had checked the returned value of scanf() Any returned value other than 2 would indicate an error occurred.
The scan() failed on the first 'input format conversion` specifier, so it never looked at the second 'input format conversion' specifier.
When a integer 'input format conversion' specifier in a call to scanf() fails, the target variable is set to 0. The second variable displays what ever trash was in memory at its' location on the stack.

Incrementing a variable value through a pointer inside a child fork

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.

Operations on child processes C

I want to create a program that:
Create child processes
List all child processes
Read PID to kill one of child processes
List all child processes again.
My code:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
int main(void) {
int c = 0;
printf("How many: ");
scanf("%d", & c);
int i = 0;
for (i = 1; i <= c; i++) {
pid_t pid = fork();
if (pid == 0) {
exit(0);
}
}
ListOfChildren();
int t;
printf("Kill child: ");
scanf("%d", & t);
char test[50];
snprintf(test, sizeof(test), "kill -15 %d", t);
system(test);
ListOfChildren();
return 1;
}
int ListOfChildren() {
char str[50] = "ps -o pid --ppid ";
char ppid[7];
sprintf(ppid, "%d", getpid());
strcat(str, ppid);
system(str);
return 1;
}
It creates some processes but the last process is not exist? And i can't kill
not even one... And why it shows 4 process when i want 3?
Because when you fork, your children immediately exit, this is likely that they are already dead when you try to kill them (likely, not mandatory, it depends on the scheduler). Same thing for listing: the processes you see are some of the remaining processes not yet exited and the process "ps" itself, created by your first process.
To answer your first question
The last process does not exists because, it is the child process which was forked by the system command in your program and this process is no longer valid once the command returns, hence you are not able to see the process. For more details have a look at the man page of the system command
http://linux.die.net/man/3/system
For the second question, indeed your child processes have finished executing and they have become defunct processes. you can check them in your program by executing
ps -ef | grep defunct
before you enter some option from "Kill child: ". Then you will see the child processes you forked in the program are defunct.
The reason they have become defunct is
The parent process has to explicitly take notice of
the childs demise by using the wait() system call.
http://en.linuxreviews.org/Defunct_process
You cannot kill them normally with a
kill -9 pid
That is why the "kill" does not work for you.

Static variable in child process of fork

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.

Segments duplicated during fork()?

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

Resources