C:How Process communicate in linux - c

I want to count the number of processes that are created with a for 1,10 and where fork() si executed. The program is executed in linux. I really don't get how to use wait or WEXITSTATUS and I've spent hours on forums and still don't get it. Can someone help me, please?
Thanks,
Dragos
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
int nr = 1;
int main()
{
int pid;
int i;
int stare;
for(i = 1; i<=10 ; i++)
{
pid = fork();
if( pid !=0 )
{
//parent
wait(&stare);
nr = nr + stare;
}
else
{
//child
nr++;
stare = WEXITSTATUS(nr);
exit(nr);
}
}
printf("\nNr: %d\n", nr);
}

The macros like WEXITSTATUS are used in the parent process to get the exit status after a wait call.
In the child process, it's enough to just return nr (or call exit with it as argument).
In the parent you use WEXITSTATUS like this:
if (wait(&stare) > 0)
{
if (WIFEXITED(stare))
nr += WEXITSTATUS(stare);
}
We must use the WIFEXITED check because otherwise the exit status is not valid.

Related

get Exit code from child process

I have passed an argument in exit code of a child process, So in the parent process I am trying the call another function that passes the exit status code passed by the child process by using wait, However I am only getting -1 as the exit status code on using the wait call, is there any way to get the parameter passes in the exit code on calling the wait method.
#include <stdio.h>
#include<stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include<sys/wait.h>
pid_t ppid;
void child();
void parent();
int get_child_exit_status()
{
int status=wait(&ppid);
return status; //returns -1 instead of 101
}
int main(void)
{
ppid = getpid();
fork();
child();
wait(&ppid);
printf("Child exited with status=%d",get_child_exit_status());
return 0;
}
void child()
{
pid_t c_pid = getpid();
if(c_pid == ppid)
{
return;
}
printf("This is a child\n");
int status;
scanf("%d",&status); //input 101
exit(status);
}
Your code is confusing. Try to make it simple:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main()
{
int status;
int code;
switch (fork()) {
case 0: // child code
scanf("%d", &code);
return code;
default: // parent code
wait(&status);
printf("child exited with status %d\n", WEXITSTATUS(status));
return 0;
}
}
I used switch here so you can easily add a case for -1 to deal with any errors when forking.

Understanding the code in C involving processes

Someone can explain me why the first code the variable "v" dont change the value in the last prinft() and se second code the variable "v" change.
First code:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
int v = 5;
int main(){
pid_t piid;
piid = fork();
if(piid==0){
v += 15;
return 0;
}
else if(piid >0){
wait(NULL);
printf("Final value = %d\n",v);
return 0;
}
}
I know this code be involving fork() for create another process maybe
Second code:
#define _GNU_SOURCE
#include <stdlib.h>
#include <malloc.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <sched.h>
#include <stdio.h>
// 64kB stack
#define FIBER_STACK 1024*64
int v = 5;
int threadFunction( void* argument )
{
v += 10;
return 0;
}
int main(){
void* stack;
pid_t pid;
stack = malloc( FIBER_STACK );
if ( stack == 0 )
{
perror("malloc: could not allocate stack\n");
exit(1);
}
pid = clone( &threadFunction, (char*) stack + FIBER_STACK,
SIGCHLD | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_VM, 0 );
if ( pid == -1 )
{
perror( "clone" );
exit(2);
}
pid = waitpid( pid, 0, 0 );
if ( pid == -1 )
{
perror( "waitpid" );
exit(3);
}
free( stack );
printf("Final value = %d\n", v);
return 0;
}
This code is a thread, but I can not understand the so-called clone () and what's inside there.
Forking a new process creates a standalone and distinct copy of the original process. Changing something in the process copy will not change anything in the original process.
Threads are different, they share everything. All threads are still parts of the same process.
While the clone system call can create a new process (that's what happens when you call fork in Linux actually) it can also be used to create a thread, which is what happens in the second program.
threads run in a shared memory space, while processes run in separate memory spaces.
so in the first case using fork each process has different reference of the variable v while in the thread both has the same reference.

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

Can this C code create zombie processes?

I am wondering if the following code can create zombies:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(){
int i=1;
pid_t p;
p = fork();
i++;
if(p!=0){
waitpid(p, NULL, 0);
}
printf("%d\n",i);
return 0;
}
So, the parent process calls the waitpid for the child process, which returns immediately if the child has not already exited. So, no zombies can arise so far. But, if the child exits before return 0; command this would be a zombie then? I am actually confused about it. Should the waitpid be the last line of code before the program terminates? Any help would be appreciated. Thanks!
The child only becomes a zombie if it ends and the parent doesn't call wait*() as long as itself lives on.
In the moment the parent also ends the child is reaped by the init process which will take care to call wait*() on the child, so it will finally end and with this leave the zombie state and disappears from the process list.
To provoke the child created in your example code to become a zombie modify the code for example as follows:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(void)
{
pid_t p = fork();
if (p != 0)
{
waitpid(p, NULL, 0); /* See if the child already had ended. */
sleep(1); /* Wait 1 seconds for the child to end. And eat away the SIGCHLD in case if arrived. */
pause(); /* Suspend main task. */
}
else
{
sleep(3); /* Just let the child live for some tme before becoming a zombie. */
}
return 0;
}
Due to the two following facts:
the child sleeps for 3s so the parent's call to waitpid() most probably will always fail
the default handling of SIGCHLD is to ignrore it.
the code above in fact is the same as:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(void)
{
pid_t p = fork();
if (p != 0)
{
pause(); /* Suspend main task. */
}
else
{
sleep(3); /* Just let the child live for some tme before becoming a zombie. */
}
return 0;
}
I found a simple way to create a zombie process and test it using ps -e
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
void main()
{
pid_t pid;
pid = fork();
//parent sleeps while the child has exited
//not an orphan since parent still alive
//child will be still present in process table
if(pid==0)
{//child
exit(0);
}
else
{//parent
sleep(15);
}
}
run ps -e while within the 15 seconds...
you will see
6454 pts/2 00:00:00 a.out < defunct >

Forking two processes results in multiple processes

I wish to design a function called from main that will fork off any process to sleep and then update the "process array" containing all forked pids and a counter of them. It seems to work, only there's other processes being forked as well (here with pid -1 and 11957) that I'm not sure where comes from. The test run gives:
Parent 11954 forks off children..
Children started: 2
Proc 11955 started
Proc 11956 started
Children started: 1
Child -1 terminated with status 0
Children started: 1
Proc 11957 started
Children started: 0
Child 11957 terminated with status 0
Child 11955 terminated with status 0
Child 11956 terminated with status 0
The code:
#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#define MAXPROC 100
void fork_off(int * proc_t, int * proc_i) {
int f = fork();
if (f == 0) {
fprintf(stderr, "Proc %d started\n", getpid());
usleep(5000000);
} else {
proc_t[*proc_i] = f;
(*proc_i)++;
}
}
int main(void) {
int proc_table[MAXPROC], proc_index, status, i;
proc_index = status = i = 0;
printf("Parent %d forks off children..\n", getpid());
fork_off(proc_table, &proc_index);
fork_off(proc_table, &proc_index);
printf("Children started: %d\n", proc_index);
for (i = 0; i < proc_index; i++) {
printf("Child %d terminated with status %d\n",
waitpid(proc_table[i], &status, 0), status);
}
return 0;
}
I wish only to fork off two processes, not more. What's causing this behaviour?
The problem with your code is that after the child processes have slept, they return from fork_off and repeat everything the parent is doing.
void fork_off(int * proc_t, int * proc_i) {
int f = fork();
if (f == 0) {
fprintf(stderr, "Proc %d started\n", getpid());
usleep(5000000);
exit (0); /* exit() closes the entire child process
* instead of simply return from the function
*/
} else if (f > 0) { /* Make sure there isn't an error being returned.
* Even though I've never seen it happen with fork(2),
* it's a good habit to get into
*/
proc_t[*proc_i] = f;
(*proc_i)++;
} else { /* Adding to the aforementioned point, consider changing
* the return type to int - so that you can return -1
* and check for error.
*/
}
}

Resources