void main()
{
fork();
fork();
printf("main");
}

pls explain me what is the output.
how it comes.

Recommended Answers

All 7 Replies

What does fork() do? :?:

where is the rest of the code ????

With more familiarity to Unix based systems I realised an important fundamental of fork()ing. The way Unix creates a new process. And a simple "man fork" helped alot. After getting a little familiar with fork() I applied it to my problem of mail bombing. On reading more thoroughly I also understood how to "put a program in background". The nature of my problem was simple, I would target a free *nix webhost and run the program in the background, though I didn't have ssh or telnet access to the remote machine, a simple perl/php program could exec() the process, and the rest is...

But to my surprise fork() was doing some weird things, and a "ps" showed some process like :

<defunt>

Ack, what's that ? A search on google revealed what it meant, and just how one could pull this off. How ? Poor coding, I say, or ignorance towards the details of fork(). So then i started off a new mission, to remove these zombies from my program.

You're having deity time with putting your program on another machine of which you are not really concerned, so why bother ?

Well it's just that instinctive feeling being a budding programmer that I felt of correcting my code.
fork()ing english style :

#include <unistd.h>
	#include <signal.h>
	#include <........>

	int main(void)
	{
	  int pid; /* alias: pid_t pid; */
	  pid = fork(); /* the familiar kitchenware! */
	  if (pid == -1) {
	    perror("fork");
	    exit(1);
	  } /* fork() returns -1 on error, and much knownigly sets the global errno variable */

	  if (pid != 0) {
	    printf("Hello World, my name is Pappy!\n");
	    printf("My process id is %d\n", getpid());
	    printf("I have a baby (unisex) his name is Googoo, and has a process id %d", pid);
	  } /* if the value returned is non zero and not -1, then this is the parent process */

	  printf("We love Unix!"); /* this is a common task for both processes */

	  if (pid == 0) {
	    printf("Hello World, my name is GoogooGaga!\n");
	    printf("My process id is %d\n", getpid());
	    printf("I have ONE papa (ofcourse), his name is Pappy, and has a process id %d, 
	    getppid());
	  } /* if the returned value is 0 then you're the child process */
	  exit(0);
	}

fork() returns twice, once in the parent process and the second in the child process, and code execution starts where the fork() left off, therefore an if condition is used to identify the process. Any piece of code after the fork() that is not delegated to the if condition which distinguishes the process will be executed in both the processes. Hence "We love Unix!" gets printed twice. Let me bring this to your notice that the process group ID, terminal group ID, file mode creation mask, current working directory are inherited from the parent process, amongst a few others. Oh yes, and signal handling, which will be an important aspect of creating a daemon process later on.

Yes, family re-union's are very touching, all we need is some party poopers, eh ? Zombies are coming this way!


I'll be right here wait()ing for you

Did you ever wonder what happens to a process when it "dies", it dies but a small tiny biny part is still left, which is what the exit call signifies, though exit() never returns to the calling process, so to whom does the return value goto, the answer is simple, the parent process!

So like what does the parent do to recieve this value ?
Again it's quite simple, it wait()s!

It's prototyped by int wait(int *status). Before you pop the question, wait() simply waits for a child process to terminate, either by a signal or exit(), if there are multiple children then the first child that terminates is returned to the parent process. If there are no children then it returns immediately with a value of -1. If the value passed to wait is not NULL, then the status variable stores the return value of exit() from the child process. For more information : "man wait" and also check out "man waitpid" -)


So technically when a process "dies" completely when the parent has waited on it, this is also known as reaping the zombie!!


Zombies - Hale Caesar!

Zombie attack, and your sysadmin becomes conan the barbarian! Yes its pretty annoying, when you have 200 or listings on performing a ps! And as I've mentioned before it's just bad code ;-)
Let's consider some possbilities how a zombie is really formed :

I fork()ed, parent process is running, and after sometime the child process dies. Now what am i suppose to do ? You're suppose to wait(). So here's some sample code :

#include <unistd.h>
	#include <signal.h>
	#include <........>

	int main(void)
	{
	  int pid;
	  pid = fork();
	  if (pid == -1) {
	    perror("fork");
	    exit(1);
	  }

	  if (pid != 0) {
	    printf("Hello World, my name is Pappy!\n");
	    printf("My process id is %d\n", getpid());
	    printf("I have a baby (unisex) his name is Googoo, and has a process id %d", pid);
	    while (1) {}
	    wait(NULL);
	  }
	  if (pid == 0) {
	    /* do something */
	  }
	  exit(0);
	}

Now that's bad! At some point of time when the child dies, and the parent doesn't and as you can see the parent won't wait(), so from that point of time, we have a zombie with us, till the time ofcourse the parent calls wait(). In the above there's no possible way. Hint: The while loop

Hence in this case a zombie is definate, no matter what, so I can safely say that if the child dies, and so does the parent [or it's in a state where it cannot call wait()] a process becomes zombie.

However if we kill the parent process, the zombie processes disappear, cause they get reparented to init, and it reaps them. Well it reaps them in a style, it can either show them in a ps, and periodically kill them, or it can kill it immediately (depending on systems).

But what happens if the parent dies before the child ? It gets reparented to init(). And the child is unaware of the change of parents.


So here's MY 2 cent conlusion

Don't let a child die before the parent (in context to a daemon), if this ever happens, killing the parent is something that can be tried, this simply reparents to init, which can reap it when it wants or kill it instantaneously. Though this is how everything really works, the child dies, and then the parent collets it's exit status, we wouldn't wanna wait() on a child that is daemon.

Because the scope of the article is daemon processes, killing the parent is a very nice thing, not very nasty either, init takes control of the children when they die, as they're reparented to init. If you want to make less fuss about all this, adding this :


signal (SIGCHLD, SIG_IGN);

would be however not completely portable, but a better solution anyhow.

(Ignoring SICHLD a.k.a SIGCLD is *NOT* POSIX!)

But you just said that it gets reparented to init so what's the big deal in adding another line ? There can be cases, when the parent dies, and almost immediately the child dies too, before getting reparented to init, in this case it shows up as a . A probability that is as rare as the Indian Political System's well progression, so you can imagine, it's pretty rare. However incase you're a programmer with belief in the uprise of our nations politic system and politicians, then here's some piece of code that is to be called in the parent process, and yes ofcourse, the parent will stay alive till it's child process dies :


Daemon Processes Are:

A daemon process is simply a process that has no terminal associated with it, and can be said to run in "background". For example when you start Apache from the shell, it after starting, shifts control back to the shell. Hence the new process started (apache) is now running in background, and has immediately shifted control to the calling process.
Now for the code, goody goody! :

#include <stdio.h>
	#include <sys/signal.h>
	#include <............>

	  /* Ignore terminal I/O signals */

	  signal(SIGTTOU, SIG_IGN);
	  signal(SIGTTIN, SIG_IGN);
	  signal(SIGTSTP, SIG_IGN);

	  /* Ignore terminal I/O signals */

	  int pid;
	  pid = fork();
	  if (pid != 0)
	    exit(0); /* this is the parent process here, so let's exit it for our daemon work */

	  setsid(); /* child process, so let's make us a session leader, and lose control tty */
	  signal(SIGHUP, SIG_IGN); /* SIGHUP will be sent to child process so ignore it */

	  if (pid != 0)
	    exit(0);

	  /* this is the main daemon process, also the grand child process */

Now you'll be wondering why we forked twice ? Well it's quite simple, the child process is a session and process group leader, hence it might be able to reacquire a terminal, and SystemV manual states that a process can only reacquire a terminal if it a process group leader, so to avoid this, we simply make a child process (grandchild) of this child process, this guarantees that the grandchild can't be a process group leader. But this now poses another problem, we obviously want to exit the parent of the grandchild process, so when we exit the parent of the grandchild the kernel will send a SIGHUP to the grandchild which'll wait for 5 seconds for the grandchild to exit, if it doesn't the kernel pan fries the process.


When the daemon process terminates it simply gets reparented to init. But you're asking now well all this hassle simply so that we could get into background ?

Well, Yes.

But couldn't we simply do that by exec("nohup myProgName 1> /dev/null 2>&1 &"); ? Sure!

But it's not always that we want it to be started from a shell prompt. However in case your task islet's say make a download(er), that goes around the net downloading files on to a server which may be closer to home (for faster downloads, ofcourse) then exec()ing is more than suitable.

commented: I like your writing style and way of approaching a problem +21

wat is yhe prototype for fork();

void main()
{
fork();
fork();
printf("main");
}
pls explain me what is the output.
how it comes.

Its output will be mainmainmain.The reason behind this is that whenever we call fork a new process is created.The PC points(in the new process) to the instruction after the fork.So we can say that first fork will create another function with statements
fork();
printf("main");
this fork creates another process with
printf("main");

so we have 3 main printed.You need to think that we have a new process each time fork is called.

What does fork() do? :?:

Fork is a function that creates a new process.A process is a program in execution.What fork() does is that it creates a new process copying the code segment.It also returns pid to identify the process.Its value is 0 for Child process.

I think that this program should print main 4 times that because the first program will create a process with
fork();
printf("main");

second fork() in the main with
printf("main");

and the fork in the first fork will also create a process with
printf("main");

main will also print the "main" once because of the printf stmnt inside the main...

So in my opinion output should be..
mainmainmainmain

Its output will be mainmainmain.The reason behind this is that whenever we call fork a new process is created.The PC points(in the new process) to the instruction after the fork.So we can say that first fork will create another function with statements
fork();
printf("main");
this fork creates another process with
printf("main");

so we have 3 main printed.You need to think that we have a new process each time fork is called.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.