I think i am very close, but some detail is missing here.
The task:
Write a program in C that creates a father and child process. Father and child are both counting from 1 to 1000 "using" a loop.
The father process only counts the even numbers, while the child process only counts the odd numbers.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
void main (){
int id = fork();
int i;
if (id == 0){
for (i=1;i<=1000;i=i+2){
printf("%d\n",i);
}
}
if (id > 0){
for (i=0;i<=1000;i=i+2){
printf("%d\n",i);
wait(0);
}
}
}
The problem i have here is, that all the numbers a completely mixed up.
It seems that my wait system call is not working correctly :(
I appreciate any help. Thanks in advance :)
Your wait system call should placed out of for loop, because there's only one child process to wait.
like that
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
void main (){
int id = fork();
int i;
if (id == 0){
for (i=1;i<=1000;i=i+2){
printf("%d\n",i);
}
}
if (id > 0){
for (i=0;i<=1000;i=i+2){
printf("%d\n",i);
}
wait(0);
}
}
Related
I'm writing a program that open a .txt file by vim and whenever i press CTRL+C the process will be killed. But the thing is i can't find the process's pid that i've just created and kill it. Can anybody help me?
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
void ctrl_C(int sig){
system("kill -9 $(pidof id)");
printf("\n You pressed Ctrl + C,Good Bye \n");
exit(0);
}
int main(){
printf("I am Programmer \n");
pid_t id = system("gnome-terminal -- vi abcd.txt");
signal(SIGINT,ctrl_C);
while(1){}
}
There are multiple issues with your code:
system(3) does NOT return PID of child process, but instead waits for it to exit, and returns its exit code. You need to use the traditional fork+exec approach.
With child PID available, it's easier to call kill(2) than kill(1)
Better add sleep in a dead loop waiting for input. This reduces CPU load and your electricity bill.
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
pid_t child_id;
void ctrl_C(int sig){
kill(child_id, 9);
printf("\n You pressed Ctrl + C,Good Bye \n");
exit(0);
}
int main(){
printf("I am Programmer \n");
pid_t child_id = fork();
if (child_id == 0) {
execlp("gnome-terminal", "gnome-terminal", "--", "vi", "abcd.txt", NULL);
return 255;
}
signal(SIGINT,ctrl_C);
while (1) {
sleep(1);
}
}
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);
}
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 >
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.
I've written a program which forks in a loop. The only thing children processes do is to increase a counter and exit, whereas a parent process waits for each of them.
My goal is to measure user and system time of parent process and all his children separately.
I've succeded with parent process using times() function and struct tms. Surprisingly, the same aproach to children processes isn't working. What is the mistake that I'm doing? How to measure those times?
I've also tried getrusage() and I/it failed.
My code:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/times.h>
#include <time.h>
#ifndef COUNT
#define COUNT 100000
#endif
int counter;
int main(){
struct tms time1,time2;
times(&time1);
int count = COUNT;
pid_t pid;
while(count--){
if((pid=fork())<0){
printf("fork error\n");
} else if(pid==0){ /* child */
counter++;
_exit(0);
} else {
waitpid(pid,NULL,0); /*wait()*/
}
}
printf("COUNTER: %d\n",counter);
times(&time2);
long double clktck=sysconf(_SC_CLK_TCK);
double user=(time2.tms_utime-time1.tms_utime)/(double)clktck;
double system=(time2.tms_stime-time1.tms_stime)/(double)clktck;
double cuser=(time2.tms_cutime-time1.tms_cutime)/(double)clktck;
double csystem=(time2.tms_cstime-time1.tms_cstime)/(double)clktck;
printf("USER:%lf\nSYSTEM:%lf\n",user,system);
printf("CUSER:%lf\nCSYSTEM:%lf\n",cuser,csystem);
return 0;
}
I think the problem is that your children are executing too quickly; they don't take enough time to execute, so the sum of their time is plenty of zeros. To test this theory, I slightly changed your program:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/times.h>
#include <time.h>
#ifndef COUNT
#define COUNT 100
#endif
int counter;
int main(){
struct tms time1,time2;
times(&time1);
int count = COUNT;
pid_t pid;
while(count--){
if((pid=fork())<0){
printf("fork error\n");
} else if(pid==0){ /* child */
int i;
for (i=0; i<10000; i++) {
printf("in child %i\n", getpid());
}
exit(0);
} else {
waitpid(pid,NULL,0); /*wait()*/
}
}
printf("COUNTER: %d\n",counter);
times(&time2);
printf("%lu %lu %lu %lu\n", time2.tms_utime, time2.tms_stime, time2.tms_cutime, time2.tms_cstime);
long double clktck=sysconf(_SC_CLK_TCK);
double user=(time2.tms_utime-time1.tms_utime)/(double)clktck;
double system=(time2.tms_stime-time1.tms_stime)/(double)clktck;
double cuser=(time2.tms_cutime-time1.tms_cutime)/(double)clktck;
double csystem=(time2.tms_cstime-time1.tms_cstime)/(double)clktck;
printf("USER:%lf\nSYSTEM:%lf\n",user,system);
printf("CUSER:%lf\nCSYSTEM:%lf\n",cuser,csystem);
return 0;
}
You'll see that I drastically cut down on the number of children, and made the children do some real work; 10_000 printf(... getpid()) operations. Now the times amount to something:
$ time ./times
...
in child 16181
COUNTER: 0
1 0 24 95
USER:0.010000
SYSTEM:0.000000
CUSER:0.240000
CSYSTEM:0.950000
real 0m2.234s
user 0m0.250s
sys 0m0.950s
I'm afraid your children just didn't have enough work to do to amount to anything. (Odd, sounds like parenting advice.)
Each child is given their own address space. The code will not work because it will increment it's own local copy of counter and quit, leaving the version in the parent process/all other children untouched.
Also, you are very likely to get some errors with that many children.
Sorry I could only help with half the program :(.