I found so many explanations and answers on execvp
but it all seems confusing. execvp
takes a command and sends it to kernel and then does something, execvp
creates an image, execvp
is system call, execvp
...etc. As a beginner with limited C language and Linux experience, only the following explanation seemed to click for me:
It's executing ls
with 2 arguments: >
and awd.txt
. It is equivalent to running:
'ls' '>' 'awd.txt'
Here is the thread: What does execvp actually do?
However, I asked the following question to the person who answered and he did not reply, hence I'm asking separately in a desperate attempt to understand it.
So to execute ls -a
in execvp
, we should do execvp ("ls", args)
; where args
is {"ls", "-a"}
? or execvp (args[0], args)
?
Can someone tell me if it's true: execvp
takes the first argument from the array args
and then sends that to kernel to follow the following array arguments? So execvp(args[0],args);
would be that from args [] = {"ls", "-a"}
array the args[0]
takes ls
, sends it to the kernel and then what?It goes looking for another args[0]
and finds -a
and sends that, and the kernel determines that these two makes a command like ls -a
?
The prototype is:
int execvp(const char *file, char *const argv[]);
The first argument, file
is the name of the program to execute. execvp
will search your path and try to find a match. From the manpage:
The execlp(), execvp(), and execvpe() functions duplicate the
actions of the shell in searching for an executable file if the
specified file name does not contain a slash (/) character.
The file is sought in the colon-separated list of directory
pathnames specified in the PATH environment variable.
If/when execvp finds a match, that program will be loaded into memory and replace your current running program.
The arguments the new program will see are the argv
array specified in execvp. You are expected to have a null pointer as the last element, or your program may crash looking for a null.
If you do:
char *argv[]={"bar","bash","penguin",0};
execvp("foo",argv);
then when foo starts, it will have the same environment as your current program, its argc will be 3 and its argv will be the above list. Even though the program name is "foo", it's argv[0] while running will show up as "bar".
You don't actually have to have argv[0] be the name of the new program. It is expected, but not required.
Incidentally, with your example of
ls > awd.txt
If you did this on the command line, your shell would fork creating a new copy of itself. The child shell would open awd.txt and do a dup2() to put the child fd attached to awd.txt as 1. After some other housekeeping, the child shell would do something like.
execvp("ls", {"ls", 0})
so in the created "ls" argc==1 and argv[1] ==0. Traditionally , we would say that ls has 0 arguments.