I've seen sites that say when a command is entered in a terminals shell, this gives it to the OS which is where the actual change is done; while others say the shell allows users to communicate with the kernel.
However, images on the internet, like the first one on this Wikipedia page say that the kernel sits between the OS and applications.
So is the shell actually sending the commands to the kernel which then sends them to the OS or does the shell sit at the same level as the kernel and and is then just sending the commands straight to the OS?
Related
Why is the following empty program exiting on Ctrl + C with 130 on Linux (which is what I suspect, because my shell bash wraps SIGINT to 130 (128+2).
On Windows with Git Bash (git-bash.exe), I get exit code 2.
package main
func main() {
for {
}
}
Is that Go's behavior on Windows or git-bash.exe? Because I need exit code 2 internally, do I need to wrap it using the signal package?
Well, it's two-fold.
On the one hand, as #Flimzy pointed out, it's shell intervening.
On the other hand, what is missing from his remark is why this happens.
The explanation is, again, two-fold:
A process has certain default signal handling disposition which is how the process reacts to certain signals. A signal can be ignored, handled or left as is which, in most if not all cases means killing the process.
You can read more about this here.
Note that in non-trivial processes such as programs written in Go which have intricate runtime system, the default signal disposition may be different from that of "more plain" processes.
By default the SIGINT signal is not handled meaning it kills the process.
The bash she'll adds 128 to the exit code of a process if it was killed with a fatal signal. More about this — in the bash manual.
Update on the behaviour in Windows.
Let's first put up a quick fact sheet:
Windows does not support the concept of Unix signals, at all.
The way terminal-aware programs work on Unix-like systems is very different from the way console-aware programs work on Windows.
Say, the way Vim looks and behaves in a "Git bash" windows on Windows may look very similar to how it looks in a GNOME Terminal window on a Linux-based OS but the underlying differences are profound.
Let's now dig a bit deeper.
Unix was born without any notion of GUI and the users would interact with a Unix system using hardware terminals.
In order to support them, kernels of Unix-like OSes implement special standardized way to make terminal-aware programs interact with the system; if you're "into" deep-diving into technical details, I highly recommend reading the "TTY demystified" piece.
The two more important highlights of this approach are:
The terminal subsystem is used even by programs running in what the contemporary generation of freshmen calls "terminals"—in windows which typically start out running a shell, in which you call various command-line programs, including those using "full screen"—such as text editors.
This basically means if you take, say Vim or GNU Nano, it will run just fine in any graphical terminal emulator, or directly on Linux's "virtual terminal" (those textual screen you can get on a PC by hitting Ctrl-Alt-F1 or booting with GUI turned off) or on a hardware terminal attached to the computer.
The terminal subsystem allocates certain codes a keyboard may send to it to perform certain actions—as opposed to sending those coder directly to the program attached to that terminal, and Ctrl-C is one of them: in a common default setup pressing that combination of keys makes the terminal subystem send the foreground process the SIGINT Unix signal.
The latter is of particular interest. You can run stty -a in a terminal window on your Linux system; amoung the copious output you'd see something like intr = ^C; quit = ^\; which means Ctrl-C sends interactive attention (SIGINT) signal and Ctrl-\ sends SIGQUIT (yes, "INT" in "SIGINT" does not stand for "interrupt"—contrary to a popular belief).
You could reassign these key combos almost at will (though it's not a wise thing to do as many pieces of software expect ^C and ^\ to be mapped the way they usually do and do not assign their own actions to these gestures—rightfully expecting to not be able to actually ever receive them.
Now back to Windows.
On Windows, there is no terminal subsystem, and no signals.
Console window on Windows was an artefact required to provide compatibility with the older MS-DOS system, and there the situation was like this: Ctrl-Break would trigger a hardware interrupt usually handled by the OS, and Ctrl-C could be explicitly enabled to do the same. The implementation of the console emulation on Windows carefully emulated this behaviour, but since Windows does not have Unix-like signals, the handling of these keyboard combos is done differently—though with much the same effect:
Each console process has its own list of application-defined HandlerRoutine functions that handle CTRL+C and CTRL+BREAK signals. The handler functions also handle signals generated by the system when the user closes the console, logs off, or shuts down the system. Initially, the handler list for each process contains only a default handler function that calls the ExitProcess function.
What this all means to Go?
Let's first see the docs:
~$ GOOS=windows go doc os.Interrupt
package os // import "os"
var (
Interrupt Signal = syscall.SIGINT
Kill Signal = syscall.SIGKILL
)
The only signal values guaranteed to be present in the os package on all systems are os.Interrupt (send the process an interrupt) and os.Kill (force the process to exit). On Windows, sending os.Interrupt to a process with os.Process.Signal is not implemented; it will return an error instead of sending a signal.
So, in a Go program running on Windows you can handle these two "signals"—even though they were not really be implemented as signals.
Let's now move to explaning the difference in the exit codes.
As you know by now, pressing Ctrl-C when a program is running in a terminal emulator windows on a Unix-like system will make the terminal subsystem send the process the actual SIGINT signal.
If this signal is not explicitly handled, the process gets killed by the OS (as that's what the default signal disposition says).
The shell notices that a process it spawned suddenly died, collects its exit code and adds 128 to it (because it wasn't expecting it to die that way).
On Windows, hitting Ctrl-C makes the process perform the ExitProcess system call, which, form the point of view of the shell process looks like normal process exit: it cannot tell this exit apart from the one occured if the process were to call os.Exit(0) explicitly.
I have recently discovered "fs_usage" which seems extremely useful.
I was wondering, along the same lines, is it possible to intercept the interaction of a process with the operating system? (to run it in a "sand box" mode for example, if the program tells "write address X", I write to address Y instead. and if program tells "read address X", I read address Y and return that etc, basically have full control on what a process I run can do to my computer or sees from my computer)
Of course it's possible, that's what debuggers do! If you're talking about Linux, that's ptrace(2). On Mac, that's dtrace.
How would I go about detecting if my go CLI program is in focus or minimized?
Current program based off https://github.com/jroimartin/gocui
I require the functionality as it is a chat program and I would like to send OS notifications but only when the program is not in focus or is minimized.
Your help/direction is much appreciated as of right now unsure where to start.
This is not possible from the library itself. A command line program does now have a focus, but the terminal program it is running in.
To implement that (if possible at all) would be dependent on os, window manager etc.
To refine the answer provided by #mbuechmann, I suggest the OP not to try to resort to APIs etc.
The reasoning is simple.
"Contemporary" users are used to running programs in terminal emulators which are typically presented as separate windows, and so the users naturally think of these programs as not really different from GUI apps.
But the reality is different: a terminal emulator—whether graphical or not (for instance, so-called "virtual consoles" provided by the Linux kernel running on an x86/amd64 hardware are terminal emulators as well)—really emulates a typical work session on a real hardware terminal, and there, a program would work in foreground solely, and the only means of "switching" to another program was using the shell's job control (those jobs, bg and fg commands).
In other words, the whole concept of a program working in a terminal has an inbuilt assumption that the terminal is always "foreground"—since at the time the concept was developed, a terminal was a physical device.
Now please also consider that "terminal emulation" may be more pervasive on a contemporary system than you might think: screen and tmux on a Unix-like OS are multiplexing terminal emulators—which may themselves be run in a terminal emulator, and a console window on Windows™ may be considered to be a terminal emulator of sorts as well.
So, "resorting to APIs" have several technical problems:
Terminal emulation tries to actually decouple the program which uses this facility from being aware of how the facility is actually provided.
To put it simple, there's, say, no easy way on X Window System, to know what window is used by the terminal emulator running your program.
You'd need to cover diverse set of APIs in order for your program to still be useful: X Window System on Unix-like systems, Mac OS, Windows™. And contemporary GUI stacks running on Linux tend to be switching to Wayland instead of X.
In certain cases, like running a program in a "nested" terminal emulation sessions (for example, a pane in a "window" of a tmux running in xterm), figuring out such facts about the environment might be next to impossible.
And still the crucial problem is that if your program really needs to know whether it's focused or not, it actually wants to be aware about the concepts currently hardly accessible to it. I mean, it wants to be GUI. And if so, just make it GUI.
In fact, it may be simpler than you think. The core of your program might still be a CLI app with a thin GUI wrapper around it which uses any sort of IPC to talk with the app (which might be two-way, if needed).
The simplest is to write some (usually line-wise) data to the program's standard input.
Im new to "Operating Systems" to please just dont blast me.
I studied the User Mode and the Kernel Mode of the CPU. I've just discovered that some CPU has intermediate modes beetween user and kernel mode.
But why is this necessary ? Is it dangerous to use always kernel mode for privileged instructions ? Or is a matter of prestations ?
The VAX/VMS system is one that used four modes. VMS works quite differently from Eunuchs. In Eunuchs variants you have a shell process. Each time you run a program you create a new process. In fact, the shell in Eunuchs variants is just a program with nothing special about it.
In VMS, the the command interpreter exists in the same process as the running program. Programs can (and often do) interact with the command interpreter. When your program ends, the command interpreter takes back control. Run another program and you remain in the same process with a new executable loaded.
The command interpreter runs in "supervisor mode" which is one level higher than user mode. It is then protected from the user mode access messing with it. As the same time, any bugs in the command interpreter will not cause the system to crash.
Also the debugger exists in supervisor mode within the process it is debugging.
For people brought up under Windoze and Eunuchs you cannot appreciate how primitive their file handling is. VMS, like most real non-toy operating systems, has different file structures. It supports stream files like Eunuchs and Windows. However, it also supports sequential file structures, fixed record file structures and files indexed on keys. The system services for managing this run in executive mode (above supervisor and below kernel). Again, that allows having protected system services that will not crash the entire operating system.
I should also mention that non-toy operating systems support file versions. If you open a document, edit it, and save it, you create a new version of the file with the same name. If you make a misteak or eror you can go back and fix it.
The general answer to your question is these other modes provide means for the operating system to provide interfaces to services that are otherwise protected from users messing with that will not affect the entire operating system when there are problems.
Ideally, an operating system would do as little as possible in kernel mode. When you have operating systems that are quick and dirty and do very little, they just use kernel mode.
Here is what I want to do:
I want to run Mathematica on another Mac from my Mac (both Snow Leopards). I want to do this because the remote Mac has multiple cores/processors while my local Mac is rather shabby. I would like to have the front end still locally (i.e. the graphical interface).
What I've learned:
I used to do this type of thing from multiple Linux machines and was expecting to have similar success for Mac-to-Mac operation. However no such luck.
The problem seems to be a display issue (front end).
Mac front end runs in Aqua while X11 is what is really needed (this is why there is no problem on Unix). While Macs have X11, for some reason Mathematica can't use it.
So how do I get around this issue?
Possible solutions that I have had to rule out are: 1. screen sharing. Not practical since someone else will be using the remote Mac on another account. Screen sharing only uses the active screen. 2. Installing Unix on the remote computer. Not possible in my situation.
Thanks.
You should be able to set up a remote kernel on the other Mac. This is done through the Evaluation > Kernel Configurations menu item. The you can set the remote kernel for a given notebook using Evaluation > Notebook's Kernel or globally via Evaluation > Default Kernel.
I haven't done this in a while, and it's sometimes useful to test things from a terminal with something like
ssh <user>#<remote.machine.com> </path/to/remote/Mathematica.app/Contents/MacOS/MathKernel>
Why not use the command line kernel? I have a script math which does:
#!/bin/bash
rlwrap /Applications/Mathematica.app/Contents/MacOS/MathKernel
I built rlwrap from source, but basically that tool gives you readline behaviors. You can just do
ssh remote-machine /Applications/Mathematica.app/Contents/MacOS/MathKernel
The only solution, I believe, is for you to upgrade to OS X Lion. It allows simultaneous screen sharing sessions where each user can control the screen for their own account:
http://www.apple.com/macosx/whats-new/features.html#screensharing