I've been studying unix/linux system fundamentals and in particular, how a list of tasks or processes gets handled in a modern computer system.
I've found a lot of resources that give what appears to be a standard explanation of the context switching that the kernel does and how signals (SIGXXX) are handled:
- A process runs for a set amount of time or until an interrupt is received
- The kernel unloads the process from running memory (cache), stows data about its context in memory elsewhere to load the next process that needs CPU time.
- If a signal (SIGXXX) is waiting for the process, the kernel tries to invoke the appropriate handler in the process. If none exists, the process is not loaded back again (killed).
- The new process is loaded in to memory and runs; the cycle continues
(Please let me know if this understanding is incorrect)
The thing I've been struggling with is, if this is all occurring on a single-core, single-thread CPU, what's physically running the scheduler? I'm missing something really simple, but I'm stuck in this chicken-or-the-egg kind of thinking.
And further, in modern systems that have multiple cores, threads, and lots of CPU resources available, does the scheduler consume a core by itself to run?
I've read a lot of articles about the different process schedulers, the original O(n), the newer O(1) introduced in 2.6 and beyond, and the CFS scheduler that (I think?) is used in most Linuxes nowadays. All of them talk about how they are prioritizing and queing processes, and none of them go in to detail about how and when the scheduler is actually running to accomplish all its tasks.
Is the scheduler sharing CPU time? Shuffling itself in and out of the CPU somehow? If so, how does the CPU know when to stop a process and let the scheduler run to do its thing?