views:

19

answers:

2

When we type vi at the prompt in a Unix Shell, we are able to use the Vim Editor.

Now the Shell forks another process.

AFAIk i read in a book that one Process cannot Modify the other. Then how come in Linux the Shell allows us to open Vim in the terminal itself?

I am confused about the fact that if the shell is actually accessing the Address space of Vim or not.

A: 

The shell simply connects Vim’s terminal file descriptors to its own’s, passing the data through.

You may have heard of file descriptors like “standard input”, “standard output” and so on. When using a terminal emulator (like XTerm or whatever you use), it provides the shell that’s running inside it with a stream of keystrokes that it receives, and it interprets the data the shell sends to the terminal (colors etc.) and displays them.

When you start Vim, the shell launches its process and provides that process with an input and output stream on its own. The input stream is the same the shell receives, i.e. everything typed on the terminal gets received by the shell which then sends it on to Vim. Everything Vim is sending into its output stream is received by the shell and then sent to the terminal.

Basically, the bidirectional flow of data looks like this:

terminal emulator <====> shell <====> vim
Scytale
Please elaborate, would be helpful!
Xaero
Not quite correct. The shell does not "pass" anything back and forth. It does `fork(2)` and then `execve(2)` to start a process. `fork(2)` system call lets child process *inherit* open file descriptors, `execve(2)` leaves them open for the new process image.
Nikolai N Fetissov
So there is one thing for sure even though Vi is the Child process,Shell has no way of modifying it?@Nikolai N FetissovCan you please Answer the Question with a good explanation :)?
Xaero
@Xaero, what exactly do you mean by "modifying a process"?
Nikolai N Fetissov
I mean Modifying something within a running process from another process via direct access, and not passing arguments/file descriptors
Xaero
A: 

There's only one way in Unix to start a user process - the fork(2) system call. It creates an exact replica of the calling process, the difference being the return value of the call - process id (pid) of the new process in the parent/caller, zero in the child. The OS maintains this parent-child relationship through parent process id property (see, for example, output of ps -f).

What happens behind the scene is that the OS kernel duplicates the whole virtual memory space of the caller (there are more details here, google for Copy-On-Write page mapping and vfork). There's no direct access from one address space to the other unless specifically setup via a shared memory mechanism like mmap(2). The parent process can wait(2) for its children to terminate.

I'm not going to go into process groups, sessions and controlling terminals. That needs a good picture. Look into, say, APUE book for thorough explanation.

The execve(2) system call replaces current process image with one of some executable from a file.

Now the shell has its stdin, stdout, and stderr connected to a terminal emulator, inherited from login(1) process on the console, or dynamically allocated by a network daemon like sshd, or a window manager (X). When you type, say, vi in the shell, it forks and then execs /bin/vi program, then waits for it. The new process inherits open file descriptors and ia able to manipulate the terminal pseudo-device through them via ioctl(2).

The fun actually starts with pipelines, when you type something like ps -ef|grep bash - that is left as an exercise for the reader :)

I glossed over many interesting details here, but hope this can help a bit as a brief introduction.

Nikolai N Fetissov