A Central Abstraction: The Process

Abstractions

I do strongly believe in abstraction being the root of computing (however, you may want to read Is abstraction the key to computing? as a motivation for a different perspective on the role of abstraction in computing). Modern hardware and software systems include a lot of features and perform so many tasks that it is impossible to understand, build and use them without recurring to abstractions. For instance, let’s take a look at the CPU: it is the central part of a general purpose computing system, and is also an extremely complex system in itself. Functionally, a CPU is an instruction-crunching device: it processes one instruction after another, following the steps of fetch, decode, execute and writeback (in von Neumann architectures). In other words, the CPU retrieves the instruction from memory, decodes it, executes it, and put the results of the operation back into memory. Further, the CPU has no clue (and actually does not care) about the higher-level semantics of the instruction it may be executing at a specific time. For example, the CPU may be executing an instruction related to a spell-checking task, and a few instructions later it may be executing an instruction related to other task, say, MP3 playing. It only follows orders, and just execute the instruction it is told to execute.

Nowadays, computing systems are expected to do more tasks on behalf of its users. Several tasks must be performed concurrently. As in the previous example, the system might be running the spell-checker and the media player simultaneously. In multiprogrammed systems we can achieve pseudoparallelism by switching (multiplexing) the CPU among all the user’s activities (true parallelism is only possible in multi-processor or multi-core systems). Remember that multiprogramming requires the CPU being allocated to each system’s task for a period of time and deallocated when some condition is met.
Continue reading “A Central Abstraction: The Process”

coLinux, int 80 on Windows and other rants

Generally speaking, an Application Binary Interface (ABI) is the interface between an application program and the operating system. Conceptually, it’s related to the more well-known API concept. But ABIs are a low-level notion, while APIs are more leaned toward the application source code level.

Recently, a friend sent me an email exposing some problems he faced when trying to assemble on Cygwin a code originally targeted at Linux. The problem, as he stated, was that int 0x80 didn’t perform as expected. Well, plenty of explanations are pertinent:

Cygwin

Cygwin allows to run a collection of Unix tools on Windows, including the GNU development toolchain. However, at its core, cygwin is a library which translates the POSIX system call API into the pertinent Win32 system calls (system calls are often abbreviated as syscalls). Therefore, cygwin is a software layer between applications using POSIX system calls and the Win32 operating systems, which allows porting some Unix applications to Windows. This way you can, for instance, have the Apache daemon working as a Windows service. Other very attractive feature of Cygwin is its interactive environment: you can run your shell quite nicely, and run your Autoconf scripts, for example. However, porting means recompiling. There is no binary compatibility, and your program cannot run in computers without Cygwin (without CYGWIN1.DLL, more precisely). Furthermore, albeit some progress has been made, Cygwin is relatively slow (it’s a POSIX compatibility layer, after all.) If possible, I prefer to recompile my applications directly with MinGW. For me, this allows for a faster development cycle. Note, though, that Cygwin can compile MinGW-compatible executables. It’s just that, as aforesaid, I prefer to work with MinGW directly. I only work on Windows if I have to develop applications for Windows. But Linux’s development tools are the best, and we can access several of them by using MinGW. I think that Cygwin is best suited for general cross-development and for handling complicated software porting.

System Calls and int 0x80

A system call is a request by an active process for a service performed by the operating system kernel. Remember that a process is an executing (running) instance of a program, and the active process is the process currently using the CPU. The active process may perform a system call to request creation of other process, for instance. Or perhaps the process needs to communicate with a peripheral device. In Linux on x86, int 0x80 is the assembly language instruction that is used to invoke system calls. int 0x80 is a software interrupt, as it will be raised by a software process, not by hardware devices. Before invoking such interruption, our program has to store the system call number (which allows the operating system to know what service your program is specifically requesting ) in the proper register of the CPU. Every interrupt is a signal to the operating system, notifying it about the occurrence of an event that must be computationally handled.

Continue reading “coLinux, int 80 on Windows and other rants”