When to use system() and when to use execv*()? - c

I need to execute a unix command with different args in a loop. Now I wonder if I should use execvp(), passing in the cmd and the args, or use system, building a string consisting of cmd + args?

Well, the other answers are mostly correct.
System, while not only forks and then execs, it doesn't exec your process, it runs the default shell, passing your program as an argument.
So, unless you really want a shell (for parameter parsing and the like) it is much more efficient to do something like:
int i = fork();
if ( i != 0 ) {
exec*(...); // whichever flavor fits the bill
} else {
wait(); // or something more sophisticated
}

The exec family of functions will replace the current process with a new one, whilst system will fork off the new process, and then wait for it to finish. Which one to use depends on what you want.
Since you're doing this in a loop, I guess you don't want to replace the original process. Therefore, I suggest you try to go with system.

I'd use execvp only if I can't achieve what I want with system. Note that to get the equivalent of system, you need execvp, fork and some signal handling as well.

Related

Creating a child process WITHOUT fork()

Is there a way to start a child process without fork(), using execvp() exclusively?
The pedantic answer to your question is no. The only system call that creates a new process is fork. The system call underlying execvp (called execve) loads a new program into an existing process, which is a different thing.
Some species of Unix have additional system calls besides fork (e.g. vfork, rfork, clone) that create a new process, but they are only small variations on fork itself, and none of them are part of the POSIX standard that specifies the functionality you can count on on anything that calls itself a Unix.
The slightly more helpful answer is that you might be looking for posix_spawn, which is a library routine wrapping fork and exec into a single operation, but I find it more troublesome to use that correctly than to write my own fork+exec subroutine. YMMV.
posix_spawn is the only posix compliant way to create a child process without calling fork directly. I say 'directly' because historically posix_spawn would itself just call fork, or vfork. However, that is no longer the case in GNU/linux. posix_spawn itself may be more efficient than fork, in addition to perhaps being a stronger fit conceptually when code is attempting to run a different executable.
If you aren't worried about portability, you can abandon posix and couple yourself directly to the kernel you are targeting. On linux the system call to create a child process is clone. At the time of this answer the manual page provides documentation for three variants, including the relatively new clone3.
I believe you can take the example from the manual page and add an execvp call to childFunc. I have not tried it yet, though!
Unlike Windows systems, where creating a new process and executing a new process image happen in a single step, Linux and other UNIX-like systems do them as two distinct steps.
The fork function makes an exact duplicate of the calling process and actually returns twice, once to the parent process and once to the child process. The execvp function (and other functions in the exec family) executes a new process image in the same process, overwriting the existing process image.
You can call execvp without calling fork first. If so, that just means the currently running program goes away and is replaced with the given program. However, fork is the way to create a new process.
As user zwol has already explained, execve() does not fork a new process. Rather, it replaces the address space and CPU state of current process,
loads the new address space from the executable filename and starts it from
main() with argument list argv and environment variable list envp.
It keeps pid and open files.
int execve(const char *filename,char *const argv [],char *const envp[]);
filename: name of executable file to run
argv: Command line arguments
envp: environment variable settings (e.g., $PATH, $HOME, etc.)
posix_spawn. But it ignores failures of execvp() -- potentially because implementing this was regarded as too complicated.

C - How do I run a program in the background using exec?

There is a program I can run on terminal like so: ./program &
But I'm trying to do it using execvp and it isn't working:
pid = fork();
char *argv[3] = {"./program", "&", NULL};
if ( pid == 0 ) {
execvp( argv[0], argv );
}
else{
wait(NULL);
}
What did I do wrong here?
As answered by Greg Hewgill, the ending & is a shell syntax (it is technically not a shell command) related to job control.
In your question, it is unclear why you need it. You could just not use that "&", and your code should work. Read also about background processes, about terminal emulators, about process groups. Read the tty demystified.
BTW, you could instead of wait use waitpid(2) and specify the pid. You generally need some waiting (e.g. wait, waitpid, wait4(2), etc ....) to avoid having zombie processes. You may want to handle the SIGCHLD signal, but read signal(7) & signal-safety(7).
Perhaps you want to use the daemon(3) function. See also setsid(2), setpgrp(2), and credentials(7). Otherwise, you probably should call wait much later in your program. You might want to redirect (using dup2(2)), perhaps to /dev/null, to some other open(2)-ed file descriptor, to some pipe(7), etc..., the stdin (and/or stdout and stderr) of your child process. You may also want to multiplex input or output using poll(2).
Your code should handle the failure of fork(2) (when it gives -1), perhaps using perror(3) in such case. You also should handle failure of execvp(3).
In some limited and specific particular cases, you could want to popen(3) a sh, nohup(1), batch, at, or bash but you generally don't need that.
(without understanding your motivations, and why you want to run something in the background, we can't help you more)
The "&" you have in the argv array isn't going to do what you want, and may be the source of your problem here. That's a place for program arguments, and & is a shell command, not a program argument. Remove it since the ./program will run in a separate process anyway since you've forked.

Process tree, how to find if a said process is the root one?

I have a directory monitoring application which works recursively by launching new processes.
I'd like to know if I'm the "root" process in this tree. I thought about trying to get the name of the caller process and check if it's the same as argv[0].
Is there a smarter way of doing this? Keep in mind, this is a Linux app.
Keep in mind, I don't have much time for this and I'm but a student, so a simple solution would be great.
Thanks for your time.
If you use fork() to create new processes, you can have a local variable initially set at zero that each child sets to 1 immediately after forking. Only the root process would still have it set at zero after a fork.
You could even increase it after each fork, which would let you know how deep in your process tree each process is.
EDIT:
If you cannot use this (e.g. because you do an exec() after fork), you can use any of the common ways that shells use to pass information to the programs that you launch:
Environment variables: call setenv() after fork() but before exec() - or add it in the environment when calling exec().
Use a special command line argument.
Use a special value for argv[0] when doing exec().
Have you the possibility to add an argument meaning "I'm not the root"? That seems the simplest approach.
If you are calling exec, add a special argument, or environment variable called "I_AM_NOT_THE_ROOT" which the child processes get, but the parent does not.
I recently used a command-line argument for this, but env variables might be more convenient.

How do I call an executable from a C program (using winapi)?

CreateProcess() came up a few times searching google....
Is it OK to assume this is the safest and most efficient method?
If so, I would like to use the output of the called process.
How do I know it has completed before continuing on in the C program?
Thanks.
ShellExecute Can be used to create a process, its a more convenient way to pass arguments.
But if you want to use the output of the process then CreateProcess is probably your best bet
With CreateProcess you can pass a STARTUPINFO structure that can be used to pass a file pipe handle to Standard Out of the process.
CreateProcess will return a PROCESS_INFORMATION structure containing a HANDLE to the created process. That handle will become signalled when the process exits.
So You can WaitForSingleObject on the process handle to wait for the output to be complete.
Don't forget to CloseHandle on the process handle and thread handle when you are done.
Depends on how you measure efficiency. system() is programmer efficient.
Also see exec() and its many brothers.
CreateProcess() is a fairly low-level function for spawning subprocesses and may not be the most convenient option. For a C program where you need to read the output, consider popen() (note that the MS CRT places an underscore before its name):
FILE *f = _popen("dir", "r");
char buf[1000];
while (fgets(buf, sizeof(buf), f)) {
// .. process output using stdio functions
}
_pclose(f);
The classic source for how to execute a Windows program and catch its output is this article on MSDN - it's actually not as complicated as it looks.
If you need full control (change std in/out etc), CreateProcess is your best option. If you are executing something specified by the user, you really need to use ShellExecute[Ex] since CreateProcess will fail for applications that require UAC elevation (ShellExecuteEx is also able to give you a handle to the child process when you start applications)

How do you spawn another process in C?

How do you run an external program and pass it command line parameters using C? If you have to use operating system API, include a solution for Windows, Mac, and Linux.
It really depends on what you're trying to do, exactly, as it's:
OS dependent
Not quite clear what you're trying to do.
Nevertheless, I'll try to provide some information for you to decide.
On UNIX, fork() creates a clone of your process from the place where you called fork. Meaning, if I have the following process:
#include <unistd.h>
#include <stdio.h>
int main()
{
printf( "hi 2 u\n" );
int mypid = fork();
if( 0 == mypid )
printf( "lol child\n" );
else
printf( "lol parent\n" );
return( 0 );
}
The output will look as follows:
hi 2 u
lol child
lol parent
When you fork() the pid returned in the child is 0, and the pid returned in the parent is the child's pid. Notice that "hi2u" is only printed once... by the parent.
execve() and its family of functions are almost always used with fork(). execve() and the like overwrite the current stackframe with the name of the application you pass to it. execve() is almost always used with fork() where you fork a child process and if you're the parent you do whatever you need to keep doing and if you're the child you exec a new process. execve() is also almost always used with waitpid() -- waitpid takes a pid of a child process and, quite literally, waits until the child terminates and returns the child's exit status to you.
Using this information, you should be able to write a very basic shell; one that takes process names on the command line and runs processes you tell it to. Of course, shells do more than that, like piping input and output, but you should be able to accomplish the basics using fork(), execve() and waitpid().
NOTE: This is *nix specific! This will NOT work on Windows.
Hope this helped.
If you want to perform more complicated operations, like reading the output of the external program, you may be better served by the popen system call. For example, to programmatically access a directory listing (this is a somewhat silly example, but useful as an example), you could write something like this:
#include <stdio.h>
int main()
{
int entry = 1;
char line[200];
FILE* output = popen("/usr/bin/ls -1 /usr/man", "r");
while ( fgets(line, 199, output) )
{
printf("%5d: %s", entry++, line);
}
}
to give output like this
1: cat1
2: cat1b
3: cat1c
4: cat1f
5: cat1m
6: cat1s
...
#include <stdlib.h>
int main()
{
system("echo HAI");
return 0;
}
I want to give a big warning to not use system and 100% never use system when you write a library. It was designed 30 years ago when multithreading was unknown to the toy operating system called Unix. And it is still not useable even when almost all programs are multithreaded today.
Use popen or do a fork+execvp, all else is will give you hard to find problems with signal handling, crashs in environment handling code etc. It's pure evil and a shame that the selected and most rated answer is promoting the use of "system". It's more healthy to promote the use of Cocain on the workplace.
On UNIX, I think you basically need to fork it if you want the spawned process to run detached from your the spawing one : For instance if you don't want your spawned process to be terminate when you quit your spawning process.
Here is a page that explains all the subtle differences between Fork, System, Exec.
If you work on Win,Mac and linux, I can recommend you the Qt Framework and its QProcess object, but I don't know if that's an option for you. The great advantages is that you will be able to compile the same code on windows linux and mac :
QString program = "./yourspawnedprogram";
QProcess * spawnedProcess = new QProcess(parent);
spawnedProcess->start(program);
// or spawnedProcess->startDetached(program);
And for extra, you can even kill the child process from the mother process,
and keep in communication with it through a stream.
One solution is the system function defined in stdlib.h
int system(const char *string);
system api example
If you need to check/read/parse the output of your external command, I would suggest to use popen() instead of system().
Speaking of platform-dependent recipes, on Windows use CreateProcess, on Posix (Linux, Mac) use fork + execvp. But system() should cover your basic needs and is part of standard library.

Resources