Take the 2-minute tour ×
Computer Science Stack Exchange is a question and answer site for students, researchers and practitioners of computer science. It's 100% free, no registration required.

I'm studying CPU's and I know how it reads a program from the memory and execute its instructions. I also understand that an OS separates programs in processes, and then alternate between each one so fast that you think that they're running at the same time, but in fact each program runs alone in the CPU. But, if the OS is also a bunch of code running in the CPU, how can it manage the processes?

I've been thinking and the only explanation I could think is: when the OS loads a program from the external memory to RAM, it adds its own instructions in the middle of the original program instructions, so then the program is executed, the program can call the OS and do some things. I believe there's an instruction that the OS will add to the program, that will allow the CPU to return to the OS code some time. And also, I believe that when the OS loads a program, it checks if there's some prohibted instructions (that would jump to forbidden adresses in the memory) and eliminates then.

Am I thinking rigth? I'm not a CS student, but in fact, a math student. If possible, I would want a good book about this, because I did not find anyone that explains how the OS can manage a process if the OS is also a bunch of code running in the CPU, and it can't run at the same time of the program. The books only tell that the OS can manage things, but now how.

share|improve this question
4  
See: Context switch The OS does a context switch to the app. The app can then request OS services which do a context back to the OS. When the app ends the context switches back to the OS. –  Guy Coder yesterday
3  
See also "syscall". –  Raphael yesterday
4  
1  
If the comments and answers do not answer your question to your understanding or satisfaction, then please ask for more info as a comment and explain what you are thinking or where you are lost, or what specifically you need more detail on. –  Guy Coder yesterday
1  
show 1 more comment

5 Answers

No. The operating system does not mess around with the program's code injecting new code into it. That would have a number of disadvantages.

  1. It would be time-consuming, as the OS would have to scan through the entire executable making its changes. Normally, part of the executable are only loaded as needed. Also, inserting is expensive as you have to move a load of stuff out of the way.

  2. Because of the undecidability of the halting problem, it's impossible to know where to insert your "Jump back to the OS" instructions. For example, if the code includes something like while (true) {i++;}, you definitely need to insert a hook inside that loop but the condition on the loop (true, here) could be arbitrarily complicated so you can't decide how long it loops for. On the other hand, it would be very inefficient to insert hooks into every loop: for example, jumping back out to the OS during for (i=0; i<3; i++) {j=j+i;} would slow down the process a lot. And, for the same reason, you can't detect short loops to leave them alone.

  3. Because of the undecidability of the halting problem, it's impossible to know if the code injections changed the meaning of the program. For example, suppose you use function pointers in your C program. Injecting new code would move the locations of the functions so, when you called one through the pointer, you'd jump to the wrong place. If the programmer was sick enough to use computed jumps, those would fail, too.

  4. It would play merry hell with any anti-virus system, since it would change virus code, too and muck up all your checksums.

You could get around the halting-problem problem by simulating the code and inserting hooks in any loop that executes more than a certain fixed number of times. However, that would require extremely expensive simulation of the whole program before it was allowed to execute.

Actually, if you wanted to inject code, the compiler would be the natural place to do it. That way, you'd only have to do it once but it still wouldn't work for the second and third reasons given above. (And somebody could write a compiler that didn't play along.)

There are three main ways that the OS regains control from processes.

  1. In co-operative systems, there's a yield function that a process can call to give control back to the OS. Of course, if that's your only mechanism, you're reliant on the processes behaving nicely and a process that doesn't yield will hog the CPU until it terminates.

  2. To avoid that problem, a timer interrupt is used, which is handled by the OS. So, periodically, the OS gets control back whether the application wants it or not.

  3. Every time a process tries to read from a file or interact with the hardware in any other way, it's asking the OS to do work for it. When the OS is asked to do something by a process, it can decide to put that process on hold and start running a different one. This might sound a bit Machiavellian but it's the right thing to do: disk I/O is slow so you may as well let process B run while process A is waiting for the spinning lumps of metal to move to the right place. Network I/O is even slower. Keyboard I/O is glacial because people are not gigahertz beings.

share|improve this answer
3  
Can you develop more on you last 2. point? I'm curious about this question, and am feeling the explanation is skipped here. It seems to me like the question is "how the OS take back the CPU from process" and your answer tells "The OS handles it". but how? Take the infinite loop in your first example: how does it not freeze the computer? –  BiAiB yesterday
2  
Some OSs do, most OS at least mess about with the code to do "linking", so the program can be loaded at any address –  Ian Ringrose yesterday
1  
@BiAiB The key word here is "interrupt". The CPU is not just something that processes a given stream of instructions, it can also be interrupted asynchronously from a separate source - most importantly for us, I/O and clock interrupts. Since only kernel-space code can handle interrupts, Windows can be sure to be able to "steal" work from any running process any time it wants to. The interrupt handlers can execute whatever code they want to, including "store the CPU's registers somewhere and restore them from here (another thread)". Extremely simplified, but that's the context switch. –  Luaan yesterday
    
Adding to this answer; the style of multitasking referred to in points 2 and 3 is called "preemptive multitasking", the name refers to the OS's ability to preempt a running process. Cooperative multitasking was used frequently on older operating systems; on Windows at least preemptive multitasking wasn't introduced until Windows 95. I've read of at least one industrial control system in use today that still uses Windows 3.1 solely for its real-time cooperative multitasking behavior. –  Jason C 8 hours ago
    
(Well, it seems 2.1 had limited support, and it was rather fuzzy and strange with increasingly better support up to '95.) –  Jason C 8 hours ago
add comment

While David Richerby's answer is a good one, it does sort of glaze over how modern operating systems halt existing programs. My answer should be accurate for the x86 or x86_64 architecture, which is the only one commonly in use for desktops and laptops. Other architectures should have similar methods of achieving this.

When the operating system is starting up, it sets up an interrupt table. Each entry of the table points to a bit of code inside the operating system. When interrupts happen, which is controlled by the CPU, it looks at this table and calls the code. There are various interrupts, such as dividing by zero, invalid code, and some operating system defined ones.

This is how the user process talks to the kernel, such as if it wants to read/write to the disk or something else that the operating system kernel controls. An operating system will also set up a timer that calls an interrupt when it finishes, so the running code is forcibly changed from the user program to the operating system kernel, and the kernel can do other things such as queue up other programs to run.

From memory, when this happens the operating system kernel has to save where the code was, and when the kernel has finished doing what it needs to do it restores the previous state of the program. Thus the program doesn't even know that it was interrupted.

The process can't change the interrupt table for two reasons, the first is that it is running in a protected environment so if it tries to call certain protected assembly code then the cpu will trigger another interrupt. The second reason is virtual memory. The location of the interrupt table is at 0x0 to 0x3FF in real memory, but with user processes that location is usually not mapped, and trying to read unmapped memory will trigger another interrupt, so without the protected function and the ability to write to real RAM, the user process can't change it.

share|improve this answer
3  
The interrupts aren't defined by the operating system, they are given by hardware. And most current architectures have special instructions to call the operating system. i386 used a (software generated) interrupt for this, but it isn't done that way anymore on its successsors. –  vonbrand yesterday
1  
I know that the interrupts are defined by the cpu, but the kernel sets up the pointers. I possibly explained it badly. I also thought that linux used int 9 to talk to the kernel still, but maybe there are better ways now. –  Programmdude 12 hours ago
    
This is a fairly misleading answer although the notion that preemptive schedulers are driven by timer interrupts is correct. First it's worth noting that the timer is in hardware. Also to clarify that "save ... restore" process is called a context switch and mostly involves saving all of the CPU registers (which includes the instruction pointer), among other things. Also, processes can effectively change interrupt tables, this is called "protected mode", which also defines virtual memory, and has been around since the 286 - a pointer to the interrupt table is stored in a writable register. –  Jason C 8 hours ago
    
(Also even the real mode interrupt table has been relocatable - not locked to the first page of memory - since the 8086.) –  Jason C 8 hours ago
add comment

The OS kernel get the control back from the running process due to CPU clock interrupt handler, not by injecting code into the process.

You should read about interrupts to get more clarification about how they works and how OS kernel handle them and implement different features.

share|improve this answer
    
Not just the clock interrupt: any interrupt. And also mode change instructions. –  Gilles yesterday
add comment

There is a method similar to what you describe: co-operative multitasking. The OS does not insert instructions, but each program must be written to call OS functions which may choose to run another of the cooperative processes. This has the disadvantages you describe: one program crashing takes out the whole system. Windows up to and including 3.0 worked like this; 3.0 in "protected mode" and above did not.

Pre-emptive multitasking (the normal kind these days) relies on an external source of interrupts. Interrupts override the normal flow of control and usually save the registers out somewhere, so the CPU can do something else and then transparently resume the program. Of course, the operating system can change the "when you leave interrupts resume here" register, so it resumes inside a different process.

(Some systems do rewrite instructions in a limited way on program load, called "thunking", and the Transmeta processor dynamically recompiled to its own instruction set)

share|improve this answer
add comment

I think the closest real-world example to what you describe is one of the techniques used by VMware, Full virtualization using binary translation.

VMware acts as a layer underneath one or more simultaneously executing operating systems on the same hardware.

Most of the instructions being executed (e.g. in ordinary applications) can be virtualized using the hardware, but an OS kernel itself makes use of instructions that cannot be virtualized, because if the machine code of the guess OS were executed unmodified it would "break out" of the control of the VMware host. For example, a guest OS would need to run in the most privileged protection ring, and set up the interrupt table. If it were allowed to do that, VMware would have lost control of the hardware.

VMware rewrites those instructions in the OS code before executing it, replacing them with jumps into VMware code that simulates the desired effect.

So this technique is somewhat analogous to what you describe.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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