上下文切换与多处理器
对于进程有两个幻觉:一认为自己独享内存;二以为自己独享处理器。我们对于一台机器上的多个进程的幻觉是感觉他们是同时运行。
我们来依次解释下上面的三个幻觉:
关于独享内存不是我们的重点,简单说说。独享内存是指我们每个进程都独享虚拟内存。而虚拟内存地址最终是通过MMU翻译成实际的物理地址。这样做只是为了提供一种逻辑上的连续性,屏蔽内存碎片或是规避因内存有限而扩展到硬盘的各种问题,这样不用考虑实际的的限制从而使应用程序开发变得容易。还有一个值得注意的问题是在这个虚拟内存中如果这个进程是多线程的,那么将共享改空间,除了各自的堆栈、寄存器和所谓的虚拟处理器。这样会导致一个问题就是多个线程的stacksize对进程栈空间的要求呈线性增长,与复杂的多层级递归运算类似,导致stackoverflow。这也是好多语言比如Java的线程模型要求线程创建时指定好stacksize大小的原因。
以前是单处理器的机器,后来因为通过单纯的提高处理器主频,已经无法明显提升系统整体性能。实在没办法了,科学家们就想啊想啊,就相出了多核处理器。这样的话处理线程级的多任务,就可以实现真正的并行了。但问题是处理器的核数远小于需要并行的任务数量。有许多因素都客观限制处理器核数。那要完成多个进程同时执行的幻觉就只能通过来回的轮番执行,快速切换。这就到上下文切换的话题了。
关于上下文切换我仅仅参考linux内核的实现从技术角度来解释:
在linux中一个叫做task_struct结构体代表一个线程,linux调度器会对一个结构体:sched_entity结构体感兴趣并对其进行调度,而它正好嵌入到task_struct中。因此对可以看出linux调度是线程级的。那具体怎么调度呢?
Linux用红黑树存所有可运行的进程(注意是可运行),使用等待队列wait_queue记录休眠(被阻塞)线程。用一个例子来介绍调度和上下文切换的细节,例如网卡产生一个中断通知有网络数据,执行中的线程阻塞(从执行状态剥离并放入等待队列),然后再到红黑树里面选一个来执行。这个过程的详细过程是:虚拟内存映射和处理器状态均要切换到新线程,前一个线程寄存器、栈信息还有其他状态信息被保存。而新线程的栈信息和寄存器信息被恢复,刚好是反操作。我们把上述过程叫做上下文切换。等到网络数据读取就绪,在等待队列中的线程又被唤醒,接着放入红黑树中,成为可执行态,等待被执行。
多处理器就是一台机器具有多个处理器。他的主流架构叫做对称多处理器(SMP),这些处理器共享内存,共用一个系统,程序可以并行执行在每一个处理器上。拿多核处理器来说,通过一个核心执行一个线程,操作系统通过指令分派让一个核心负责一个程序执行,达到真正意义上的并行。目前的手机尤其是android手机通过添加核心数来提升运行速度。这确实可以得到提高。但是在软件角度还受到几方面限制:一是调度算法针对核心数优化,以充分利用多核优势;二是程序的并行性,如果程序是单线程再多核同时也只能跑在一个上面,其他的却白白浪费;还有就是,增加核心数和处理能力并非成线性关系。
文章转自 并发编程网-ifeve.com
仔细揣摩了一段时间. 系统调用过程,用户进程进入内核态,进程栈进入内核态栈, cpu进入内核态,cpu用户态各寄存器的值保存到内核态栈,执行内核态代码. 执行完从内核态返回到用户态,包括进程栈返回到用户态栈,cpu返回到用户态,cpu各寄存器的值用之前保存在内核态栈的值还原. 内核在执行系统调用时处于进程上下文中,current指针指向当前进程,即引发系统调用的进程。
相关文章
- Android Fragment实现button间的切换
- 34 动态组件(切换组件)保存状态input值
- 输入法 ctrl+句号 切换 中英文符号
- OSG addEventHandler W键显示网格 L键控制光照 F键切换全屏窗口 S键显示统计数据 事件处理器
- 53 爬虫 - Selenium 页面切换
- 实战演练 | Navicat 中英文模式切换
- 从Java视角理解系统结构(一)CPU上下文切换
- 一篇文章带你「重新认识」线程上下文切换怎么玩儿
- MyEclipse SVN 下面切换用户的解决方案
- iOS Sprite Kit教程之场景的切换
- 在多个游戏视图间切换实现效果
- van-tabs初始化v-model不能切换
- 《Adobe Dreamweaver CS6中文版经典教程》——1.2 切换和拆分视图
- libco协程库上下文切换原理详解
- tab切换案例
- sweiper做一个tab切换
- Fragment实现底部选项卡切换效果
- 【Visual Studio】切换版本控制工具插件