当前位置: 首页 > news >正文

外贸商城网站资质seo优化排名技术百度教程

外贸商城网站资质,seo优化排名技术百度教程,西宁网站设计制作,韩国在中国做美食的视频网站有哪些协程实现原理 协程的本质都是通过修改 ESP 和 EIP 指针来实现的。其理论上还是单线程在运行. 程序在CPU上运行时依赖3个寄存器: ESP寄存值指向当前栈顶地址,指向当前指令需要的数据EBP指向当前活动栈帧的基地址指令寄存器IP,指向当…

协程实现原理

协程的本质都是通过修改 ESP 和 EIP 指针来实现的。其理论上还是单线程在运行.

程序在CPU上运行时依赖3个寄存器:

  1. ESP寄存值指向当前栈顶地址,指向当前指令需要的数据
  2. EBP指向当前活动栈帧的基地址
  3. 指令寄存器IP,指向当前需要运行的指令

其中主要有(IP,ESP)寄存器最重要,这两个寄存器指针的改变可以修改当前需要加载到 CPU 运行的指令和数据,当某个操作陷入到耗时的等待中时,通过修改这两个指针即可让出CPU,交给其他的任务去使用,每个任务都必须主动的让出CPU,然后等待下一次的调度来继续未完成的任务,这样就可以最大程度的利用CPU,当一个任务等待过程非常短的时候,就出现了多个任务并行运行的效果,也就是协程。

实现协程的多种方法

  1. 利用 glibcucontext 组件(云风的库)
  2. 使用汇编来切换上下文(实现miniC协程,腾讯libco)
  3. 利用C语言语法switch-case的奇淫技巧来实现(Protothreads)
  4. 利用了 C 语言的 setjmplongjmp( 一种协程的 C/C++ 实现,要求函数里面使用 static local 的变量来保存协程内部的数据)
  5. 利用Boost库提供的两种实现,分别是stacklessstackfull
  6. 等等语言和库....

当然了,最"厉害"的还是去用汇编去实现,因为这样会避免许多跨平台等问题.比如在有些平台就会用不了setcontext等函数.有些函数可能也慢慢的废除了,所以用汇编实现是最有效的,也是腾讯公司经过多年的实践得出的.

glibc库里的上下文操作函数:

1.getcontext()  : 获取当前context
2.setcontext()  : 切换到指定context
3.makecontext() : 设置 函数指针 和 堆栈 到对应context保存的 sp 和 pc 寄存器中,调用之前要先调用 getcontext()
4.swapcontext() : 保存当前context,并且切换到指定context

具体使用可以自己查询一下,最后我会用他们实现一个C++11协程库.

如何实现保存和恢复协程运行栈


实例:使用C++11setcontext类函数实现协程库

main.cpp

#include "Coroutine.h"#include <iostream>
#include <stdio.h>
#include <unistd.h>
using namespace std;
using namespace Tattoo;class TEST
{public:void func3(std::shared_ptr<CoroutineSchedule> s, void *arg){for (int i = 0; i < 10; i++){cout << "coroutine : " << s->GetCurCoID() << " : " << *(int *)arg + i << endl;s->Yield();}}
};int main()
{std::shared_ptr<CoroutineSchedule> schedule = std::make_shared<CoroutineSchedule>();int test1 = 1;int test2 = 2;int test3 = 3;TEST tt;int id_co1 = schedule->CreateCoroutine(std::bind(&TEST::func3, &tt, schedule, &test1));int id_co2 = schedule->CreateCoroutine(std::bind(&TEST::func3, &tt, schedule, &test2));int id_co3 = schedule->CreateCoroutine(std::bind(&TEST::func3, &tt, schedule, &test3));printf("main start\n");while ((schedule->IsAlive(id_co1)) && (schedule->IsAlive(id_co2)) && (schedule->IsAlive(id_co3))){schedule->ResumeCoroutine(id_co1);schedule->ResumeCoroutine(id_co2);schedule->ResumeCoroutine(id_co3);}printf("main end\n");return 0;
}

CoroutineSchedule.h


#ifndef _COROUTINESCHEDULER_H
#define _COROUTINESCHEDULER_H //B.h#include <ucontext.h>
#include <unordered_map>
#include <memory>
#include <functional>
#include <iostream>#define INFO(x, y, z) std::cout << x << " : " << y << " : " << z << std::endl;
namespace Tattoo
{class Coroutine;
class CoroutineSchedule
{public:static const int STACK_SIZE = 1024 * 1024;static const int MAX_CO = 16;using CoFun = std::function<void()>;CoroutineSchedule() : cur_co_num_(0), cur_run_id_(-1) {}~CoroutineSchedule() {}CoroutineSchedule(const CoroutineSchedule &) = delete;CoroutineSchedule &operator=(const CoroutineSchedule &) = delete;int CreateCoroutine(CoFun func);void DestroyCroutine(int cor_id);void ResumeCoroutine(int cor_id);void Yield();bool IsAlive(int cor_id);int GetCurCoID() { return cur_run_id_; }static void static_fun(void *arg);private:std::unordered_map<int, std::shared_ptr<Coroutine>> mmap_;char SchStack[STACK_SIZE] = {0};ucontext_t main_ctx;int cur_co_num_; /*实时记录协程数量,也会控制map下标*/int cur_run_id_;
};
} // namespace Tattoo
#endif

CoroutineSchedule.cpp


#include "Coroutine.h"namespace Tattoo
{int CoroutineSchedule::CreateCoroutine(CoFun func)
{/*这里可以用 cur_max_num_ 去限制协程数目*/cur_co_num_++;auto cor = std::make_shared<Coroutine>(this, func, cur_co_num_);mmap_[cur_co_num_] = cor;return cur_co_num_;
}
void CoroutineSchedule::DestroyCroutine(int cor_id)
{if (mmap_.find(cor_id) == mmap_.end())return;if (cor_id == cur_run_id_)cur_run_id_ = -1;mmap_[cor_id]->SetStatus(Coroutine::CO_FINSHED);cur_co_num_--; /*下次重复使用就行了,不需要 erase */
}
void CoroutineSchedule::Yield()
{if (-1 == cur_run_id_)return;int id = cur_run_id_;std::shared_ptr<Coroutine> cor = mmap_[id];// assert(reinterpret_cast<char *>(&cor) > );cor->save_stack(SchStack + STACK_SIZE);cor->SetStatus(Coroutine::CO_SUSPEND);cur_run_id_ = -1;swapcontext(&cor->ctx_, &main_ctx);
}
bool CoroutineSchedule::IsAlive(int cor_id)
{if (mmap_[cor_id]->GetStatus() == Coroutine::CO_FINSHED)return false;elsereturn true;
}
void CoroutineSchedule::ResumeCoroutine(int cor_id)
{// INFO("*******************************************ResumeCoroutine", cor_id, cur_run_id_);if (mmap_.find(cor_id) == mmap_.end()) /*不存在的 id */return;assert(this->cur_run_id_ == -1); //保证没有其他协程运行std::shared_ptr<Coroutine> cor = mmap_[cor_id];switch (cor->GetStatus()){case Coroutine::CO_READY:{getcontext(&cor->ctx_);cor->ctx_.uc_stack.ss_sp = SchStack;cor->ctx_.uc_stack.ss_size = STACK_SIZE;cor->ctx_.uc_link = &main_ctx;cur_run_id_ = cor_id;cor->SetStatus(Coroutine::CO_RUNNING);makecontext(&cor->ctx_, reinterpret_cast<void (*)()>(static_fun), 1, this);swapcontext(&this->main_ctx, &cor->ctx_);}break;case Coroutine::CO_SUSPEND:{memcpy(SchStack + STACK_SIZE - cor->stack_cur_size_, cor->CorStack, cor->stack_cur_size_);cur_run_id_ = cor_id;cor->SetStatus(Coroutine::CO_RUNNING);swapcontext(&main_ctx, &cor->ctx_);}break;default:assert(0);}if (-1 == cur_run_id_ && cor->status_ == Coroutine::CO_FINSHED)DestroyCroutine(cor_id);
}
void CoroutineSchedule::static_fun(void *arg)
{CoroutineSchedule *sch = reinterpret_cast<CoroutineSchedule *>(arg);int id = sch->cur_run_id_;std::shared_ptr<Coroutine> cor = sch->mmap_[id];cor->func_();sch->cur_run_id_ = -1;sch->mmap_[id]->SetStatus(Coroutine::CO_FINSHED);
}
} // namespace Tattoo

Coroutine.h


#ifndef _COROUTINE_H
#define _COROUTINE_H
#include <ucontext.h>
#include <memory>
#include <assert.h>
#include <string.h>
#include "CoroutineSchedule.h"namespace Tattoo
{
class Coroutine
{public:using CoFun = std::function<void()>;enum{CO_FINSHED,CO_READY,CO_RUNNING,CO_SUSPEND,};Coroutine(CoroutineSchedule *sch, CoFun func, int id);~Coroutine();Coroutine(const Coroutine &) = delete;Coroutine &operator=(const Coroutine &) = delete;void SetStatus(int status);int GetStatus();private:friend class CoroutineSchedule;void save_stack(void *top);CoFun func_;ucontext_t ctx_;std::shared_ptr<CoroutineSchedule> sch_;std::ptrdiff_t stack_max_size_; //stack最大 大小std::ptrdiff_t stack_cur_size_; //协程实际大小int status_;char *CorStack;int id_;
};
} // namespace Tattoo
#endif

Coroutine.cpp


#include <ucontext.h>
#include <memory>
#include <assert.h>
#include <string.h>#include "Coroutine.h"namespace Tattoo
{
Coroutine::Coroutine(CoroutineSchedule *sch, CoFun func, int id): func_(func), id_(id), sch_(sch),stack_max_size_(0), stack_cur_size_(0),status_(CO_READY), CorStack(0)
{
}
Coroutine::~Coroutine()
{delete[] CorStack;
}void Coroutine::SetStatus(int status)
{status_ = status;
}
int Coroutine::GetStatus()
{return status_;
}
void Coroutine::save_stack(void *top)
{char dummy = 0;assert((char *)top - &dummy <= CoroutineSchedule::STACK_SIZE);if (stack_max_size_ < (char *)top - &dummy){delete[] CorStack;stack_max_size_ = (char *)top - &dummy;CorStack = new char[stack_max_size_];}stack_cur_size_ = (char *)top - &dummy;memcpy(CorStack, &dummy, stack_cur_size_);
}
} // namespace Tattoo

运行截图:

在这里插入图片描述

因为我的目标是用汇编去实现,所以也就不花时间去优化代码了(比如里面还存在原始指针,new,delete ,内存泄露等).

转载于:https://www.cnblogs.com/Tattoo-Welkin/p/10335248.html

http://www.lbrq.cn/news/2531899.html

相关文章:

  • 做网站什么职业廊坊网站推广公司
  • 做直播平台网站赚钱吗互联网销售平台
  • 假冒网站能通过备案登记吗电商网站建设公司哪家好
  • 昆明房地产网站建设百度引擎
  • 优秀国内个人网站网址sem推广软件选哪家
  • 宝鸡英文网站建设短视频矩阵seo系统源码
  • to a wordpress上海seo有哪些公司
  • 做金融网站看那些素材宁波优化网页基本流程
  • 杭州网站建设服务企业网站开发费用
  • 在哪个网站找婚照公司网络代运营推广
  • 网站怎么做更新吗如何优化网站
  • 有什么网站可以做宣传网络推广十大平台
  • 做设计需要知道的几个网站吗中国网民博客 seo
  • 北京做网站的公司上海网站推广服务公司
  • 做网站上的在线支付怎么做长沙企业seo服务
  • js网站源码已到期信息流推广主要具有哪两大优势
  • 做网站店铺图片用什么软件搜索引擎营销策划方案
  • 东丰在线网站建设成都移动seo
  • 西宁网站制作宁波谷歌优化
  • 做局域网网站教程网站设计说明
  • 福田网站建设龙岗网站建设龙岗网站建设推销产品的万能句子
  • tp框架做展示网站重庆seo
  • 2017网站趋势百度推广一级代理商名单
  • 常德网站优化想开个网站怎样开
  • 网站建设装什么系统湖南企业竞价优化公司
  • 做网站域名需哪些百度手机下载安装
  • 长春服务好的网站建设北京seo相关
  • 免费网站系统下载广州疫情已经达峰
  • 有哪些网站是用vue做的网站快速有排名
  • 祥云网站建设公司 概况网站生成app工具
  • CSS font-weight:500不生效
  • 开发避坑短篇(9):解决升级Vue3后slot attributes废弃警告
  • Python Day19 时间模块 和 json模块 及例题分析
  • 【C#】DevExpress.XtraEditors.MemoEdit memoEditLog控件讲解
  • 数据结构第3问:什么是线性表?
  • 【Qt开发】信号与槽(三)-> 自定义信号和槽