操作系统 context switch
时间: 2023-10-06 15:10:42 浏览: 32
操作系统 context switch(上下文切换)是指在一个进程执行时,由于需要等待某些事件的发生(如 I/O 完成、定时器到期等),操作系统需要停止当前进程的执行,保存其执行状态,切换到另一个进程的执行状态,使其继续执行。这个过程中,操作系统需要保存当前进程的所有执行状态(CPU 寄存器、程序计数器等),以便后续再次执行该进程时能够恢复到之前的执行状态。
Context switch 是操作系统的核心机制之一,它可以实现多任务并发执行,提高系统的资源利用率和响应时间。但是,context switch 的开销非常大,它需要操作系统进行大量的寄存器保存和恢复操作,而且需要频繁访问内存,因此会降低系统的性能。为了减少 context switch 的开销,操作系统设计者需要采用一系列优化技术,如进程优先级调度、抢占式调度、时间片轮转等。
相关问题
context switch
上下文切换(Context Switch)是指在操作系统中,当一个进程或线程被暂停执行,而另一个进程或线程被调度并开始执行时,系统需要保存当前进程或线程的上下文信息,并加载下一个进程或线程的上下文信息。这个过程被称为上下文切换。上下文切换的目的是实现多任务并发执行,提高系统的资源利用率和响应性能。
在Windows系统中,可以使用性能计数器来监控上下文切换的变化趋势。可以添加System\Context Switches/sec或Thread(_Total)\Context Switches/sec计数器来进行性能分析。此外,还可以使用工具如Process Explorer来查看进程的上下文切换情况,可以添加Context Switches和Context Switches Delta列来显示上下文切换的信息。进程的属性中的Threads标签页也可以查看线程对应的上下文切换情况。
在一些特定的代码中,也可以通过一些函数或指令来进行上下文切换。例如,在某些代码中可以使用fpsimd_thread_switch、tls_thread_switch、hw_breakpoint_thread_switch和contextidr_thread_switch等函数或指令来进行上下文切换,这些与硬件跟踪相关的操作可以实现特定的上下文切换功能。
#### 引用[.reference_title]
- *1* *2* [Context Switches上下文切换性能详解](https://blog.csdn.net/u011391839/article/details/107493267)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item]
- *3* [进程切换(context_switch)代码分析:基本逻辑](https://blog.csdn.net/zdy0_2004/article/details/54871189)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item]
[ .reference_list ]
文件系统的void SysTick_Handler(void) { g_timeMilliseconds++; } 和freertos里port.c的void xPortSysTickHandler( void ) { /* The SysTick runs at the lowest interrupt priority, so when this interrupt executes all interrupts must be unmasked. There is therefore no need to save and then restore the interrupt mask value as its value is already known - therefore the slightly faster vPortRaiseBASEPRI() function is used in place of portSET_INTERRUPT_MASK_FROM_ISR(). / //g_timeMilliseconds++; vPortRaiseBASEPRI(); { / Increment the RTOS tick. / if( xTaskIncrementTick() != pdFALSE ) { / A context switch is required. Context switching is performed in the PendSV interrupt. Pend the PendSV interrupt. */ portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } } vPortClearBASEPRIFromISR(); }重复定义了怎么解决,给我具体的解决方法带代码
如果您遇到了重复定义的问题,可以使用如下方法解决:
1. 将 `g_timeMilliseconds` 定义为一个全局变量,然后在两个函数中都使用它,而不是在 `SysTick_Handler` 函数中直接对它进行操作。
例如,您可以在某个头文件中定义 `g_timeMilliseconds`:
```c
// 在头文件中定义全局变量
extern uint32_t g_timeMilliseconds;
```
然后在一个 C 文件中定义这个全局变量:
```c
#include "header.h"
uint32_t g_timeMilliseconds = 0;
```
然后在 `SysTick_Handler` 函数中,将其修改为:
```c
void SysTick_Handler(void) {
g_timeMilliseconds++;
}
```
在 `xPortSysTickHandler` 函数中,您可以通过 `g_timeMilliseconds` 全局变量来获取当前时间的值,而不需要在该函数中对其进行操作。例如:
```c
void xPortSysTickHandler( void ) {
/* Increment the RTOS tick. */
if( xTaskIncrementTick() != pdFALSE ) {
/* A context switch is required. Context switching is performed in the PendSV interrupt. Pend the PendSV interrupt. */
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
}
}
```
2. 如果您仍然想要在 `xPortSysTickHandler` 函数中对时间进行操作,您可以将其代码合并到 `SysTick_Handler` 函数中,而不需要在 `xPortSysTickHandler` 函数中重新定义。例如:
```c
void SysTick_Handler(void) {
g_timeMilliseconds++;
/* Increment the RTOS tick. */
if( xTaskIncrementTick() != pdFALSE ) {
/* A context switch is required. Context switching is performed in the PendSV interrupt. Pend the PendSV interrupt. */
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
}
}
```
然后在 `xPortSysTickHandler` 函数中,您可以删除对 `g_timeMilliseconds` 的操作,只保留对 RTOS tick 的操作:
```c
void xPortSysTickHandler( void ) {
/* Increment the RTOS tick. */
if( xTaskIncrementTick() != pdFALSE ) {
/* A context switch is required. Context switching is performed in the PendSV interrupt. Pend the PendSV interrupt. */
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
}
}
```