Unix Programming - What is the purpose of fork?

This is Interesting: Free IT Magazines  
Home > Archive > Unix Programming > February 2007 > What is the purpose of fork?





You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

Author What is the purpose of fork?
uberkermit@gmail.com

2007-02-18, 7:17 pm

Someone asked the question of the following program (which you will no
doubt recognise as having its origin - though slightly modified - from
Steven's Advanced programming in the UNIX Environment [APUE], page
11),

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#define MAXLINE 4098

int main(void)
{
char buf[MAXLINE]; /* from apue.h */
pid_t pid;
int status;

printf("%% "); /* print prompt (printf requires %% to print %) */

while (fgets(buf, MAXLINE, stdin) != NULL) {
if (buf[(int)strlen(buf) - 1] == '\n')
buf[strlen(buf) - 1] = 0; /* replace newline with null */

if ((pid = fork()) < 0) {
printf("fork error");
} else if (pid == 0) { /* child */
execlp(buf, buf, (char *)0);
printf("couldn't execute: %s", buf);
return 127;
}
/* parent */
if ((pid = waitpid(pid, &status, 0)) < 0)
printf("waitpid error");
printf("%% ");
}

return 0;
}

The question being, why is the call to fork necessary? An answer
given was that execl replaces the current process image with a new
process image, so the fork is necessary in order to (in the case of
this program anyway) prevent the shell from disappearing.

I found the question to be an interesting one, as I personally had no
answer. I did some digging in Steven's APUE, Bach's The Design of the
UNIX Operating System, as well as The Design and Implementation of the
4.3 BSD UNIX Operating System. In all of these (I only did a cursory
search) I read that a call to fork is the only way to create a new
process, but I still did not see why it was necessary in the case of
the program above - I experimented on my own machine (I admit that
this is not necessarily a good way to learn anything) with a modified
version of the program:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#define MAXLINE 4098

int main(void)
{
char buf[MAXLINE]; /* from apue.h */

printf("%% "); /* print prompt (printf requires %% to print %) */

while (fgets(buf, MAXLINE, stdin) != NULL) {
if (buf[(int)strlen(buf) - 1] == '\n')
buf[strlen(buf) - 1] = 0; /* replace newline with null */


execlp(buf, buf, (char *)0);
}

return 0;
}

As you can see, I removed the call to fork, and then compiled it and
when I ran it, it listed the contents of the directory, and then
exited. It all seems to have worked fine. Anyway, knowing that a
fork/exec call is the traditional way of doing things, I still don't
see why the fork was necessary in the original program.

I would add that I run a GNU/Linux machine with a fairly recent 2.6
kernel.

Binary

2007-02-18, 7:17 pm

On 2=D4=C219=C8=D5, =C9=CF=CE=E78=CA=B107=B7=D6, uberker...@gmail.com wrote:
> Someone asked the question of the following program (which you will no
> doubt recognise as having its origin - though slightly modified - from
> Steven's Advanced programming in the UNIX Environment [APUE], page
> 11),
>
> #include <stdio.h>
> #include <unistd.h>
> #include <sys/wait.h>
> #define MAXLINE 4098
>
> int main(void)
> {
> char buf[MAXLINE]; /* from apue.h */
> pid_t pid;
> int status;
>
> printf("%% "); /* print prompt (printf requires %% to print %) */
>
> while (fgets(buf, MAXLINE, stdin) !=3D NULL) {
> if (buf[(int)strlen(buf) - 1] =3D=3D '\n')
> buf[strlen(buf) - 1] =3D 0; /* replace newline with null */
>
> if ((pid =3D fork()) < 0) {
> printf("fork error");
> } else if (pid =3D=3D 0) { /* child */
> execlp(buf, buf, (char *)0);
> printf("couldn't execute: %s", buf);
> return 127;
> }
> /* parent */
> if ((pid =3D waitpid(pid, &status, 0)) < 0)
> printf("waitpid error");
> printf("%% ");
> }
>
> return 0;
>
> }
>
> The question being, why is the call to fork necessary? An answer
> given was that execl replaces the current process image with a new
> process image, so the fork is necessary in order to (in the case of
> this program anyway) prevent the shell from disappearing.
>
> I found the question to be an interesting one, as I personally had no
> answer. I did some digging in Steven's APUE, Bach's The Design of the
> UNIX Operating System, as well as The Design and Implementation of the
> 4.3 BSD UNIX Operating System. In all of these (I only did a cursory
> search) I read that a call to fork is the only way to create a new
> process, but I still did not see why it was necessary in the case of
> the program above - I experimented on my own machine (I admit that
> this is not necessarily a good way to learn anything) with a modified
> version of the program:
>
> #include <stdio.h>
> #include <unistd.h>
> #include <string.h>
> #define MAXLINE 4098
>
> int main(void)
> {
> char buf[MAXLINE]; /* from apue.h */
>
> printf("%% "); /* print prompt (printf requires %% to print %) */
>
> while (fgets(buf, MAXLINE, stdin) !=3D NULL) {
> if (buf[(int)strlen(buf) - 1] =3D=3D '\n')
> buf[strlen(buf) - 1] =3D 0; /* replace newline with null */
>
> execlp(buf, buf, (char *)0);
> }
>
> return 0;
>
> }
>
> As you can see, I removed the call to fork, and then compiled it and
> when I ran it, it listed the contents of the directory, and then
> exited. It all seems to have worked fine. Anyway, knowing that a
> fork/exec call is the traditional way of doing things, I still don't
> see why the fork was necessary in the original program.
>

Yes, case like so simple don't bother to use fork. But at least one
reason that fork() can work better, that is when the execd program
will block, the caller will eventually be blocked.
> I would add that I run a GNU/Linux machine with a fairly recent 2.6
> kernel.



Rainer Weikusat

2007-02-19, 7:20 am

uberkermit@gmail.com writes:

[...]

> Steven's Advanced programming in the UNIX Environment [APUE], page
> 11),
>
> #include <stdio.h>
> #include <unistd.h>
> #include <sys/wait.h>
> #define MAXLINE 4098
>
> int main(void)
> {
> char buf[MAXLINE]; /* from apue.h */
> pid_t pid;
> int status;
>
> printf("%% "); /* print prompt (printf requires %% to print %) */
>
> while (fgets(buf, MAXLINE, stdin) != NULL) {
> if (buf[(int)strlen(buf) - 1] == '\n')
> buf[strlen(buf) - 1] = 0; /* replace newline with null */
>
> if ((pid = fork()) < 0) {
> printf("fork error");
> } else if (pid == 0) { /* child */
> execlp(buf, buf, (char *)0);
> printf("couldn't execute: %s", buf);
> return 127;
> }
> /* parent */
> if ((pid = waitpid(pid, &status, 0)) < 0)
> printf("waitpid error");
> printf("%% ");
> }
>
> return 0;
> }
>
> The question being, why is the call to fork necessary? An answer
> given was that execl replaces the current process image with a new
> process image, so the fork is necessary in order to (in the case of
> this program anyway) prevent the shell from disappearing.


[...]

> int main(void)
> {
> char buf[MAXLINE]; /* from apue.h */
>
> printf("%% "); /* print prompt (printf requires %% to print %) */
>
> while (fgets(buf, MAXLINE, stdin) != NULL) {
> if (buf[(int)strlen(buf) - 1] == '\n')
> buf[strlen(buf) - 1] = 0; /* replace newline with null */
>
>
> execlp(buf, buf, (char *)0);
> }
>
> return 0;
> }
>
> As you can see, I removed the call to fork, and then compiled it and
> when I ran it, it listed the contents of the directory, and then
> exited.


And the original program reads lines from stdin until EOF or some
input error condition and tries to execute programs with corresponding
names. Hence the fork.
Stephane CHAZELAS

2007-02-19, 7:20 am

2007-02-18, 16:07(-08), uberkermit@gmail.com:
[...]
> while (fgets(buf, MAXLINE, stdin) != NULL) {
> if (buf[(int)strlen(buf) - 1] == '\n')
> buf[strlen(buf) - 1] = 0; /* replace newline with null */
>
>
> execlp(buf, buf, (char *)0);
> }
>
> return 0;
> }
>
> As you can see, I removed the call to fork, and then compiled it and
> when I ran it, it listed the contents of the directory, and then
> exited. It all seems to have worked fine. Anyway, knowing that a
> fork/exec call is the traditional way of doing things, I still don't
> see why the fork was necessary in the original program.

[...]

In the code above, your /shell/ is being replaced by the command
whose path is given in the first line of input. So, when that
command is finished, the process dies, your shell won't magically
get back to life to read the second line of input (the second
command path).

--
Stéphane
Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com