嵌入式操作系统内核原理和开发(线程切换)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
在操作系统中,线程切换是很重要的一个环节。如果没有线程的切换,我们如何才能实现多线程的并发运行呢?既然要实现切换,那么一方面,我们需要对原来的寄存器进行保存,另外一方面我们还要压入新堆栈的寄存器,这样才能实现线程切换的效果。在x86下面,因为切换线程的ip地址是固定的,所以切换所需要的寄存器也是固定的,一般来说保存eax、ebx、ecx、edx、esi、edi、ebp和esp即可。比如说,像这样,
void swap(UINT32* prev, UINT32* next)
{__asm("push %%eax\n\t""push %%ebx\n\t""push %%ecx\n\t""push %%edx\n\t""push %%esi\n\t""push %%edi\n\t""push %%ebp\n\t""push %%esp\n\t""lea 0x8(%%ebp), %%eax\n\t""mov (%%eax), %%eax\n\t""mov %%esp, (%%eax)\n\t""lea 0xc(%%ebp), %%eax\n\t""mov (%%eax), %%eax\n\t""mov (%%eax), %%esp\n\t""pop %%esp\n\t""pop %%ebp\n\t""pop %%edi\n\t""pop %%esi\n\t""pop %%edx\n\t""pop %%ecx\n\t""pop %%ebx\n\t""pop %%eax\n\t"::);
}
上面说的都是对已经运行的线程进行切换。那么刚刚创建的线程怎么进行切换呢?一个不错的方法就是仿真出栈的处理流程。把初始状态的寄存器放在堆栈里面,模仿线程的出栈过程,设置好线程的初始寄存器数值即可。比如说,像这样,
void signal_handler(int m)
{UINT32* data;UINT32 unit;if(count != 0){printf("count = %d\n", count++);return;}printf("count = %d\n", count++);data = (UINT32*)malloc(STACK_LENGTH);unit = STACK_LENGTH >> 2;if(NULL == data)return;memset(data, 0, STACK_LENGTH);data[unit -1] = (UINT32) hello;data[unit -2] = 0;data[unit -3] = 0;data[unit -4] = 0;data[unit -5] = 0;data[unit -6] = 0;data[unit -7] = 0;data[unit -8] = 0;data[unit -9] = 0;data[unit -10] = (UINT32) &data[unit - 9];new = (UINT32) &data[unit -10];swap(&old, &new);free(data);
}
最后,我们给出一份完整的代码。在程序收到第一个signal的时候,我们发现代码不仅申请了内存,还初始化成了堆栈的格式,完美地解决了堆栈切换的问题。当然在hello处理结束后,代码又恢复成了原来的格式,而且内存正常释放,一切就像没有发生过一样。试想,如果每一次处理的都是一个function和stack,那基本上就可以模仿线程的运行过程了。
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include <stdlib.h>
#include <signal.h>#define UINT32 unsigned int
#define STACK_LENGTH 1024static struct itimerval oldtv;
UINT32 old = 0;
UINT32 new = 0;
UINT32 count = 0;void set_timer()
{struct itimerval itv;itv.it_interval.tv_sec = 1;itv.it_interval.tv_usec = 0;itv.it_value.tv_sec = 1;itv.it_value.tv_usec = 0;setitimer(ITIMER_REAL, &itv, &oldtv);
}void swap(UINT32* prev, UINT32* next)
{__asm("push %%eax\n\t""push %%ebx\n\t""push %%ecx\n\t""push %%edx\n\t""push %%esi\n\t""push %%edi\n\t""push %%ebp\n\t""push %%esp\n\t""lea 0x8(%%ebp), %%eax\n\t""mov (%%eax), %%eax\n\t""mov %%esp, (%%eax)\n\t""lea 0xc(%%ebp), %%eax\n\t""mov (%%eax), %%eax\n\t""mov (%%eax), %%esp\n\t""pop %%esp\n\t""pop %%ebp\n\t""pop %%edi\n\t""pop %%esi\n\t""pop %%edx\n\t""pop %%ecx\n\t""pop %%ebx\n\t""pop %%eax\n\t"::);
}void hello()
{printf("hello!\n");swap(&new, &old);
}void signal_handler(int m)
{UINT32* data;UINT32 unit;if(count != 0){printf("count = %d\n", count++);return;}printf("count = %d\n", count++);data = (UINT32*)malloc(STACK_LENGTH);unit = STACK_LENGTH >> 2;if(NULL == data)return;memset(data, 0, STACK_LENGTH);data[unit -1] = (UINT32) hello;data[unit -2] = 0;data[unit -3] = 0;data[unit -4] = 0;data[unit -5] = 0;data[unit -6] = 0;data[unit -7] = 0;data[unit -8] = 0;data[unit -9] = 0;data[unit -10] = (UINT32) &data[unit - 9];new = (UINT32) &data[unit -10];swap(&old, &new);free(data);
}int main()
{set_timer();signal(SIGALRM, signal_handler);while(count < 10);exit(0);return 1;
}
嵌入式操作系统内核原理和开发(线程切换)相关推荐
- 嵌入式操作系统内核原理和开发
嵌入式操作系统内核原理和开发(开篇) 操作系统是很多人每天必须打交道的东西,因为在你打开电脑的一刹那,随着bios自检结束,你的windows系统已经开始运行了.如果问大家操作系统是什么?可能有的人会 ...
- 嵌入式操作系统内核原理和开发(总结篇)
[ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 很多朋友都喜欢嵌入式操作系统的内容,但是如何实现和仿真这样一个系统一直是困扰我们的难题.现在郑 ...
- 嵌入式操作系统内核原理和开发(cpu的那些事)
[ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] cpu是数字处理系统中的一个重要环节.在我看来,单片机.微处理器.dsp都可以称作是cpu,只 ...
- 嵌入式操作系统内核原理和开发(地址空间)
[ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 不管是什么样的嵌入式cpu,它必然有自己的访问地址空间.至于这个具体的访问空间是什么,那cpu ...
- 嵌入式操作系统内核原理和开发(线程状态)
[ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 从第一篇的os博客以来,谈了很多内容,有中断.切换.调度.内存.互斥和延时等等, ...
- 嵌入式操作系统内核原理和开发(消息队列)
[ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 消息队列是线程交互的一种方法,任务可以通过消息队列来实现数据的沟通和交换.在嵌入式系统上,这可 ...
- 嵌入式操作系统内核原理和开发(信号量)
[ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 之前因为工作的原因,操作系统这块一直没有继续写下去.一方面是自己没有这方面的经历,另外一方面就 ...
- 嵌入式操作系统内核原理和开发(基础)
[ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 在编写我们的操作系统之前,我们需要明确一些事情.比如说,这个系统的运行环境是什么?怎么编译?基 ...
- 嵌入式操作系统内核原理和开发(开篇)
[ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 操作系统是很多人每天必须打交道的东西,因为在你打开电脑的一刹那,随着bios自检结束,你的wi ...
最新文章
- 分享一个Go按行读取命令行输入的例子
- java resources目录 编码_关于Java项目读取resources资源文件路径
- Linux服务器网卡驱动安装及故障排除(转)
- 计算机操作系统指导书,《计算机操作系统》实验指导书-2015
- TikZ学习笔记番外篇: 使用tikzcd包绘制交换图
- 台风怎么看内存颗粒_【无趣】使用300多元的D4 16G内存是种什么体验
- java MAVEN下载的代码仓库位置 mac
- Python 中Python 为什么要继承 object 类
- AngularJS 控制器 ng-controller
- 小车|PID算法 闭环控制 带有 霍尔编码器 的电机
- SAP SD销售订单保存提示 定价错误: 必要条件 MWSI 丢失解决方法
- mt6771(Helio P60)套片开发资料下载,mt6771处理器性能
- 【三石jQuery视频教程】01.图片循环展示_重发
- Maven –如何跳过单元测试
- 五大常用算法一(回溯,随机化,动态规划)
- 从零开始学习VIO笔记 --- 第一讲:基础知识(四元数,李代数)
- 安卓设置keychain_简单实现KeyChain实例
- 华强北再也没法生产散装 iPhone 了
- 谈B2B电商平台与大数据
- html 按键检测,js如何检测键盘按键的ascii码?
热门文章
- Uniform Distribution均匀分布
- javaweb男的gulp入手实践
- 开启事务处理插入多条数据 速度也可以
- 【转】Android用NDK和整套源码下编译JNI的不同
- 使用Monitor调试Unity3D Android程序日志输出(非DDMS和ADB)
- h3c s5500-28c-si操作
- [转]调整 VirtualBox 虚拟机的磁盘大小
- [NOIP2016]换教室(概率期望$DP$)
- 通过SecureCRT访问亚马逊Amazon EC2主机
- LeetCode85 Maximal Rectangle