Manipulating var from father in child process - c

Can someone pls explain why the output of the following program is 1 and not 2?
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main(int argc, char *argv[])
{
int x = 1;
int *y = &x;
pid_t pid = fork();
if (pid == 0) {
*y = 2;
exit(0);
} else {
wait(NULL);
printf("father: %d\n", x);
}
return 1;
}

fork doesn't create a thread, it creates a whole new process.
The address space of the child is a copy of the parent's one, they don't share it.
Modifications done by the parent are not visible from the child, and vice-versa, unless the specifically set something up to do so (via shared memory segments for instance).

Related

C communicate parent and child to increase and print counter

I am trying to write a program so that the parent and child process can communicate back and forth between each other. The parent process and the child process ought to print the values from 1-100 where each process prints the value incrementing it by 1 each time. Now the issue I face is that, I know nothing much about pipes. What I gather from reading materials online is that I can use a pipe to read and write values. I have leveraged this to print something in the child process, and send back something to the parent. Now, I am not sure how to get the parent to return to the child after printing for itself? I know my code is probably all wrong, but I am really not sure what I should do.
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc, const char * argv[]) {
int fd[2];
if (pipe(fd)== -1){
printf("An error occured while opening the pipe\n");
}
int id = fork();
int i = 0;
if (id == 0){
close(fd[0]);
printf("In child: %d", i);
i ++;
write(fd[1], &i, sizeof(int));
close(fd[1]);
} else {
wait(NULL);
close(fd[1]);
int y;
read(fd[0],&y, sizeof(int));
close(fd[0]);
}
}
To keep it simple, it's up to you to check return values and handle errors. This will only do it between 0 - 9 and you will have to expand the mathematics.
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{
int pipefd_1[2];
int pipefd_2[2];
pid_t cpid;
pipe(pipefd_1);
pipe(pipefd_2);
cpid = fork();
if (cpid == 0) { /* Child reads from pipe 1, writes to pipe 2*/
char cval[] = {'0'};
close(pipefd_1[1]); /* Close unused write and read ends */
close(pipefd_2[0]);
while (atoi(cval) != 9) {
read(pipefd_1[0], cval, 1);
printf("Child print %d\n", atoi(cval));
cval[0] += 1;
write(pipefd_2[1], cval, 1);
}
} else {
char cval[] = {'0'}; /* Parent writes buf to pipe 1 */
close(pipefd_1[0]); /* Close unused read end */
close(pipefd_2[1]);
while (atoi(cval) != 9) {
write(pipefd_1[1], cval, 1);
read(pipefd_2[0], cval, 1);
printf("Parent print %d\n", atoi(cval));
cval[0] += 1;
}
}
}
Output

Fork and exec several children in linux

I want to fork and exec several processes from another.
My parent code is
/*Daddy.c*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main(void)
{
int status;
char *nChild;
for (int i=0; i<3;i++){
int pid = fork();
if (pid == 0)
{
sprintf(nChild, "%d", i);
printf("%d\n", i);
char *const arguments[]={nChild, NULL};
fflush(NULL);
execv("child",arguments);
printf("\nNo , you can't print!\n");
}else if (pid == -1){
printf("%d\n", getpid());
exit(0);
}
}
wait(&status);
printf("Dad %d went out!\n", getpid());
exit(0);
}
and my child process is
/*child.c*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int args, char **argv){
if( args !=2){
printf("Child going away!\n");
exit(1);
}
printf("Child %s: %d going away stylishly!\n", argv[1], getpid());
exit(0);
}
When I don´t create three forks, but one, I know how to create the child, do some work and exit from child and parent. But, in this case, with several children it seems like the child never executes.
Because of the line wait(&status) I did hope that when the first child exits, the parent also exits but, any child prints any message.
Some relevant previous questions didn´t help.
You need to make parent wait for all child processes to finish. If not, assume that 1 child waited for is done and then parent exits. What about the other 2 children? They become orphan since their parent doesn't wait for them.
pid_t wpid;
int status = 0;
.
.
while ((wpid = wait(&status)) > 0); // the parent waits for all the child processes
This code did the job
/* daddy.c */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
int main(void)
{
int status=0;
char nChild[16];
pid_t wpid;
for (int i=0; i<3;i++){
sprintf(nChild, "%d", i);
int pid = fork();
if (pid == 0)
{
printf("%s\n", nChild);
char *const arguments[]={"child", nChild, NULL};
fflush(NULL);
execv("child",arguments);
printf("\nNo , you can't print!\n");
}else if (pid == -1){
printf("%d\n", getpid());
exit(0);
}
}
while ((wpid=wait(&status)) >0);
printf("Dad %d went out!\n", getpid());
exit(0);
}
As #OnzOg said in the comments of the question, allocation of nChild was the main problem. Also execv need pass child name twice, one as argument.
And finally, to improve the code, parent process needs to wait all processes to finish.

How many child processes are created in the following code

#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
int value = 5;
int main()
{
pid t pid;
pid = fork();
if (pid == 0) {
value += 15;
return 0;}
else if (pid > 0) { /* parent process */
wait(NULL);
printf("PARENT: value = %d",value); /* LINE A */
return 0;}}
How many child processes are created and what value is printed in Line A?
Did you try it?
Just single child is created and the parent prints value 5 as it's not modified in the parent process. The global variables have a copy in each of the processes, they are not shared.

Logging results of fork() in C to file to see results

I'm trying to get the results of each run of the program (both the parent and child). The results print once on the screen and only once in a file. I can't seem to get two unique files created (one representing parent and one representing child). I'm not sure if getpid() is the effective way to separate parent and child identification. What could I be doing wrong?
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static char *app1="/path/to/app1";
static char *app;
static pid_t forky=-1;
void otherfunction(){
int aflag=1;
//do something
if (aflag==1){
//run app 1
app=app1;
printf("Starting fork\n");
forky=fork();
}
}
int main(){
char dat[40000],test[10000];
sprintf(dat,"Exec start\nFORKY = %d\nPID = %d\nPPID = %d\n",forky,getpid(),getppid());
sprintf(test,"/TEST%d",getpid());
int h=open(test,O_WRONLY|O_CREAT);
write(1,dat,strlen(dat));
write(h,dat,strlen(dat));
close(h);
otherfunction();
return 0;
}
You're creating the file before you call fork. The fork is the last thing you do and then both processes just return 0.
As specified in fork's man page, the process created by calling fork is a copy of the parent process except for some specific differences, and this child process starts execution as if resuming from after the call to fork. So, it's kind of like you get two returns from fork, one for the parent and one for the child. So, it looks like you ask two questions here:
How to differentiate parent and child
Again, the man page mentions that fork will return the child's pid in the parent process and 0 for the child process so the following code sample will get you distinguished output from both:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char **argv)
{
pid_t pid = fork();
if (pid == 0)
printf("Hello from child!!!\n");
else if(pid > 0)
printf("Hello from parent!!!\n");
else
printf("Wow, fork failed!!!");
return 0;
}
Obtaining separate files for each process
As mentioned above, both processes resume from after the call to fork, so the files must be created after calling to fork. In your example you are calling otherfunction last in main, so fork is pretty much the last call in both processes.
The following is an example that will give you different files with different content for each process, as well as print in stdout for each process. The usage of getpid here is just so you can actually check what the man page says.
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char **argv)
{
pid_t pid = fork();
int h;
char *test;
char dat[100];
if (pid == 0)
test = "child";
else if(pid > 0)
test = "parent";
else
test = "failed";
h = open(test,O_WRONLY|O_CREAT);
sprintf(dat, "%s | fork returned = %d | my_pid = %d\n", test, pid, getpid());
write(1,dat,strlen(dat));
write(h,dat,strlen(dat));
close(h);
}

Grabbing the return value from execv()

//code for foo (run executable as ./a.out)
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/wait.h>
int main (int argc, char **argv) {
pid_t pid;
pid = fork();
int i = 1;
char *parms[] = {"test2", "5", NULL}; //test executable named test2
if(pid < 0) {
fprintf(stderr, "Fork failed");
return 1;
}
else if(pid == 0) {
printf("Child pid is %d\n", pid);
i = execv("test2", parms); //exec call to test with a param of 5
}
else {
wait(NULL);
}
printf("I is now %d\n", i); //i is still 1 here, why?
return 0;
}
Hey everybody, I am trying to learn a little bit about fork and execv() calls. I make my foo.c program above make a call to a file I have named test.c. I fork a child and have the child make a call to execv, which will just add 10 to the parameter read in. I am unsure of why the variable does not change, at the bottom of my foo.c function. Does the call need to be a pointer or return an address? Any help would be greatly appreciated. Thanks
Code for test.c (executable named test2)
#include <stdio.h>
int main(int argc, char ** argv[]) {
int i = atoi(argv[1]);
i = i +10;
printf("I in test is %d\n", i);
return i;
}
You only call execv() in the child process. The exec() family functions never return if it runs successfully. See evec(3):
The exec() functions only return if an error has occurred. The return value is -1, and errno is set to indicate the error.
You printed the value of i in the parent process, it never changed in the parent process.
To get the exit status from the child process, you can make use of wait() or waitpid():
else {
int waitstatus;
wait(&waitstatus);
i = WEXITSTATUS(waitstatus);
}

Resources