the difference of using fork() and exec() with system()
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
the difference of using fork() and exec() with system()
Hello there. Is there someone kind enough to please explain to me the difference of using fork() and exec() with system() in invoking a process. I just want to know their difference according to well experienced with processes here. And what is the most efficient in invoking a process between the two. Thanks.
I'm a bit confused. In order to spawn a new process, you must first use fork()to make a copy of the current process, then exec() to transform one of these processes into an instance of the program you want to spawn. I have here a test program. I used fork and exec to execute the command in Linux "switch user" or the "su" command. I was surprised to see two outputs. It executed two "su" commands. Here's the code.
You received two "su" commands because you executed it twice.
Your original process (the "master") called fork(). A second process (the "slave") was created--a mirror image of the master. Then both processes continued execution. The next instruction for both processes was the execvp() call.
If you want only one process to execute execvp(), then you need to build an if statement around it, and check the return result of fork(). The fork() function's return value indicates whether the process was originally the master or the slave. Read the man page to understand what the return value should be in each case.
Last edited by Dark_Helmet; 06-01-2007 at 12:15 AM.
Hi jaepi,
let me answer ur first question,
exec family will replace the current execution of the process context with the image that u have specified....so always exec calls is used with the fork().. i.e. after forking... fork will create another instance of the process.. so the from the next statement of forking everything is duplicated...fork returns the child pid to the parent and the 0 to the child process.. so after forking there will be a child and parent.. normally in child we will exec..(execvp u have used there is a blocking call it wont return untill there is some error in execvp, since u have used fork() it has executed that twice...) fork() and exec wont invoke the shell...
where as system() it creates a shell and executes the command what u have given inside the system in the shell...
for further clarifications read the man pages..
cheers
culin...
Your original process (the "master") called fork(). A second process (the "slave") was created--a mirror image of the master. Then both processes continued execution. The next instruction for both processes was the execvp() call.
Both the master and the slave executed the execvp() function. Two processes--two calls to execvp()--two invocations of "su".
Last edited by Dark_Helmet; 06-01-2007 at 01:15 AM.
Ahh. So the parent process (the main program) was split into two, producing the child process and the parent process. Now here, the execvp() function invoked both process that's why I end up producing two "su" commands. How do I filter that the child process will be the one executing the "su" command?
If you want only one process to execute execvp(), then you need to build an if statement around it, and check the return result of fork(). The fork() function's return value indicates whether the process was originally the master or the slave. Read the man page to understand what the return value should be in each case.
Store the return value of fork() in a variable (which you already do), and use an if statement to decide whether to call execvp() based on fork()'s return value.
...
execvp u have used there is a blocking call it wont return untill there is some error in execvp, since u have used fork() it has executed that twice
...
'execvp' is just 'execv' that searches PATH for the command.
The main reason to use 'system' is when you have a command line as a string, such as "ls -ld". That will not 'execv' because there is no program "ls -ld"; just the "ls" program.
'su' will use the 'system' call when using '-c' since the entire command must be in 1 argument. The 'exec' built-in in bash, however, can take the entire command line and build an 'execv' call.
'system' uses the default shell to evaluate the argument, whereas 'execv' actually inserts the 'char*[]' argument into 'argc' and 'argv' of the program given by the 'char*' argument.
Since 'system' returns rather than replacing the process, you can emulate 'execv' by doing 'exit( system("ls -ld") );'. Normally 'system' is used when a program needs the assistance of an outside command, whereas 'execv' is used when a lengthy process or daemon needs communication with the parent outside of just command line arguments.
You should also check out 'pipe', 'dup2', and 'fcntl' to make full use of 'fork' and 'execv'. If you need some help putting it all together let us know.
ta0kira
PS To make 'fork' more clear: In the parent process the function returns a positive number (the process ID of the child) if successful and a negative number if unsuccessful. In the child process it will return 0. You can therefore do this:
Code:
pid_t child = 0;
if ( !(child = fork()) )
{
char *command[] = { "ls", "-ld", NULL };
exit( execvp(command[0], command) ); //use 'exit' in case there is a problem with 'execvp'
}
else if (child < 0) exit(1);
//...parent program continues...
good info ta0kira, but i have a clarification..
but , we can as well use execvp to accomplish "ls -ld" but we need to pass "-ld" as the argument to the execvp..
Quote:
Originally Posted by ta0kira
The main reason to use 'system' is when you have a command line as a string, such as "ls -ld". That will not 'execv' because there is no program "ls -ld"; just the "ls" program.
see the code below and execute that.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
int spawn(char *program, char** arg_list);
int main (int argc , char *argv[])
{
int child_pid,child_pid3;
int *status;
//pid_t child_pid1,child_pid2,child_pid3;
//int i=2;
char* arg_list1[] =
{
"ls", // argv[0], the name of the program.
"-ld",
"/home/naren/Proj_conf",
NULL // The argument list must end with a NULL.
};
child_pid=spawn("ls",arg_list1);
printf("the first child pid is %d\n\n ",child_pid);
return 0;
}
int spawn(char *program, char** arg_list)
{
int child_pid,*status;
child_pid=fork();
if (child_pid != 0)
return child_pid;
else
{
execvp(program, arg_list);
fprintf (stderr, "\nan error occurred in execvp\n\n\n");
}
}
Yes, I understand that. It is nearly the same in the example I give. The distinction I was making was that sometimes you only have an unparsed command line, such as from the environment or from user input. Rather than parsing input into a command and arguments, you can use 'system' to parse it into "ls" and "-ld" using the default shell.
ta0kira
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.