Steps in Context Switching

南笙酒味 提交于 2019-11-27 09:07:03

问题


I am asked to describe the steps involved in a context switch (1) between two different processes and (2) between two different threads in the same process.

  1. During a context switch, the kernel will save the context of the old process in its PCB and then load the saved context of the new process scheduled to run.
  2. Context switching between two different threads in the same process can be scheduled by the operating system so that they appear to execute in parallel, and is thus usually faster than context switches between two different processes.

Is this too general or what would you add to explain the process clearer?


回答1:


It's much easier to explain those in reverse order because a process-switch always involves a thread-switch.

A typical thread context switch on a single-core CPU happens like this:

  1. All context switches are initiated by an 'interrupt'. This could be an actual hardware interrupt that runs a driver, (eg. from a network card, keyboard, memory-management or timer hardware), or a software call, (system call), that performs a hardware-interrupt-like call sequence to enter the OS. In the case of a driver interrupt, the OS provides an entry point that the driver can call instead of performing the 'normal' direct interrupt-return & so allows a driver to exit via the OS scheduler if it needs the OS to set a thread ready, (eg. it has signaled a semaphore).

  2. Non-trivial systems will have to initiate a hardware-protection-level change to enter a kernel-state so that the kernel code/data etc. can be accessed.

  3. Core state for the interrupted thread has to be saved. On a simple embedded system, this might just be pushing all registers onto the thread stack and saving the stack pointer in its Thread Control Block (TCB).

  4. Many systems switch to an OS-dedicated stack at this stage so that the bulk of OS-internal stack requirements are not inflicted on the stack of every thread.

  5. It may be necessary to mark the thread stack position where the change to interrupt-state occurred to allow for nested interrupts.

  6. The driver/system call runs and may change the set of ready threads by adding/removing TCB's from internal queues for the different thread priorities, eg. network card driver may have set an event or signaled a semaphore that another thread was waiting on, so that thread will be added to the ready set, or a running thread may have called sleep() and so elected to remove itself from the ready set.

  7. The OS scheduler algorithm is run to decide which thread to run next, typically the highest-priority ready thread that is at the front of the queue for that priority. If the next-to-run thread belongs to a different process to the previously-run thread, some extra stuff is needed here, (see later).

  8. The saved stack pointer from the TCB for that thread is retrieved and loaded into the hardware stack pointer.

  9. The core state for the selected thread is restored. On my simple system, the registers would be popped from the stack of the selected thread. More complex systems will have to handle a return to user-level protection.

  10. An interrupt-return is performed, so transferring execution to the selected thread.

In the case of a multicore CPU, things are more complex. The scheduler may decide that a thread that is currently running on another core may need to be stopped and replaced by a thread that has just become ready. It can do this by using its interprocessor driver to hardware-interrupt the core running the thread that has to be stopped. The complexities of this operation, on top of all the other stuff, is a good reason to avoid writing OS kernels :)

A typical process context switch happens like this:

  1. Process context switches are initiated by a thread-context switch, so all of the above, 1-9, is going to need to happen.

  2. At step 5 above, the scheduler decides to run a thread belonging to a different process from the one that owned the previously-running thread.

  3. The memory-management hardware has to be loaded with the address-space for the new process, ie whatever selectors/segments/flags/whatever that allow the thread/s of the new process to access its memory.

  4. The context of any FPU hardware needs to be saved/restored from the PCB.

  5. There may be other process-dedicated hardware that needs to be saved/restored.

On any real system, the mechanisms are architecture-dependent and the above is a rough and incomplete guide to the implications of either context switch. There are other overheads generated by a process-switch that are not strictly part of the switch - there may be extra cache-flushes and page-faults after a process-switch since some of its memory may have been paged out in favour of pages belonging to the process owning the thread that was running before.




回答2:


I hope that I can provide more detailed/clear picture.

First of all, OS schedules threads, not processes, because threads are the only executable units in the system. Process switch is just a threads switch where threads belongs to different processes. Due to this in general switch procedure is common.

  1. Scheduler should be invoked. There are three basic scenarious:

    • Involuntary switch. Some external to your thread event has happened which have affected schedulling. For example, timer ring has woken up a thread with high priority, HDD controller has reported that requested part of file has been read into the memory, and thread waiting it can continue its execution, system timer has told to the kernel that your thread had ran out of its time quantum, etc.
    • Voluntary. Thread explicitly request rescheduling by system call. For example requested a yield, or requested a sleep, or requested to wait until mutex will be released.
    • Semi-voluntary. Thread implicitly triggered rescheduling performing some unrelated system call. For example, it asked a system to read a file. OS has routed this request to the disk controller and to not waste time on busy waiting the result decided to switch to another thread.
  2. In all cases, to be able to perform thread switch, control should be passed to the kernel. In case of involuntary switches such control pass is performed by interrupt, in the case of voluntary (and semi-voluntary) control is passed via system call.

  3. In both cases, entering into the kernel is CPU-assisted. Processor performs permissions check, remember a point at which thread was preempted (to be able to resume it in future), switch from user part of thread stack to its kernel counterpart, and passes a control to a predefined and well-known point in the kernel code.

  4. The first action which kernel performs is saving of the content of CPU registers, which kernel will reuse for its own tasks. Usually kernel uses only general purpose CPU registers and saves them by pushing into stack.
  5. Then kernel handles a primary request -- handle interrupt, or prepares file read request or perform timer setup.
  6. At some point of request handling, kernel performs an action that either affect the state of the current thread (decided that there is nothing todo in this thread and we should wait for something) or affect the state of another thread(s) (new thread became runable as a result of interrupt received or due to the mutex released, etc.).
  7. Kernel invokes a scheduller. Scheduler has to made two decision. First one is about what to do with a current thread. Should it be blocked? If so, into what wait queue it should be placed? If thread is switched involuntary it is placed into the end of runqueue, if thread is blocked, because it waits for somethins, it is placed into one of the waitqueues. Second decision is about which thread to run next.
  8. Once both decisions are made, scheduller performs context swicth passing to it two parameters -- thread control block of the current and next threads.
  9. Context switch itself consist from three main steps. At the first one, kernel figures out what CPU registers thread actually uses and saves their content either on the stack or in TCB of outgoint thread. If thread does not use FPU and SSE registers (exaple for IA-32 platform) their content will not be saved.
  10. The second step is a heart of context switch. Kernel pushes current instruction pointer to the stack and value of stack pointer saves in TCB of outgoing thread. Then it loads into CPU new stack pointer from TCB of incoming thread and pops instruction pointer from its top. That it! New active stack means new active thread. Starting from this point the rest of the system will think that it works in the context of incoming thread.
  11. At the third step kernel figures out what registers actually used by incoming thread and loads their previously saved content (look at step 1) back into CPU.
  12. Then kernel checks does the both threads (incoming and outgoing) belong to the same process or not. If they belong to different processes (the case which peoples call process switch), kernel reset the current address space pointing MMU to the new set of virtual to physical address translation tables. As part of this process CPU flushes Translate Lookaside Buffer (TLB) which caches virtual to physical address traslation rules. New virtual address space means that previously cached rules now incorrect. Note that this is the only step in the entire set of context switch actions which care about processes!
  13. Kernel prepares Thread Local Storage for the incoming thread. For example, maps respective memory pages to the specified addresses or for example on IA-32 common approach is to load new segment which point to the TLS data of the incoming thread.
  14. Finally kernel loads into CPU address of kernel part of the incoming thread. After this, every new kernel invocation will use kernel part of stack of incoming thread, and will not corrupt the data stored on the stack of outgoing thread.
  15. One another step which can be performed by kernel is reprogramming of system timer. Doing this kernel asks the timer to ring and pass control to the kernel after some time will be passed. This time period is called quantum of time of the thread.
  16. Finally kernels likes to collect statistics during context switches including soch info as how much CPU time threads consumes, how may context switches happens in the system in the unit of real time, how many times threads were invoked, how many times they have released CPU voluntary and involuntary, how many times they were ran out of they quantum. Part of that statistics is used then by scheduller, which attemps to make more optimal decisions. Another purpose of statistics is delivery to the system administrators and users to show them what going on under the hood of the system.
  17. Thread switch can be considered as accomplished at this point and kernel continues previously interrupted system actions. For example thread which was waiting for file read inspects read result in the memory and handles it. Or a thread which was blocked on the mutex in the middle of some big system activity continues that activity.
  18. Finally, later or sooner thread finishes its system activities and wants to return back to the user mode to continue its primary task, for which it was initially employed. At this point kernel pops from the kernel stack content of general-purpose registers which was previously saved during enter into the kernel and asks CPU to perform return into the user mode.
  19. CPU captures the values of instruction pointer and stack pointer, which were previously saved during enter into the kernel mode and restores them. Doing this it also switches thread back from kernel part of its stack to the user part of the stack. Finally CPU resets the permissions of the code which will be executed to a more limited set (prohibits use of special system instructions for example, or prohibits access to the kerel code and data). Finally CPU passes control back to the point where thread was initially preempted. In the case of system call thread will proceed in the point where system call was invoked, by capturing and handling its result. In the case of preemption by interrupt, thread will continue its execution exactly in the same point in which it was when interrupt has happened. In that case it even will be completely unaware that it was interrupted.

Some summary notes:

  1. Kernel schedules and executes only threads, not processes. Due to this context swicth happens between threads.
  2. Procedure of Context switch between treads belonging to different processes is essentially the same as between threads which belongs to the same process. There is only one additional step in the first case - loading of new virtual address space (which leads to the TLB flush).
  3. Context of threads are stored either in the kernel part of the stack of thread or in the thread TCB (not in PCB!).
  4. Threads switch introduces performance penalty. There is significant direct cost of threads switch. And even much bigger inderect cost created by cache pollution and TLB flush (if virtual address space was reloaded during switch).



回答3:


  1. In a switch, the state of process currently executing must be saved somehow, so that when it is rescheduled, this state can be restored.
  2. The process state includes all the registers that the process may be using, especially the program counter, plus any other operating system specific data that may be necessary. This is usually stored in a data structure called a process control block (PCB) or switchframe.
  3. The PCB might be stored on a per-process stack in kernel memory (as opposed to the user-mode call stack), or there may be some specific operating system defined data structure for this information. A handle to the PCB is added to a queue of processes that are ready to run, often called the ready queue.
  4. Since the operating system has effectively suspended the execution of one process, it can then switch context by choosing a process from the ready queue and restoring its PCB. In doing so, the program counter from the PCB is loaded, and thus execution can continue in the chosen process. Process and thread priority can influence which process is chosen from the ready queue (i.e., it may be a priority queue).

(Source: Context switch)




回答4:


1.Save the context of the process that is currently running on the CPU. Update the process control block and other important fields.

2.Move the process control block of the above process into the relevant queue such as the ready queue, I/O queue etc.

3.Select a new process for execution.

4.Update the process control block of the selected process. This includes updating the process state to running.

5.Update the memory management data structures as required.

6.Restore the context of the process that was previously running when it is loaded again on the processor. This is done by loading the previous values of the process control block and registers.



来源:https://stackoverflow.com/questions/7439608/steps-in-context-switching

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!