So this is simple program of creating two process: parent and child. So what I did is have the greeting inside the parent and the name inside the child process. For some reason my child process is not printing despite that I called wait() inside the parent. What should I do?
GOAL OUTPUT: "Hello Sam"
OUTPUT I"M GETTING: "Hello"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
char *greeting = "Hello";
char *name;
pid_t pid;
pid = fork();
if(pid == 0)
{
name = "Sam";
exit(0);
}
else if(pid == -1)
printf("Fail\n");
else{
wait(0);
printf("%s %s", greeting, name);
}
}
When you make a call to fork(), the child process will receive a copy of the parent process' address space (variables etc...). This means that in the child, "name" is defined, from the parent. However, "name" in the child process is just a copy. So modifying it in the child process does not affect the parent.
To get the behavior that I sense you're after, replace fork() with vfork(). For the purposes of this discussion, the only difference is that:
The address space is shared instead of copied. Editing "name" in the child process will be reflected in the parent process
The parent process is suspended while the child process executes. I assume that this is OK, because you are already calling wait() in the parent process
Edit:
I forgot to add that if you go the vfork route, change exit() to _exit() in the child process
Child process once forked will run independantly of the parent process. So when you set name="Sam" in child it is in different program, than the printf. So you are not able to see the message.
In the child process, you assigned to name and then exit.
if(pid == 0)
{
name = "Sam";
exit(0);
}
The printf("%s %s", greeting, name); line is executed only in the else branch, i.e, the parent process. It's actually undefined behavior because name is uninitliazed.
Related
The task is as follows
Write a program that would run another process in memory and leave it running in an infinite loop. When the program is restarted, it must remove the previously started process from memory (you can use kill).
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <spawn.h>
#include <sys/wait.h>
int main(void){
int pid = getpid(); // we find out the PID of the current process and store it in a variable
FILE *file = fopen("example.txt", "r"); // getting information from a file about a child process
int filePid = 0;
fscanf(file, "%d", filePid);
fclose(file);
switch (filePid){
case -1:{ // if there is no child process, then run it and write the PID to a file
filePid = fork();
file = fopen("example.txt", "w");
fprintf(file, "%d", filePid);
fclose(file);
break;
}
case 0:{ // if this process is a child, then we go into an infinite loop
for(;;){
sleep(7); // waiting for seven seconds so that the system is not heavily loaded
}
break;
}
default:{ // if this program is started again with a child process, then we send a signal to the child process
kill(filePid, SIGKILL); // we send a signal to the child process so that it ends, and after that we write the information to the file
file = fopen("example.txt", "w"); // we write information to the file that the child process is missing
fprintf(file, "%d", -1);
fclose(file);
}
}
return EXIT_SUCCESS;
}
/Yes, I have to do it through the qnx operating system./
the errors are as follows..I'm a little confused with getpid, because I haven't used the pid variable anywhere.
and another mistake.
I will be grateful for your help.since I'm a little confused...
UPD:
I can't get the value 0
UPD: how could it execute both cases, i mean "if" and "else" blocks at the same time?
how could it execute both cases, i mean "if" and "else" blocks at the same time?
You have to have a clear understanding of how fork works, when you use fork two identical processes are created parent and child and they run simultaneously, when you say filePid = fork() and if the operation is successful then the parent process will hold the process id of the child process and child process will hold 0. So here in parent process filePid == child process ID and in child process filePid == 0.
See man fork
On success, the PID of the child process is returned in the parent,
and 0 is returned in the child. On failure, -1 is returned in the
parent, no child process is created, and errno is set appropriately.
So whatever you put in the if (filePid == 0) block will be executed by the child process and whatever you put in the else block will be executed by the parent process simultaneously.
This will be helpful if you want to know more about fork.
fork() system call creates a child process and return its pid so once child is created you have two process running same instruction after fork() one is checking pid is greater which means its parent which gets child pid and in child context OS will set the pid value to 0 so it will enter condition block intended for child
[SOLVED]
So for this practice exercise I was assigned we are practicing process control. I'm simply wondering why it seems that my child process will never execute (when child_pid == 0). Any help on this issue would be greatly appreciated!
Also, safe_fork() is a function our instructor wrote in order to avoid students opening too many processes.
#include "safe-fork.h"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
int main(void) {
pid_t child_pid;
int pipefd[2];
int pipe_result;
int count;
pipe_result = pipe(pipefd);
if (pipe_result == -1) {
perror("pipe failure");
exit(1);
}
child_pid = safe_fork();
/*Parent Process*/
if (child_pid > 0) {
dup2(pipefd[0], STDIN_FILENO);
scanf("%d", &count);
if (count > 200) {
printf("Long enough!\n");
exit(0);
}
else {
printf("Too short!\n");
exit(1);
}
}
/* Child Process */
else {
dup2(pipefd[1], STDOUT_FILENO);
execl("/usr/bin/wc", "-w");
}
return 0;
}
Here is a suggestion, check for child_pid == 0 explicitly cause it could also be the case that your safe_fork() function failed, also check for those errors i.e child_pid < 0.
Add debug printf statements to check control flow if you already haven't and finally check if the execl call failed.
Also please have a look at this tutorial for creating pipes in C and using them to communicate between a parent and a child process. As I feel there are some issues with how you are handling those file descriptors. A possible reason that you can't see any output is that wc might still waiting for some input.
And another thing you might need to wait for the child process to complete/do something useful or actually be run before checking for its output. Check the other issues first before you worry about this.
Hope this Helps :)
Yes, But no. First you should carefully understand the meaning of fork().
fork(): creates a child process and it returns into TWO PROCESSES, with different return value in each. In parent, it always returns the number that OS has assigned for the newly created child's process id. At the same it returns in newly created child also, as child process will start executing the code copied from parent just after the fork() statement. In child fork always returns zero. So normally after a fork() system call, people check for returned value by fork to differentiate child process and parent process.
particularly in this case after a fork(), there will be two processes with same code and same program states(except both will have different value assigned in child_pid variable). In parent its a non zero value (which is corresponding to child's pid) and in child, its the value zero as the fork returns zero in child.
Now both processes will execute
if (child_pid > 0)
which is true only for parent so parent process will flow into 'if block' and is false for child so it will directly jump to else part and will execute the else block.
What if child_process id is zero?
OS will always assign a non zero value for a child so that fork() will work. And if you have somehow got child process id as zero then parent will fail to enter in 'if block' and will execute else block which is the same as child.
It seems that if I create a process, fork it and send a SIGHUP from the parent to the child, the child dies but it's "/proc/PID" dir doesn't dissappear until the parent also dies.
(See code below).
What is the right way to let the parent check if the child is dead ?
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <errno.h>
#include <signal.h>
void testprocdir(pid_t pid) {
struct stat sb;
char path[1024];
sprintf(path,"/proc/%d",pid);
if(stat(path, &sb)==-1 && errno == ENOENT) {
printf("%s does not exist\n", path);
} else {
printf("%s exists\n", path);
}
}
int main(int argc,char **argv) {
pid_t parent,child;
parent=getpid();
printf("I am %d\n",parent);
child=fork();
switch(child) {
case -1:
printf("Forking failed\n");
return 2;
case 0:
parent=getppid();
child=getpid();
printf("I am the child (%d) and my parent is %d\n", child, parent);
while(1) { sleep(1); printf("I am the child and I have slept 1s\n");}
printf("This line should not be visible\n");
}
sleep(1); //make sure kid is in the while loop
printf("I am the parent (%d) and my kid is %d\n", parent, child);
kill(child,SIGHUP);
testprocdir(parent);
printf("Waiting 5s before testing if the procdir of the child (/proc/%d) is removed\n",child);
sleep(5);
testprocdir(child);
return 0;
}
You could use the wait family of system-calls.
fork returns the PID of the child process in the parent process, and 0 in the child process.
man waitpid should provide more than enough direction beyond that to call waitpid in the parent, allowing you to check that child process or all child processes ― including the ability to allow the parent to continue executing if the child is still alive or stop all execution in the parent until the child is dead.
I will start with some concepts:
The OS will keep a child process' entry in the process table (including exit status) around until the parent calls waitpid (or another wait-family function) or until the parent exits (at which point the status is collected by the init process). This is what a "zombie" process is: a process that has exited by is still resident in the process table for exactly this purpose. The process' entry in the table should go away after the first call to waitpid.
Also, from the man page :
A child that terminates, but has not been waited for becomes a "zombie". The kernel maintains a minimal set of information about the zombie process (PID, termination status, resource usage information) in order to allow the parent to later perform a wait to obtain information about the child.
So, by using the wait family of functions you can examine the status of child process.
There are some macros also that can be used with with wait family of functions to examine the status of child process like WEXITSTATUS, WIFSIGNALED, WIFEXITED etc .
I'm new to c language and Linux. I have a problem related to fork(),getpid()and exec()function.
I wrote a c program using fork() call the code of my program is following"
code:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
void fun()
{
printf("\n this is trial for child process");
}
int main (int argc, char const *argv[])
{
int i,status,pid,t;
if(pid=fork()<0)
{
printf("\nfailed to create the process\n");
}
if(pid=fork()==0)
{
printf("\n the child process is created");
fun();
exit(1);
}
while(wait(&status)!=pid);
return 0;
}
The out put of this program is following:
the child process is created
this is trial for child process
the child process is created
this is trial for child process
Now my questions are as follows:
Why the output of program showing same thing twice? The output supposed to be "child process is created this is trial for child process"
Why the output is not according to code ?
Can we have a program which has 4 processes and all the processes perform different task for example one process print "my name". One process print "my age", the other process print "my address ?
How to make multiple process in main function ?
How to control the execution of multiple process ?
what does the exec() function do? Can anyone please explain me the working of exec(), fork(), getpid() with a source code?
Please help this novice fellow.
Your code calls fork() multiple times:
if(pid=fork()<0) /* calls fork() */
{
...
}
if(pid=fork()==0) /* also calls fork() */
{
...
}
Each successful fork() creates a new child process. To make matters worse, the second fork() is called by both the parent and the first child.
If you're trying to create a single child process, you should call fork() just once:
pid_t pid; /* note the correct return type of fork() */
...
pid = fork();
if (pid < 0)
{
...
}
else if (pid == 0)
{
...
}
If you want to create multiple child processes, you can have the parent process call fork() in a loop.
As to questions like "what does exec do?", my advice is to learn how to use man and then come back with specific questions if there's something in the manpages that remains unclear.
In this code you are creating Three process not including your main process.
pid=fork()
is itself a statement , which forks a new process even though it is inside an if statement condition. After the first fork() call the remaining codes will be executed twice. so next fork call will be called twice. You have already created a new process.
fork returns zero to itself and its
process id to its parent
That is consider a process A forks B (not from your code)
pid = fork();
printf("pid is : %d",pid);
printf statement executes twice(one for A and one for B). For A it prints(A is parent)
pid is : 512 //some integer value
process id
and B prints
pid is : 0
So in your question
if(pid=fork()==0)
{
printf("\n the child process is created");
fun();
exit(1);
}
this is the second fork which is already executing twice. So each of this execution creates a new child process. For both childs pid value is 0. So your print statement executes, which is what you see in the output. But for both parents a pid value will be there and your if condition fails, so it wont print. These two childs are your second and third processes..So in short you create 3 processes along with the main process
The output is generated twice because you are forking twice:
if(pid=fork()<0) // Fork #1
{
printf("\nfailed to create the process\n");
}
if(pid=fork()==0) // Fork #2
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