本来我想一口气发完的,但感觉这次的文章写得实在太差,逻辑感不强,也比较长,所以本文尝试分为三部分:

这部分主要讲上下文切换的实现。

ucontext

我们实现了上下文切换主要是使用了glibc提供的ucontext.h。它提供了四个api:

/* Get user context and store it in variable pointed to by UCP. */

extern int getcontext (ucontext_t *__ucp) __THROWNL;

/* Set user context from information of variable pointed to by UCP. */

extern int setcontext (const ucontext_t *__ucp) __THROWNL;

/* Save current context in context variable pointed to by OUCP and setcontext from variable pointed to by UCP. */

extern int swapcontext (ucontext_t *__restrict __oucp,

const ucontext_t *__restrict __ucp) __THROWNL;

/* Manipulate user context UCP to continue with calling functions FUNCand the ARGC-1 parameters following ARGC when the context is usedthe next time in `setcontext' or `swapcontext'.We cannot say anything about the parameters FUNC takes; `void'is as good as any other choice. */

extern void makecontext (ucontext_t *__ucp, void (*__func) (void),

int __argc, ...) __THROW;

上一篇中实现C的原型的时候,就有展示过怎么用了。我们最主要的使用到了上下文切换的功能。而ucontext还支持了非局部转跳(setjmp/longjmp)等功能,多保存了些我们不需要的上下文信息。最主要的是glibc windows上也没有(但是有winapi提供的WinFiber)。

上下文切换

现在我们要去ucontext化,如何实现上下文切换功能呢?我们需要先要了解一下x86-64和posix abi的调用约定(先假定是非windows的x64平台)

寄存器rax作为返回值。不需要保护。

rsp栈指针寄存器,指向栈顶。需要被保护。

rdi, rsi, rdx, rcx, r8, r9依次对应函数的前六个参数,当参数超过6个,才会压栈。不需要保护。

rbx, rbp, r12到r15,用于数据存储,“属于”调用者。需要被保护。x86_64 posix abi各寄存器的说明

调用栈

调用栈是从上往下增长的,一个函数的栈帧长这样:一个函数的栈帧

当前函数栈帧从高地址(栈底)到低地址(栈顶)分别有返回地址,局部变量等东西。然后前一个帧栈有函数参数。

函数调用call指令:先将下一条指令的地址(return address)push到栈顶,然后转跳到函数体

ret指令:将return address(栈顶,rsp所指向的位置) pop到rip中。

在执行call之后,会将rsp挪到新的位置,创造一个新的帧栈。

在执行ret之前,会将rsp挪回去,销毁当前帧栈。

对于上下文切换我们只需要把需要被保护的寄存器存起来就好,同时也不需要处理浮点数的东西。

#[derive(Debug, Default, Clone, Copy)]#[repr(C)]struct Ctx{rsp: u64,r15: u64,r14: u64,r13: u64,r12: u64,rbx: u64,rbp: u64,gen_ptr: u64,// 当做参数指向协程generator}extern"C"{fn switch_ctx(old: *mutCtx,new: *constCtx);}

上下文切换实现起来十分的简单,只要简单的保存上下文,恢复上下文就可以了。switch_ctx的汇编实现:

switch_ctx:

; 这里没像普通函数那样子开辟新的栈帧

; 保存当前上下文到old

mov %rsp, 0x00(%rdi)

mov %r15, 0x08(%rdi)

mov %r14, 0x10(%rdi)

mov %r13, 0x18(%rdi)

mov %r12, 0x20(%rdi)

mov %rbx, 0x28(%rdi)

mov %rbp, 0x30(%rdi)

; 从new恢复上下文

mov 0x00(%rsi), %rsp ; 修改栈指针,使得调用栈从自定义的空间中开始

mov 0x08(%rsi), %r15

mov 0x10(%rsi), %r14

mov 0x18(%rsi), %r13

mov 0x20(%rsi), %r12

mov 0x28(%rsi), %rbx

mov 0x30(%rsi), %rbp

; 将gen_ptr当做第一个参数传给bootstrap

mov 0x38(%rsi), %rdi

ret

还有makecontext对应的过程:

unsafefn init_ctx(ctx: &mutCtx,dual_gen: Box>,// caller的generatorstack_ptr: *mutu8,stack_size: usize,){// bootstrap的第一个参数,并用Box::into_raw释放其所有权。// 进入bootstrap前给rdi寄存器ctx.gen_ptr=Box::into_raw(dual_gen)asu64;// 设置协程入口点为bootstrapptr::write(// 这里要给栈底设置足够多的空闲位置stack_ptr.add(stack_size-32)as*mutu64,bootstrap::asu64,);// 让栈顶指针指向返回地址(bootstrap)// 当switch_ctx返回时,就会将所指向的地址(bootstrap)弹到rip中,然后执行bootstrapctx.rsp=stack_ptr.add(stack_size-32)asu64;}

现在只需要将swapcontext换成我们写的switch_ctx,然后将makecontext换成init_ctx,最后在bootstrap最后手动调用switch_ctx就好。

其中bootstrap的签名为:

unsafefn bootstrap(dual_gen_raw: *mutGen)-> !

伪小结

本篇的实现参考了文章Introduction​cfsamson.gitbook.io

将ucontext替换为了自己的实现的上下文切换的函数。这里的汇编代码可以先编译成静态库然后给rust使用,也可以编写build.rs执行编译打包的脚本,直接在cargo工程中编写汇编。

rust军用船指令_给Rust实现一个简单的stackful generator(中)上下文切换相关推荐

  1. rust军用船指令_RUST物品指令清单(英文版)

    RUST物品指令清单(英文版) 所属分类:其他 开发工具:WINDOWS 文件大小:19KB 下载次数:7 上传日期:2017-07-03 20:24:08 上 传 者:escmfack 说明:  R ...

  2. rust军用船指令_Rust基础学习笔记(五):Cargo与Crates.io

    最近复习鸽了几天,今天继续学,希望在考试之前搞定这个官方文档 もうダメ.... 本章学习Cargo和Crates.io相关,内容有下: 自定义构建 向crates.io提交libraries 利用工作 ...

  3. rust新版组队指令_腐蚀rust新版服务器指令大全 腐蚀指令一览

    服务器指令 rcon.login "password" [Use your 'Password' to login into Rcon via ingame console (F1 ...

  4. rust新版组队指令_新版rust指令是啥啊?

    基本指令 (以下在聊天框内输入) /msg [message a specified player(私信一个玩家)] /me [Puts your text into a purple color(你 ...

  5. rust如何改睡袋_腐蚀rust怎么做睡袋 | 手游网游页游攻略大全

    发布时间:2016-05-07 腐蚀是一款FPS僵尸类生存游戏,这款游戏中玩家可以体验到非常自由的游戏方式,玩家需要寻找生存的资源,同时也需要及时预防僵尸和其他不怀还以的玩家的入侵,下面是新手全面攻略 ...

  6. rust主播排行_「Rust日报」2019每周精选 • 第四期

    前言: 从2018年开始,我每天会花1个小时关注Rust社区动态,并且在Rust.CC论坛.tg channel.Steemit.GitHub.语雀订阅都开通了Rust日报,分享我每天的见闻,偶尔也夹 ...

  7. rust关闭抗锯齿_腐蚀Rust画面设置指南 游戏设置优化心得分享

    今天小编要为大家带来得是腐蚀Rust画面设置指南,腐蚀Rust是一款第一人称僵尸生存网络游戏,在游戏中玩家需要防范动物.僵尸.玩家的袭击,并依靠各类物品进行生存. 画面设置优化指南 图像质量1~3为一 ...

  8. rust怎么造双层_腐蚀rust双层防炸地基教学 rust伪分离图文教学

    腐蚀rust双层防炸地基教学 rust伪分离图文教学 2018-02-10 11:57:14来源:游戏下载编辑:野狐禅评论(0) 腐蚀rust是近日发售的一款FPS游戏,很受玩家欢迎,一些技巧也被玩家 ...

  9. hashmap 从头到尾_如何从头到尾设计一个简单的复古徽标

    hashmap 从头到尾 在纸上素描粗糙的概念 (Sketch rough concepts on paper) Start by sketching out a few ideas for your ...

最新文章

  1. [转载]VC轻松解析XML文件 - CMarkup类的使用方法
  2. linux find命令详解--转
  3. 局域网计算机中arp,在局域网中的一台计算机上使用了arp-a命令,有如下输出: C:\arp.a Interface: 192.168.0.1 0n - 赏学吧...
  4. 由铁路订票系统联想到的
  5. CoInitialize和CoInitializeEx
  6. json绑定到实体_绑定到JSON和XML –处理集合
  7. python 绘制时频图 plt.specgram
  8. 【mysql基础知识】数据库中新建触发器,监控数据变化
  9. 素拓活动策划书的撰写范文
  10. Android---------------ContentProvider的学习
  11. 二.公共建筑安全防范系统配置
  12. sql2000 mysql_sql2000迷你版 超精简版SQL Server 2000数据库下载
  13. 22. vCenter上解决”此主机当前没有管理网络冗余“的警告
  14. 算法 | 八皇后问题
  15. 序列化(boost serialization)
  16. 产品生命周期管理PLM技术研究
  17. 图形库LVGL v8.2版本移植
  18. 【电脑全部浏览器显示您与网站连接不是私密连接】
  19. Ubuntu server 14.04 启用root用户并设置密码
  20. 可道云kodexplorer搭建私有云后的配置优化

热门文章

  1. 计算机视觉(北邮鲁鹏)--卷积
  2. SSM考试题库管理系统毕业设计源码069043
  3. mong命令学习记录
  4. 作品集十(平面设计)
  5. 使用jquery,按回车键实现tab键的功能
  6. 计算机单位厘米 像素,300dpi的dpi是多少?是像素/英寸吗?还是像素/厘米?
  7. A-瑞神的序列 B- 消消乐大师-Q老师(M3)
  8. 内存小实用的手机浏览器,这2款无广告,功能不输UC
  9. T1118,T1677,T1122
  10. 数字图像处理:4.色彩空间转换