CPU寄存器和多任务 [英] CPU Registers and Multitasking

查看:105
本文介绍了CPU寄存器和多任务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在学习Assembly,我对CPU寄存器与多任务处理的工作方式感到困惑.因此在多任务系统中. CPU可以随时暂停某个程序的执行并运行另一个程序.那么在此步骤中如何保存寄存器值?寄存器是否被压入堆栈或以其他任何方式?

I'm currently learning Assembly and I'm confused how the CPU registers work with Multitasking. So in a Multitasking System. CPU can pause the execution of a certain program at any time and run another program. So how are the register values preserved during this step ? Are the registers pushed to stack or any other way ?

推荐答案

CPU寄存器如何与多任务一起工作.

how the CPU registers work with Multitasking.

CPU基本上可能无法与多任务一起使用,任务切换可能(并且已经)在软件中实现.某些CPU(intel x86)可能具有硬件状态(TSS https://en.wikipedia.org/wiki/Task_state_segment )和TR(任务寄存器),以将状态从一个任务自动更改为另一个任务. (TSS仍可用于切换保护环 ring0/ring3;但不能切换任务. )

CPU basically may not work with multitasking, task switch may be (and is) implemented in software. Some CPU (intel x86) may have hardware state (TSS https://en.wikipedia.org/wiki/Task_state_segment) and TR (task register) to atomically change state from one task to another. (TSS may still be used to switch protection rings ring0/ring3; but not to switch tasks.)

因此,在多任务系统中,CPU可以随时暂停某个程序的执行并运行另一个程序.

So in a Multitasking System, CPU can pause the execution of a certain program at any time and run another program.

差不多.

在大多数能够运行操作系统和用户空间任务的CPU中,有 中断 ,用于某些外部事件(来自硬件,中断请求,IRQ的信号)的情况,以暂停当前代码(任务)的执行并跳转至几个特殊的内核功能之一,称为中断处理程序(ISR,中断服务程序).

In most CPU, capable of running OS and user-space tasks, there are interrupts which are used in case of some external event (signal from hardware, interrupt request, IRQ) to pause execution of current code (task) and to jump to one of several special kernel functions, called interrupt handlers (ISR, interrupt service routine).

那么在此步骤中如何保存寄存器值?

So how are the register values preserved during this step ?

大多数寄存器在中断输入时保持不变.一些在中断进入过程中由CPU保存.

Most registers just stays untouched on interrupt entry. Some are preserved by CPU in interrupt entry process.

中断支持机制是在CPU内部实现的,它确实将当前任务的一些 cpu寄存器保存到某个空间(是的,它堆栈,x86 cpu会推送* FLAGS,CS,IP). CPU跳转到在中断向量表/中断描述符表(IDT)数组(在IVT的情况下存储在特殊的内存位置或由IVT指向IDT专用的CPU寄存器IDT);对于IRQ 1,它将选择记录号1(例程1);对于IRQ 20,它将选择例程20.

Interrupt support mechanism is implemented inside CPU, it does save some cpu registers of current task to some space (yes, it can save to stack, x86 cpu pushes *FLAGS, CS, IP). CPU jumps to these routines, registered in Interrupt Vector Table / Interrupt Descriptor Table (IDT) arrays (stored at special memory location in case of IVT or pointed by special CPU register IDT for IDT); for IRQ 1 it will select record number 1 (routine 1); for IRQ 20 it will select routine 20.

寄存器被压入堆栈还是以其他任何方式?

Are the registers pushed to stack or any other way ?

两者.有些是在中断时由CPU推送的,有些是由中断处理程序的命令推送的. (还有在内核模式下更改EIP的代码...)

Both. Some are pushed by CPU in interrupt, and some are pushed by commands of interrupt handler. (And there is also code to change EIP in kernel mode...)

ISR例程知道CPU保存了什么,如果它想使用更多的寄存器(基本上是想要的),它将推入堆栈(或保存到其他位置)其他用户寄存器,然后执行其中断工作,然后恢复手动保存的寄存器,然后使用特殊命令从中断中退出(在x86字中为 iret ,它将从堆栈中重新加载"CS:IP和FLAGS").如果堆栈中未更改原始IP,则CPU将继续执行原始用户代码(原始任务),并且所有寄存器均保持不变.如果作者或中断处理程序需要,他可以在执行iret之前更改堆栈中的IP地址,因此它将在其他位置返回(它可能返回内核模式或某些任务或重新启动PC等).

ISR routine knows what was saved by CPU, and if it want to use some more registers (it basically wants), it will push to stack (or save to other place) other user registers, then do its interrupt work, then restore manually saved registers back, and then will exit from interrupt using special command (iret in x86 word, it will reload "CS:IP and FLAGS" back from stack). If original IP was untouched in the stack, CPU will continue execution of original user code (original task), and it will have all registers unchanged. If author or interrupt handler wants, he may change IP address in the stack before doing iret, so it will return in other place (it may return to kernel mode or to some task or reboot PC and so on).

更改当前正在运行的任务(上下文切换, Wiki sched_yield (在Linux世界中).

Changing current running task (context switch, wiki, osdev) is one of problems which may be done using interrupts. There are basically two kinds of context switching: involuntary (when the task just runs and do not want to leave CPU) and voluntary (when task asks OS to do the context switch, either because current task may no run further or if current task is polite and gives other tasks chance to run - sched_yield in linux world).

非自愿上下文切换通常是在定期计时器中断的帮助下完成的.几年前,该计时器每隔10、1或3毫秒生成一些特定的IRQ(计时器/RTC IRQ).并且计时器中断处理程序调用操作系统调度程序来确定当前任务运行时间是否过多(超出其时间段,即分时),还是有一些优先级更高的任务可以运行.

Involuntary context switch is usually done with help of periodic timer interrupt. Several years ago this timer used to generate some specific IRQ (timer/RTC IRQ) every 10, 1 or 3 milliseconds; and timer interrupt handler calls OS scheduler to decide is current task runs for too much time (exceeds its time slice, the quantum of time-sharing) or is there some task with higher priority ready to run.

自愿上下文切换通常在系统调用的帮助下完成(当OS使用特权分离时,在ring3中运行用户空间代码,在ring0中运行内核空间代码-阻止-阻止当前任务运行;从

Voluntary context switch is usually done with help of system call (when OS used privilege separation, runs user-space code in ring3 and kernel-space code in ring0 - concept of protection rings), which is special CPU instruction to switch between privilege levels (it may be / was implemented with software-generated interrupts; int 80h in older linux/BSD). User-space code asks kernel to do some work, for example read from file or socket or write to file. It also may ask kernel to run scheduler to switch to other task if there is any - with sched_yield syscall. If syscall code decides that request need some time and the task can't run further before the request is done (system call blocks - blocks current task from running; switches it state from TASK_RUNNING), it will also call OS scheduler.

OS调度程序可以使当前任务保持运行状态(如果它处于可运行状态),或者可以决定切换到其他任务(实际上是切换到其他任务的内核模式;还会有从系统返回的调用,以恢复任务的CS :IP + FLAGS),然后使用switch_to asm宏进行操作:

OS scheduler may keep current task as running (if it is in runnable state) or may decide to switch to other task (actually to kernel-mode of other task; there also will be return-from-syscall to restore task's CS:IP+FLAGS) and do it using switch_to asm macro: http://lxr.free-electrons.com/source/arch/x86/include/asm/switch_to.h?v=4.6#L27:

 33         /*                                                              \
 34          * Context-switching clobbers all registers, so we clobber      \
 35          * them explicitly, via unused output variables.                \
 36          * (EAX and EBP is not listed because EBP is saved/restored     \
 37          * explicitly for wchan access and EAX is the return value of   \
 38          * __switch_to())                                               \
 39          */                                                             \
 40         unsigned long ebx, ecx, edx, esi, edi;                          \
 41                                                                         \
 42         asm volatile("pushfl\n\t"               /* save    flags */     \
 43                      "pushl %%ebp\n\t"          /* save    EBP   */     \
 44                      "movl %%esp,%[prev_sp]\n\t"        /* save    ESP   */ \
 45                      "movl %[next_sp],%%esp\n\t"        /* restore ESP   */ \
 46                      "movl $1f,%[prev_ip]\n\t"  /* save    EIP   */     \
 47                      "pushl %[next_ip]\n\t"     /* restore EIP   */     \
 48                      __switch_canary                                    \
 49                      "jmp __switch_to\n"        /* regparm call  */     \
 50                      "1:\t"                                             \
 51                      "popl %%ebp\n\t"           /* restore EBP   */     \
 52                      "popfl\n"                  /* restore flags */     \
 53                                                                         \

如果唯一的非睡眠用户任务进入睡眠状态,则没有可见的任务可供运行.但实际上,存在一个隐含的任务,其pid为0,有时也称为swapper或 idle ,优先级最低,并且随时可以运行.它将循环运行一些特殊的CPU指令以冷却CPU- HLT ;它还可能会对事件/对调度程序的调用进行一些检查,以查找可运行的任务.

If there was the only non-sleeping user task and it goes to sleep, there are no visible tasks ready to be run. But in fact there is invisible task with pid 0, sometimes called swapper or idle, which has lowest priority and always ready to run. It will run some special CPU instruction in loop to cool down the CPU - HLT; it may also do some checks for events / calls to scheduler to find runnable tasks.

一些奇怪的实时操作系统(名称以"V"开头并以版本5结尾)没有用户空间/内核空间的分隔和隔离(所有代码都在环0中运行)可能实现了自愿的上下文切换,而没有系统调用或软件中断;但通常会致电调度程序.

Some strange realtime OS (with name starting from "V" and ending in version 5) without user-space/kernel-space separation and isolation (all code runs in ring 0) may implement voluntary context switch without syscall or software interrupts; but by usual call to scheduler.

有用的链接:

  • https://en.wikibooks.org/wiki/X86_Assembly/Advanced_Interrupts
  • http://wiki.osdev.org/Interrupt
  • http://wiki.osdev.org/Context_Switching
  • http://www.informit.com/articles/article.aspx?p=364068 - How Multitasking Works at the Hardware Level, 2005, chapter of very good book "Unabridged Pentium 4, The: IA32 Processor Genealogy".
  • Task management on x86 mentions "Protected Mode Software Architecture" book and "Understanding the Linux Kernel, 3rd Ed.", Bovet, chapter 3 Processes, 3.3.2. Task State Segment.
  • http://wiki.osdev.org/Task_State_Segment of hardware task switching

这篇关于CPU寄存器和多任务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆