LinuxQuestions.org
Help answer threads with 0 replies.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 05-31-2007, 10:12 PM   #1
jaepi
Member
 
Registered: Apr 2007
Location: Urban Jungle
Distribution: Ubuntu
Posts: 189
Blog Entries: 1

Rep: Reputation: 30
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.
 
Old 05-31-2007, 10:31 PM   #2
jaepi
Member
 
Registered: Apr 2007
Location: Urban Jungle
Distribution: Ubuntu
Posts: 189

Original Poster
Blog Entries: 1

Rep: Reputation: 30
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.

Code:
 
      #include <iostream>
   
      #include <unistd.h>
   
       
   
      using namespace std;
   
     
   
      int main(){
   
      const char* command = "su";
   
      pid_t child_p;
   
  
      child_p = fork();
  
       
  
      execvp(command, NULL);
  
      return 0;
  
      }
Question:

Quote:
you must first use fork()to make a copy of the current process
-What was the process that the fork in my test program copied?
-Why is it that it produced two instances of the "su" command?
 
Old 06-01-2007, 12:13 AM   #3
Dark_Helmet
Senior Member
 
Registered: Jan 2003
Posts: 2,786

Rep: Reputation: 374Reputation: 374Reputation: 374Reputation: 374
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.
 
Old 06-01-2007, 12:23 AM   #4
culin
Member
 
Registered: Sep 2006
Distribution: Fedora Core 10
Posts: 254

Rep: Reputation: 32
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...
 
Old 06-01-2007, 12:37 AM   #5
jaepi
Member
 
Registered: Apr 2007
Location: Urban Jungle
Distribution: Ubuntu
Posts: 189

Original Poster
Blog Entries: 1

Rep: Reputation: 30
@Dark_Helmet and culin - Thank you sirs!

Quote:
You received two "su" commands because you executed it twice.
@Dark_Helmet - How come I executed the "su" command twice?
 
Old 06-01-2007, 01:14 AM   #6
Dark_Helmet
Senior Member
 
Registered: Jan 2003
Posts: 2,786

Rep: Reputation: 374Reputation: 374Reputation: 374Reputation: 374
Quote:
Originally Posted by Dark_Helmet
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.
 
Old 06-01-2007, 01:20 AM   #7
jaepi
Member
 
Registered: Apr 2007
Location: Urban Jungle
Distribution: Ubuntu
Posts: 189

Original Poster
Blog Entries: 1

Rep: Reputation: 30
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?
 
Old 06-01-2007, 11:49 AM   #8
Dark_Helmet
Senior Member
 
Registered: Jan 2003
Posts: 2,786

Rep: Reputation: 374Reputation: 374Reputation: 374Reputation: 374
Quote:
Originally Posted by Dark_Helmet
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.
 
Old 06-01-2007, 12:58 PM   #9
jlliagre
Moderator
 
Registered: Feb 2004
Location: Outside Paris
Distribution: Solaris 11.4, Oracle Linux, Mint, Debian/WSL
Posts: 9,789

Rep: Reputation: 492Reputation: 492Reputation: 492Reputation: 492Reputation: 492
Quote:
Originally Posted by jaepi
I just want to know their difference according to well experienced with processes here.
system is a standard library function, fork and exec are system calls, i.e. lower level.
Quote:
And what is the most efficient in invoking a process between the two.
There should be no difference in performance, system is using fork and exec (and waitpid) under the hood anyway.
 
Old 06-03-2007, 07:49 PM   #10
jaepi
Member
 
Registered: Apr 2007
Location: Urban Jungle
Distribution: Ubuntu
Posts: 189

Original Poster
Blog Entries: 1

Rep: Reputation: 30
Thank you very much.
 
Old 06-04-2007, 08:21 AM   #11
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Quote:
Originally Posted by culin
...
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...

Last edited by ta0kira; 06-04-2007 at 02:50 PM.
 
Old 06-05-2007, 03:56 AM   #12
culin
Member
 
Registered: Sep 2006
Distribution: Fedora Core 10
Posts: 254

Rep: Reputation: 32
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");
                        }

}
 
Old 06-05-2007, 07:14 AM   #13
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
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
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
fork/exec problem djgerbavore Programming 2 04-13-2006 11:13 PM
how to fork/ exec schneidz Programming 10 08-30-2005 11:50 AM
Programming: fork, exec and system memory atienza Programming 2 08-24-2005 07:26 AM
what is the difference between Fork & exec augustus123 Linux - Newbie 1 11-29-2004 07:32 AM
Fork 'n Exec sourceman Linux - General 4 02-14-2002 02:31 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 04:46 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration