execl return - Ubuntu - c

My question is: after finishing the execution of the new process image, the function
execl()
would return the execution to the caller process or to the father process?

When using one of the exec family of functions, you do not expect the function to return at all. The program counter begins at the first instruction of the binary image that replaced the calling process.
From the Darwin man page:
If any of the exec() functions returns, an error will have occurred.
The return value is -1, and the global variable errno will be set to
indicate the error.
There was a comment asking about the following, but it was deleted:
If you are in a child process, and execl succeeds, then the child process is replaced by the new binary. If it fails, then control returns to that child process (the caller). There's no strict relationship between fork and exec, if that's what you're asking. If you are in a child process, and exec fails, then you have a "forked" child process, which is a copy of the original parent process. At this point you probably want to print some error message and exit from the child process.
If you want to know why it failed, you can use the following pattern:
if (execl(...)) {
perror(NULL);
exit(errno);
}
For example, try running this program, the error message will indicate how to fix the program:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main (const int argc, char * const argv[]) {
if (execl("ls", "ls", "-la", NULL)) {
perror(NULL);
exit(errno);
}
return 0;
}
The solution, use execlp instead of execl in this case.

Related

What happens to the child process after calling exec?

I'm new to system programming and curious how the exec function works. My first question is why does the child never print "I'm the child" after calling exec. How does exec replace the child process? My second question is why does the program (after calling exec) continue and ask for one more command line argument before it completely terminates. I'm not sure what's going on here. Anyone could explain what is going on would be very appreciated. Here is the code:
#include <stdio.h>
#include <unistd.h>
int main(void) {
if(fork() == 0){
printf("Hello from child!\n");
execl("/usr/bin/sort", "sort", "talk.c",NULL);
printf("I'm the child\n");
}
else{
printf("Hello from parent!\n");
printf("Iam the parent\n");
}
return 0;
}
You can read about execl in https://linux.die.net/man/3/execl
The exec() family of functions replaces the current process image with a new process image. The functions described in this manual page are front-ends for execve(2). (See the manual page for execve(2) for further details about the replacement of the current process image.)
exec family REPLACES the current process image with a new process image so nothing after execl happen.

How to execute multiple processes in C?

I need to create a program that takes input from the user and executes it just like it does in the terminal. I am using the execvp() function for this purpose. The requirement of the program is to keep taking input from the user unless the quit call is encountered. The problem here is that the current program is replaced after the execvp() call. So, using a goto is not an option either. I found this Fork–exec article but it doesn't tell how to create an indefinite number of processes. Here is my code:
#include <unistd.h>
#include <stdio.h>
#include <string.h>
void main() {
char *args[4];
char inputCommand[100];
fgets (inputCommand, 100, stdin);
printf ("Splitting string \"%s\" into tokens:\n",inputCommand);
/* Perfrom string tokenization here */
execvp(args[0], args);
}
fork() can be called an indefinite number of times; as long as the return value indicates that you're the parent process, you can continue to operate as usual and call it again.
Thus, you can have a loop within which you fork, call an execvp() if you're the child process, and continue to the next iteration if you're the parent.
Execvp replaces the current process image with the command you run. So it cancels your C program. To produce the desired effect, you should fork before execvp. It would look something like this:
int status = 0;
pid_t pid = fork();
if(pid > 0) {
waitpid(pid, &status, 0);
// is parent
} else if(pid == 0) {
execvp(*args, args);
// is child
} else {
// fork didn't work
}

Why does fflush() affect the output of forked processes?

I'm trying to learn UNIX programming and came across a question regarding fork() and I couldn't interpret the output of the 2 programs below.
I understand that fork() creates an identical process of the currently running process, but where does it start? For example, if I have these two programs below, what will be the output and how does it work ?
#include<stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main (int argc, char **argv)
{
int retval;
printf ("This is most definitely the parent process\n");
// now here fork will create a child process
// i need to know from which line child process starts execution
retval = fork ();
printf ("Which process printed this?\n");
return (0);
}
What will be the difference in above program and the one below with
respect to child process execution:
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
int main (int argc, char **argv)
{
int retval;
printf ("This is most definitely the parent process\n");
fflush (stdout);
// how does fflush change the output of above program and why ?
// even though no string operations are being used
retval = fork ();
printf ("Which process printed this?\n");
return (0);
}
I think both of them should print :
This is most definitely the parent process
Which process printed this?
Which process printed this?
But the first one is printing:
This is most definitely the parent process
Which process printed this?
This is most definitely the parent process
Which process printed this?
I understand that fork() creates an identical process of the currently
running process, but where does it start?
If fork(2) is successful (i.e. does not return -1), it starts in the line that calls fork(2). fork(2) returns twice: it returns 0 in the child, and a positive number C in the parent, where C is the process ID of the newborn child.
The reason you're seeing This is most definitely the parent process twice is related to stdio's buffering. Stdio buffers output in userspace buffers that are flushed only when some condition occurs (for example, the buffer becomes full). The buffering mode dictates when and how buffers are flushed.
Usually, if output is being written to an interactive device such as a terminal (or pseudoterminal), stdio is line-buffered, which means that the buffers are flushed when a newline is found or fflush(3) is called.
OTOH, if output is redirected to a file or other non-interactive devices (for example, output is redirected to a pipe), stdio is fully-buffered, which means that buffers are flushed only when they become full or fflush(3) is called.
So, without fflush(3), executing the code in a terminal device will print this:
This is most definitely the parent process
Which process printed this?
Which process printed this?
Which is expected. However, if you pipe it through cat(1), you will see this (or some other variant, depends on execution order):
This is most definitely the parent process
Which process printed this?
This is most definitely the parent process
Which process printed this?
This is because output is fully buffered when redirected to a pipe. The string This is most definitely the parent process isn't enough to fill and flush the buffer, so when the parent forks, the child (which gets a copy of the parent's memory space) will get a copy of the output buffer, which already contains the string This is most definitely the parent process. So both processes end up printing that string.
If you always call fflush(3) before forking, this won't happen because the buffer is empty when the parent's memory space is copied to the child.
Execution will continue at (or just after) the fork call. You can use the return value to check if you're the parent or the child process:
RETURN VALUE
On success, the PID of the child process is returned in the parent, and 0 is returned
in the child. On failure, -1 is returned in the parent, no child process is created,
and errno is set appropriately.
(Source: man fork)
For example, if you have the following program:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char **argv) {
printf("Foo.\n");
int retval = fork();
printf("Bar from %s (%d).\n", (retval == 0) ? "child" : "parent", retval);
return 0;
}
The output would be something like:
Foo.
Bar from parent (18464).
Bar from child (0).
...assuming output is line buffered.
when calling fork() there are three possible return conditions.
Do read the man page for fork()
the three return conditions are
-1 -- the fork() failed
0 -- the child is executing
some positive number -- the pid of the child, the parent is executing
The code needs to be something like this:
pid_t pid;
pid = fork();
if ( 0 > pid )
{ // then handle error
}
else if ( 0 == pid )
{ // then child executing
}
else // if ( 0 < pid )
{ // then parent executing
}

Where does code Execution start in a child process?

Consider the code:
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
/* main --- do the work */
int main(int argc, char **argv)
{
pid_t child;
if ((child = fork()) < 0) {
fprintf(stderr, "%s: fork of child failed: %s\n",
argv[0], strerror(errno));
exit(1);
} else if (child == 0) {
// do something in child
}
} else {
// do something in parent
}
}
My question is from where does in the code the child process starts executing, i.e. which line is executed first??
If it executes the whole code, it will also create its own child process and thing will go on happening continuously which does not happen for sure!!!
If it starts after the fork() command, how does it goes in if statement at first??
It starts the execution of the child in the return of the fork function. Not in the start of the code. The fork returns the pid of the child in the parent process, and return 0 in the child process.
When you execute a fork() the thread is duplicated into memory.
So what effectively happens is that you will have two threads that executes the snippet you posted but their fork() return values will be different.
For the child thread fork() will return 0, so the other branch of the if won't be executed, same thing happens for the father thread.
When fork() is called the operating system assigns a new address space to the new thread that is going to spawn, then starts it, they will both share the same code segment but since the return value will be different they'll execute different parts of the code (if correctly split, like in your example)
The child starts by executing the next instruction (not line) after fork. So in your case it is the assignment of the fork's return value to the child variable.
Well, if i understand your question correctly, i can say to you that your code will run as a process already.When you run a code,it is already a process , so that this process goes if statement anyway. After fork(), you will have another process(child process).
In Unix, a process can create another process, that's why that happens.
Code execution in a child process starts from the next instruction following the fork() system call.
fork() system call just creates a seperate address space for the child process therefore it is a cloned copy of the parent process and the child process has all the memory elements of it's parent's process.
Thus, after spawning a child process through fork(), both processes (the parent process and the child process) resumes the execution right from the next instruction following the fork() system call.

Creating a child process on Unix systems?

I'm trying to create a child process in another process. I am writing both the programs in C language. First I write a dummy process which will be the child process. What it is doing is only to write a string on the screen. It works well on its own. Then I write another program which will be the parent process. However, I can't make it happen. I'm trying to use fork and execl functions together, but I fail. I also want the child process does not terminate until the parent process terminates.
How should I write the parent process?
Thanks.
Here is the code for the child process:
#include <stdio.h>
int main(void) {
while(1) {
printf("*");
sleep(1);
}
}
And here is the parent process:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void) {
if (fork()) {
while(1) {
printf("-\n");
sleep(5);
}
} else {
execl("./", "dummy", (char *)0);
}
}
The fork() system call may return three different statuses: failure (<0), parent process (>0) or child process (==0). You must test the return value properly.
int pid = fork();
if (pid < 0) {
/* handle error */
perror("fork");
exit(1);
} else if (pid > 0) {
/* parent code */
} else {
/* child code */
}
Your execl() system call is wrong. The first argument is the path to the program you want to execute, "./" is not valid, it should be something like "./dummy" at least. The next argument is by convention the command name (argv[0] in the executed program), which may be a repetition of the first argument. So:
execl("./dummy", "dummy", NULL);
Also, note that the printf("*") statement in the child program will probably buffer and you won't see anything on the terminal. You must either add a "\n" to the end or call fflush(stdout) to flush the standard output.
Basic use of fork in C
int PID = fork();
if( PID < 0 ) {
//fail
return PID;
}
else if( !PID ) {
//child process
return exec( prog, args );
}
else {
//parent process
return 0;
}
There is no way to force the child process to "not terminate" when it's done (you'll still be able in the parent to wait for it to get info on how it terminated, but that's about it). Apart from that, any of the many examples of fork/exec on the web, such as this one, should work -- why don't you try it and see if it performs as you wish (in which case you'll just need to change whatever you were doing differently in your own attempt). If it doesn't work as desired (except for the impossibility per the first sentence in this A;-), please edit your to add copious detail about how the code behaves differently than you expect it to.

Resources