Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have a simple doubt on execution of the command ls. As per my understanding from the research I have done on the internet, I understood the below points.

  1. When we type ls command shell interprets that command.

  2. Then the shell process forks and creates the child process & the parent(shell) executes the wait() system call, effectively putting itself to sleep until the child exits.

  3. Child process inherits all the open file descriptors and the environment.

  4. Then The child process executes an exec() of the ls program. This reads the ls program from its program file on disk into the existing [child] process.

  5. When the ls program runs to completion it calls exit() and it sends a signal to its parent indicating the child has terminated.

My doubt starts from here onwards,as soon as ls finishes its tasks ,does it sends the result back to the parent process or it just itself displays the output to the screen?. If it sends the o/p back to parent, then is it using pipe() implicitly?

share|improve this question

3 Answers 3

Typically the parent process waits until the child process ends by calling waitpid. The parent process gets the PID of the process from fork.

This means the child never signals the parent process in any way that it exited or what happened. This is done by the system and not the child process.

If you are talking about the output of the program, the parent typically never receives the output of the child process unless it provided fds. This also means that the child process prints the output and not the parent process. The parent process just receives information about the state of the process (for more information see the macros in the waitpid manpage)

share|improve this answer
    
>Thanks for the input buddy –  Subi Suresh Mar 16 '13 at 6:56

ls will output what it has to output on its standard output. To do that, it calls the write system call, something like:

 write(1, "file1  file2...\n", 16)

(or more likely it calls libc functions like printf or fwrite that eventually do the write() system call)

It assumes that the file descriptor 1 (stdout by convention) was already opened and points to something. Actually, ls does check whether its file descriptor 1 points to a terminal or something else. If it doesn't point to a terminal, it does instead:

 write(1, "file1\nfile2...\n", 15)

That is, it writes one file per line when the output doesn't go to a terminal.

When you write:

 ls file1 file2

ls's file descriptor 1 will point to the same resource as the shell's fd 1 (so for instance, if it was an interactive shell started by xterm, that will point to the pseudo-terminal device controlled by xterm). The shell does nothing special, it's inherited upon fork and because the O_CLOEXEC flag is typically not set of the file descriptor, it is preserved upon execve.

If you write:

var=$(ls file1 file2)

The shell creates a pipe, and assignes the fd 1 of the child process to the writing end of that pipe and reads the other end of the pipe to fill the var variable.

It's not magically done upon exit, it's just done as part of the job of the process. It's independant from any other activity of the shell. ls is just another process with its fd 1 connected to some resource like the terminal while the shell is another process busy doing a waitpid().

What you may find though is that when stdout is not a terminal, ls buffers its output and would only call write() when enough data (enough being several kilobytes) have been accumulated or it's closing its output or it's exiting. So, in that regard, you'll find the write is done upon exiting, but only as part of the flushing of buffers that is being done by those I/O libraries.

share|improve this answer
    
>Thank u steve for the input –  Subi Suresh Mar 16 '13 at 6:58

If exec(3) succeeds, the program which called it is no more. It is replaced by the program execed. The new program running inherits the environment, in particular the open files, of the original.

share|improve this answer
    
> Could you pls help me in understanding the concept.My question is does the child sends the result back to the parent?who is printing the output of ls command.is it the child process or the shell,which is the parent process in this case.? –  Subi Suresh Mar 14 '13 at 18:33
1  
Your shell fork(3)s, and the child then exec(3)s ls. While ls runs, it is the child process, which took over the child shell. The child ls writes directly to the screen, while the parent process wait(2)s for the child to finish before resuming. The first thing the parent does is print the prompt again. –  vonbrand Mar 14 '13 at 18:37
    
Thanks for clearing my doubt.If you dont mind shall i ask 1 more doubt,it was in my mind when i started learning pipes.Even the above doubt itself arise in my mind because of that root doubt..Can a pipe() be called implicitly in any case even if we dont use command like this ls | more.What i meant to ask exactly is if i execute a single command say for eg ls and assume that here child process sends data back to parent,then it need to use one or other way say pipe.Then does pipe() is called such scenarios implicitly even if we dont use "|" operator? –  Subi Suresh Mar 14 '13 at 18:44
    
There is no pipe from the child to the parent in this case. Both just happen to write to the same output file (screen). Unless you explicitly ask it to connect processes with |, the shell won't do it. –  vonbrand Mar 14 '13 at 18:52
    
@vondrand> Fine you cleared all my confusions.Thanks buddy ;-) –  Subi Suresh Mar 14 '13 at 18:54

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.