1
$\begingroup$

TL;DR: I would like to know how a programming language, the OS and drivers work together to perform a task.

I (and we all) have used various softwares/modules/packages on the top of our OS which provides us with a very simple API/GUI/CLI to perform tasks. But one question which keeps me disturbing is:

How does that software/module/package actually perform any specified action? I mean, it actually should be instructing OS to do that. So, OS should be providing procedure calls. But many functionalities aren't provided by the OS itself but the device driver provides it. So, how does the OS know what functions are supported by this particular device? And how can we instruct a particular device to perform a particular task?

Like suppose we are planning to change the IP address of a computer, we can do it through the OS's GUI or CLI. IP address is a logical thing and doesn't belong to a specific device (hardware), so we don't need any device driver for that. Keeping this simple, how can I write a module in python (without using already available API functionality) to change the IP address of a computer? Suppose the language itself i.e. python or a module/package written in python provides this functionality that calling a function such as change_ip() does the task. But how does it actually work in background? I know the background job is different for different OSes but I don't know how that module/package/language interacts with the OS. Or is it doesn't actually interact with the OS and performs the operations itself? (Maybe its possible in some cases)

Now, some other example. Suppose I would like to change the MAC address of the machine. Now, this operation is device dependent (the Network Card). Also, few NICs doesn't support this MAC changing functionality. This is actually dependent on the device driver and not the driver itself. So how can the OS know if the function is supported or not? Also, if the module/package/language is directly performing tasks without the help of OS, how can it know if the functionality is supported?

A very few might understand this question.. I don't know how to ask.. I am pursuing BE in Computer Engineering and I know several concepts and theories. But our education system makes us learn the things separately and not understand them in a combined manner. Like what would be the benefit if I know Operating System and Python but I don't know how they interact with each other and work in a combined manner. So, this is the base of my query.

I looked for an answer on Google but never found one.. Thank you..

$\endgroup$
  • $\begingroup$ Have you checked any textbook on operating systems? Here is a one online. $\endgroup$ – Apass.Jack Jan 15 at 14:44
  • $\begingroup$ "IP address is a logical thing and doesn't belong to a specific device (hardware), so we don't need any device driver for that." Yes, we need network driver for that, I believe. $\endgroup$ – Apass.Jack Jan 15 at 14:45
  • $\begingroup$ Surely we need driver for that but, now-a-days those drivers have become a part of operating system. The question is actually very complex for me to understand that I have tried to keep it as simple as possible. $\endgroup$ – Kadam Parikh Jan 15 at 15:09
  • $\begingroup$ If I try to make it complex, it will be like diving in a deep sea... Also, I have tried to find an answer in a step-by-step manner and reached a conclusion. But I don't know if I am correct! $\endgroup$ – Kadam Parikh Jan 15 at 15:11
  • 1
    $\begingroup$ @Apass.Jack Yes.. I have referred books on OS. But the question here is not related to OS only. I would like to know how the OS, drivers and a programming language work together to perform a task. $\endgroup$ – Kadam Parikh Jan 15 at 15:13
1
$\begingroup$

There are many possible OSes, each one with its own design philosophy and technical conventions. Here's a rough, but reasonably common design for an OS. Beware that, for brevity, I had to simplify things a bit and cut some corners. OS design is a huge topic (we have whole university courses covering that!), so don't expect this to be comprehensive.

First, we exploit some hardware support to separate the OS from the userland processes. At any time, a bit register inside the CPU tells whether the CPU is executing in "OS mode" (AKA supervisor mode) or "user mode".

In OS mode, the CPU runs unrestricted, and can read/write everywhere in RAM, modify any register of the CPU, send messages to devices ("To video card: make pixel at 542,234 black"), and so on. In user mode, the CPU can only read/write at some RAM address, and use only some CPU registers. It can not directly send messages to devices.

Crucially, it can not flip the bit which turns the CPU into OS mode, otherwise a process could bypass the protection and pretend to be the OS.

Well, almost. The CPU actually allows executing a kind of magic instruction -- let's call it help! -- which precisely flips that bit and put the CPU in OS mode. There is a big catch, though: help! also acts as a jump to a special address in RAM where OS code lies. So, a process can not go in OS mode and still execute its code, but it has to jump to a specific location, causing a part of the OS code to be executed.

Usually, before asking help!, the process writes some numbers in the CPU registers.

After help! is called, the OS reads those CPU registers, and interprets those numbers as a request from the process. For example, if in register r1 there is number 0, this could be a request to change a pixel in the screen (the pixel having coordinates in registers r2 and r3 and the new color in r4). The OS then runs the code to ask the video card to change that pixel. Since every card likely requires a different message to be sent for that, the OS first calls a device driver with an hardware-independent message (color pixed X,Y as C) and that driver will then craft and send the message to the video card. Note that the driver is run in OS mode -- it is a component of the OS (in this basic design, at least).

If instead register r1 there is number 1, this could request a file to be opened (the file name being specified by r2). This could involve asking the disk diver to access the disk.

And so on. When the OS is done, it flips the CPU mode back to "user mode" and jumps to the process code, so that it can continue.

There are usually many possible requests from a process to the OS, usually specified by an ABI (application binary interface) which describes what registers to write and with what. Sometimes there's no public ABI, but programmers are supposed to call instead a usermode library, typically written in the C programming language. That library has a public API (in C), and will provide a bridge from that to the internal OS unpublished ABI.

There requests are known as "system calls" or "syscalls", by the way.

If you want to do a syscall in python, without relying on absolutely any library, you can not. This is because bare python does not give you a way to control the registers, or to run the help! instruction. Python is not special here, bare C also does not allow that, as with most programming languages.

Usually, though, one exploits some library. Or, if one really wants to go low-level, one can write a small module directly in assembly, and then call that from C or python (or anything else). That could require to use a "foreign function interface", so to link the assembly module with the language. In C it's usually very easy to do, since the language is low level. In python, calling assembly could be harder to do, but it's surely doable.

I strongly recommend you try to read an OS textbook. It should cover these topic in much more detail than we can do here.

$\endgroup$
  • $\begingroup$ Thank you for the answer.. By the way, I knew this thing but your explanation was more deeper than my understanding. Though, my question still persists. Here are the queries: 1. How can an OS know which functions are supported by a device driver? As you said, the OS first calls a device driver with an hardware-independent message (color pixed X,Y as C) and that driver will then craft and send the message to the video card. But how will the OS know if the driver it is asking to process its request is actually capable of doing that. I think drivers need to inform OS about their capabilities. $\endgroup$ – Kadam Parikh Jan 16 at 10:24
  • $\begingroup$ 2. You said "one can write a small module directly in assembly, and then call that from C or python (or anything else)". Some functionalities are supported by already python or its modules. So are all these supported functionalities executing at User level? Also, though it gets executed in user level, how is it actually implemented in python? For ex: I need to make a new directory. In python, I can do os.path.mkdirs(). This is a simple function call but how does it get implemented in background? Will python use system calls or request OS to make the directory? Thank you.. $\endgroup$ – Kadam Parikh Jan 16 at 10:30
  • $\begingroup$ @KadamParikh Each OS requires its drivers to conform to a specific API (or ABI). I.e. an HD driver must implement a function capacity, a function writeAt(position, sector) etc. Some of these functions are used by the OS to discover the features the driver supports. E.g. the driver has to implement a boolean function video3D-Capable() reporting whether the card supports 3D graphics, so that the OS can inform itself about what is actually supported. Whoever writes the driver has to follow the API spec defined by the OS. $\endgroup$ – chi Jan 16 at 16:00
  • $\begingroup$ @KadamParikh 2. a possible implementation is: when you use os.path.mkdirs() some python library code gets executed. This code uses a special command to invoke a C library (libc), passing the right arguments to a C function inside the library (mkdir()). When run, this C function will do some more checks and then eventually jump to a small code snippet written in assembly, which fill the registers exactly as the OS wants to see them, and finally calls the OS using help!. Then the OS creates the directory. If you have a linux around, you could use strace command to log all the syscalls $\endgroup$ – chi Jan 16 at 16:08
  • $\begingroup$ Two questions here.. You said, "This code uses a special command to invoke a C library (libc), passing the right arguments to a C function inside the library". So, I guess that the C library belongs to the OS and not the programming language, right? If python uses a way to call C libraries of the OS, can I too write a script which can call any C library of the OS? $\endgroup$ – Kadam Parikh Jan 17 at 6:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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