June 20
Chapter 11: The Environment, officially this time (maybe)
Chapter 12: vi
Videos:
11. The Environment
12. The vi editor
Review pipelines
broken pipe: I could not reproduce this. But this occurs when the upstream end tries to write, and the downstream end has closed the pipe.
Hwk 3 #2: ls -lrS vs ls -lRS
#5: what about grep 'systemd\[' syslog | wc -l
A process is something that gets scheduled on the CPU. It has its own virtual memory space, its own stack,its own heap, and its own code segment (often called "text segment" for historical reasons). When a process is suspended, the address of the next instruction to be executed is saved, as is the virtual-memory mapping. When the process is scheduled, the VM map is restored, the registers are restored, and control branches to the previously saved address of the next instruction.
One process can have multiple threads, but we'll ignore that here. Two processes can use shared memory; that is, a set of pages of physical memory that are mapped into the virtual-address spaces of both processes. The processes can talk to one another that way.
Processes can create other processes, eg with the fork() system call.
Every process has a numeric Process IDentifier, or pid. You can see these with the ps command (ps -ef or ps ax). Actually, the top command is simplest, but note that it goes into full-screen mode; type q to quit.
It is common to pipe the output of ps into grep to look for specific processes; eg ps -ef | grep -i firefox or ps ax | grep -i cups. Of course, that is likely to find the grep process as well.
The command ps alone, without the -ef or ax, just shows processes that are still "attached" to your terminal. That pretty much means processes you explicitly started.
Shotts has a table of process run states on page 112. R means it's either running or is waiting to run. S means it is sleeping, which usually means in turn that it is waiting for input. D used to be the bane of my existence. Z means it's become a zombie.
The top command is a bit better at showing how much memory and cpu the process is using.
Any command we type will start a process (unless it's a shell built-in command). Here are some gui-display commands:
What does the shell do when you start one of these? It waits. You can tell it not to wait by typing an '&' after it.
We can send signals to processes. Typing Cntl-C in the shell window where we started the process sends it the Interrupt (INTR or INT) signal. It exits (although processes can catch this signal). Other signals:
Signals can be sent manually to processes using the kill command (which, despite the name, sends the TERM signal).
To be able to send a signal to a process, you must either be root or else own the process (that is, your userid matches the userid of the process)
Finally, let's do this process example:
If you want to reproduce this from the command line and can't run xlogo, try sleep 120 &. This sleeps for 120 seconds.
When a process exits, its parent is supposed to run the wait() system call to clean up. Until that happens, the process is in zombie state (that is, it's dead, but still in the process table so still partly alive). Having the parent have to remember to wait() for all its children is more complicated than it should be.
Processes are normally in the same process group as their parent. When you type Ctrl-C on the terminal, the INTR signal is sent to all processes in the shell's process group. The shell ignores it. But your runaway program hopefully does not.
Likewise, when your dial-in line experienced a phone-system hangup, one of the lines in the serial cable signals this to the terminal driver. The terminal driver then sends the HANGUP (or HUP) signal to every member of the process group living on that terminal. That includes the shell, and probably also whatever you were running.
At the heart of modern-day containers (like Docker and Kubernetes) is the idea of creating namespaces for various resources. A process can only see the resources for a namespace if it is part of a group that is granted such visibility. Group membership is inherited by child processes. Examples:.
The namespace then behaves a bit like it's isolated from everything else, almost like it's running in its own virtual machine but without the memory overhead.
We'll consider these editors:
gedit: a basic menu-driven editor. Control characters can be used
line mode vs character mode
So far we've been working in line mode, where maybe nothing is sent to the system until you press ENTER. This makes backspace a local operation.
character mode: each character is sent to the system as soon as it is pressed.
Editing needs character mode.
Actually, character mode may be used all the time now. The so-called "readline" feature means bash has to recognize arrow keys and characters as they are typed. Still,
Line mode is forced via stty icanon. It is unset via stty -icanon. (Note: the hyphen usually, but not always, undoes the result of the non-hyphen form)
Generally, icanon is not used much any more so that, say, the up-arrow key works at the command line. That is, true line mode is sort of obsolete.
stty: this is where associations are defined between certain control characters and signals. The signals are sent to the process group of the shell.
How about ^W?
stty raw (undone with stty -raw)
Another important stty setting: echo. This means the terminal driver echoes back what you type (so you can see what you type). Of course, in an editor the software has to take control of echoing, since updates might involve considerable screen reformatting. And characters may be commands, not to be echoed at all!
When you edit in a terminal, the editor has a model of what your terminal screen looks like, and sends various control sequences to make your actual terminal match that. You are in trouble if this breaks down, and your screen no longer looks like what the editor thinks it does!
Arrow keys
What do your arrow keys actually send to the system? Try:
cat > rarrow
[press right-arrow]
press ENTER
press Ctrl-D
od -c rarrow
Then there's also what the system can send back to your terminal to update the screen. Here are a few basic terminal operations:
Typically these are low-level operations. To insert a character on line 5 that causes wraparound of the end of the line onto line 6, the editor might need to:
Your editor learns what kind of terminal you have by the shell variable TERM in your environment. What is it? Probably "linux". On my desktop, it's set to "xterm-256color". Another popular choice is "ansi".
Once upon a time, each different model of "real" hardware terminal had its own entry. Then the DEC vt100 became popular (following their vt52), and everyone started being compatible with that.
After looking at editing normally, we'll try editing with TERM=dumb
Nano is modeless. Every displayable character is entered when you press it. Nano uses control characters for actions; see the bottom two lines.
Some Nano commands are implemented with the "Meta" key, which is usually mapped to "Alt".
The vi editor is much more powerful, but definitely harder to use. It's the one I use most, because I started doing this before nano or pico existed. (Emacs existed, but it's even harder to use.)
Most versions of vi today are actually vim, by Bram Moolenaar.
Vi has a command mode and an insert mode. Many commands are just ordinary letters. Command sequences starting with ':' automatically jump to the bottom line. To exit vi without saving, use ":q!". To exit with saving, use ":wq"
A common modern-day recommendation is to spend most of your time in insert mode (the arrow keys do work there)
Here are some moving-around commands:
Here are some commands to enter insert mode.
Use ESC to exit insert mode.
Use u to undo the most recent command. Multiple u's now undo multiple previous commands.
To delete:
To paste:
To search:
Commands: env, export, execve()
settings in .bashrc