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.
Related
I'm writing a program that accepts two integer values from the user as input, X and Y (it's for an assignment).
The tricky part is that the program has to create a parent and child, where the parent process will read X and the child process will read Y (using scanf).
The expected output of the program is the following:
From parent 2255: child with PID 2256 is created
From parent 2255: Reading X from the user
>> 99
>> X in parent is 99
From child: Reading Y from the user
>> 88
>> Y in child is 88
The issue I'm having is that the child executes automatically, and doesn't wait until input is received in the parent.
My professor gave a hint that we can use sleep() at the beginning of child process to solve this problem, but I'm not having any luck.
My sample code (which isn't working):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h> // pid_t
#include <unistd.h> // NULL, fork()
#include <errno.h> // errno
int main(void){
// Initializing variables
int X = 0, Y = 0;
// Fork
pid_t pid;
pid = fork();
// ERROR
if (pid < 0){
// error handling
}
// PARENT
else if (pid > 0){
// Read X
printf("From parent %d: Reading X from the user\n>> ", pid);
scanf(" %d", &X);
printf("X in parent is %d\n", X);
// Some other code afterwards
}
// CHILD
else {
// Read Y
printf("From child: Reading Y from the user\n>> ");
scanf(" %d", &Y);
printf("Y in child is %d\n", Y);
// Some other code afterwards
}
return 0;
}
I would really appreciate any help. Thank you!
parent can wait for the child to finish, something along the following lines
printf("X in parent is %d\n", X);
int status = 0;
waitpid(pid, &status, 0);
// Some other code afterwards
The side effect is that // some other code afterwards will only be executed after child has exited.
If synchronization is required between the two process for reading X & Y and then do computation then consider using conditional variable (wait/signal). Something like parent waits on a condition that's set by child so that parent can proceed further. The waitpid still might be a good idea unless you do not have a concern about creating a zombie process (that is the parent exits without reaping its child's status) or are setting the SIGCHLD appropriately.
I need to create a program that takes input from the user and executes it just like it does in the terminal. I am using the execvp() function for this purpose. The requirement of the program is to keep taking input from the user unless the quit call is encountered. The problem here is that the current program is replaced after the execvp() call. So, using a goto is not an option either. I found this Fork–exec article but it doesn't tell how to create an indefinite number of processes. Here is my code:
#include <unistd.h>
#include <stdio.h>
#include <string.h>
void main() {
char *args[4];
char inputCommand[100];
fgets (inputCommand, 100, stdin);
printf ("Splitting string \"%s\" into tokens:\n",inputCommand);
/* Perfrom string tokenization here */
execvp(args[0], args);
}
fork() can be called an indefinite number of times; as long as the return value indicates that you're the parent process, you can continue to operate as usual and call it again.
Thus, you can have a loop within which you fork, call an execvp() if you're the child process, and continue to the next iteration if you're the parent.
Execvp replaces the current process image with the command you run. So it cancels your C program. To produce the desired effect, you should fork before execvp. It would look something like this:
int status = 0;
pid_t pid = fork();
if(pid > 0) {
waitpid(pid, &status, 0);
// is parent
} else if(pid == 0) {
execvp(*args, args);
// is child
} else {
// fork didn't work
}
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.
`#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv){
int pid = 0;
int forever;
static char s; //Uses simply s in the while loop, press s once for each process to
//terminate each process
//char *s; This can't work because it always points to the start of a char array.
//I don't know why. int * doesn't do that.
pid = fork();
if(pid>0)// a child cannot see it's own process ID so pid would be 0 if it was the
child
printf("This is the parent.\n");
else if(pid == 0) printf("This is the child.\n");
while(s != 's'){//One quote is a character, two quotes is a char array
forever = fork();
if(forever>0)
printf("Parent process\n");
else printf("Child process\n");
s = getchar();//I tried making this *s but it causes a segmentation fault
}
return 0;
}`
This is causing a problem. When I execute the program from terminal, I can exit the program by entering 's' once for each process, and the terminal goes back to normal. Or so it appears. When I press the "up" arrow when in terminal, I go into an endless loop and get a fork bomb. How do I avoid this?
Change s to
int s = 0;
Because getchar returns int and you do need it. Also no point making it static (no harm either here, just bad/unusual style). Note that you now need initialization, unlike when it is static.
Then check getchar return value for error/EOF, <0 and terminate on that also. That should fix the fork bomb, because it is most likely caused by getchar starting to return immediately with error. Add prints to see what is happening, especially print the error message or EOF status.
Also you should check fork return value for errors as well, just in case.
I found this sample via a search.
At first glance I thought only the first fork() would be executed based on the IF condition, but actually both fork() calls get executed.
If the fork() command is changed to a simple boolean comparison like (x==10) then the IF conditions behave as expected.
What is it about the fork() that causes the IF condition to behave differently?
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
pid_t whichone, first, second;
int howmany;
int status;
int x = 0
if ((first=fork())==0) /* Parent spawns 1st child */
{
printf("Hiya, I am the first child nd my id is %d\n", getpid());
sleep(10);
exit(0);
}
else if (first == -1)
{
perror("1st fork: something went bananas\n");
exit(1);
}
else if ((second=fork())==0) /* Parent spawns 2nd child */
{
printf("Hiya, I am the second child and my id is %d\n", getpid());
sleep(15); /* Sleep 15 sec, then exit */
exit(0);
}
else if (second == -1)
{
perror("2nd fork: something went bananas\n");
exit(1);
}
printf("This is the parent\n");
howmany=0;
while (howmany < 2) /* Wait twice */
{
whichone=wait(&status);
howmany++;
if (whichone==first)
printf("First child exited ");
else
printf("Second child exited ");
if ((status & 0xffff)==0)
printf("correctly\n");
else
printf("uncorrectly\n");
}
return 0;
Here is the output when executed. Notice that both fork() calls are processed.
> runtThis
Hiya, I am the first child, and my id is 31204
Hiya, I am the second child, and my id is 31205
This is the parent
First child exited correctly
Second child exited correctly
The first if detects if its running in the child. If it isn't, but fork() didn't fail (i.e., it didn't return -1), it's in the original process, which can then continue and call fork() again.
Not sure what the confusion is about.
The fork() function duplicates the current process and then returns in both processes. So, effectively, the fork() function returns twice.
In the new process, fork() returns with the value 0, which causes the relevant branch that prints "I am the child" to be taken.
In the original process, fork() returns a non-zero value, indicating either failure (if it is negative) or the process id of the new process (if it is positive). As this value is non-zero, the branch is skipped to the next else if and that test is performed until one succeeds.
In the parent process, none of the if/else if tests will succeed, but each of the fork calls causes a new process to be created in which the corresponding test succeeds and that creates the effects you noticed.