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.
Related
Is there any way to know if a process has started to run from a call of exec() or has started from the terminal by the user?
Helpful to you: child and parent process id;
getppid() returns the process ID of the parent of the calling
process. This will be either the ID of the process that created this
process using fork(), or, (!!!CARE!!!) if that process has already terminated, the
ID of the process to which this process has been reparented;
I would also consider adding additional program arg.
All programs are started by a call to exec family of functions.
When you type a command in the terminal, for example, it searches for the binary executable, forks and calls exec in the child process. This will substitute the binary image of the calling process (the terminal) for the binary image of the new program. The program will execute and the terminal process will wait.
There is this absolutely awesome answer by paxdiablo on the question Please explain exec() function and its family that will surely help you understand how exec works.
In Unix, all processes are created by using the fork system call, optionally followed by the exec system call, even those started by a user (they are fork/exec'd by the user's shell).
Depending on what you really want to do, the library function isatty() will tell you if stdin, stdout or stderr are file descriptors of a tty device. i.e. input comes from a terminal, output goes to a terminal or errors go to a terminal. However, a command like
myprog < somefile 1>someotherfile 2>errorfile
will fool code using isatty. But maybe that is what you want. If you want to take different actions based on whether there is a user typing input from a keyboard or input is coming from a file, isatty is what you need.
What is the usage of execl command?
excel("/bin/sh", "sh", "-c", cmdstring, (char *)0);
_exit(127);
Can anyone explain each statement used in execl command?
And why only _exit(127) and not exit(0).
What is 127 number indicating?
execl is one of the several functions (exec*) that let you replace the current code of your process with the one provided by the file (an executable one) specified as the first argument. The whole space of your process is replaced by a fresh one... Other arguments serve as arguments to the command. A process is a kind of system structure controlling execution of some code. exec lets you mutate that code.
In the case exec succeed then the old code is forgotten, you will never be able to get back into it. This is not a function call.
In the case exec fails then execution continues, and in your case a call to _exit is made. _exit is a system function designed to stop execution of the current process, leading to its death. exit is a C-function that does the same at C-level, roughly closing C-streams and calling _exit.
The value provided (127) is used to communicate some information about the termination of this process to the process that launched it (process are launched by the use of fork, a call that clones a process). The value can be any eight bit value, but 0 is used to denote a process that terminated correctly, and any other non 0 value to denote a process that terminated in some abnormal condition.
You can type
man execl
in the terminal for more information on the execl command.
This is homework
Hey folks, here's the portion of the assignment I'm working on now:
A command, with or without arguments, executed in the background using &.
For simplicity, assume that if present the & is always the last thing on the line.
Example: vi &
Details: In this case, your shell must execute the command and return immediately, not
blocking until the command finishes. The distinction must be made between
backgrounding a process that does not need interactive input and one that does, e.g., the
who command vs. the vi command.
Concepts: Background execution, signals, signal handlers, process groups, asynchronous
execution.
System calls: sigset(), sigaction()
Signals: SIGTTOU
So we're writing our "own shell" in C, and the code I've written up to now is working fine. Here are a few snippets so you can see what I'm doing:
// Check for ampersand
block = (ampersand(args) == 1);
The ampersand function works and returns properly according to my debug statements. Here is where I'm almost positive I actually have to do the backgrounding code, and I'm looking for help here:
// Wait for the child process to complete, if necessary
if(block) {
//If this executes, there IS an ampersand, and should be backgrounded
printf("Waiting for child, pid = %d\n", child_id);
result = waitpid(child_id, &status, 0);
} else {
//If this gets executed, there is no ampersand, and should not be backgrounded
result = waitpid(child_id, &status, 0);
}
So now I'm at the point where if I type, say "ls -l &" it'll do the ls -l command, and it'll execute that printf statement. So that's good. If I don't put the & in there, it doesn't do the printf. Also good.
Million dollar question:
Once I hit the printf statement, what should I do at that point? Please note that this is an introductory course, and I don't know much beyond the code I've already written. I mean, I know C, but Unix is very new to me.
Thanks in advance, I'll be around to supply more detail if needed :)
Suppose I have a function exec_cmd_with_child(\*params*\), which will take care of executing the command with appropriate arguments. This function needs to be called from both if and else.
The only difference we have is. inside if(block) you will not call wait as the parent process should not wait for the command to execute. Whereas inside else you will have to call wait which means the parent will wait till the command executes and will not ask for the next command.
Well, there are plenty of things to take care of if you want to bring back to process in the foreground but if not asked for that, then you are good to go.
I am trying to run a new process in background so it will be possible to continue working with parent process.
I used fork then execl. I tried to add to the execl command the argument & but it doesn't work:
execl("newproc","newproc","arg1","&",NULL);
Is there any solution?
The child will run in the background since you used fork. The child will keep running in parallel with the parent (if exec succeeded). If you care about whether the child process succeeded or not (and your code should) you should eventually call waitpid to collect its exit status. Otherwise you should call fork twice and have the intermediate process exit without waiting for the child, so that init adopts the grandchild process.
As #mah said, the & is unnecessary. But another change is needed to that line; execl is a variadic function, and function prototypes therefore don't take care of converting arguments to the correct type. Therefore the final argument should be passed as the correct type - just change it to (char*)NULL.
You mention that your code didn't work. While that could just be because of the spurious &, it may also be because of the first argument. The execl function does not search $PATH for the named program, so unless newproc is actually in the current directory, this execl() invocation will return. When execl returns, that always indicates that there is a problem. The simplest way to solve this is to use execlp() instead of execl(). The alternative approach is to specify an absolute path as the first argument. You can even specify a relative path as the first argument, but this is rarely useful.
The problem is that & is not a command line option to programs. Instead, it is merely special shell syntax which puts a command in the background. The distinguishing feature of background programs is that they are not connected to a terminal, and the terminal is not waiting for the process to complete. The proper function is daemon(). Do a man daemon to read up on how it is used.
& is not a command argument, its a flag that the shell uses to know to run the command in the background. In this case, you're performing the work of the shell... remove the &. Since you state you've called fork(), as long as you're only performing execl() in the child process after fork returns, you're already running in the background.
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.