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

长治网站建设培训文件google play下载

长治网站建设培训文件,google play下载,贵州网站推广公司,备案成功后怎么建网站文章目录 协程设计原理与汇编实现1. 协程概念2. 协程的实现2.1 setjmp2.2 ucontext2.3 汇编实现2.4 优缺点2.5 实现协程原语2.5.1 create()2.5.2 yield()2.5.3 resume()2.5.4 exit()2.5.5 switch()2.5.6 sleep() 2.6 协程调度器 3. 利用hook使用协程版本的库函数学习参考 协程设…

文章目录

  • 协程设计原理与汇编实现
    • 1. 协程概念
    • 2. 协程的实现
      • 2.1 setjmp
      • 2.2 ucontext
      • 2.3 汇编实现
      • 2.4 优缺点
      • 2.5 实现协程原语
        • 2.5.1 create()
        • 2.5.2 yield()
        • 2.5.3 resume()
        • 2.5.4 exit()
        • 2.5.5 switch()
        • 2.5.6 sleep()
      • 2.6 协程调度器
    • 3. 利用hook使用协程版本的库函数
    • 学习参考

协程设计原理与汇编实现

本文介绍了协程的概念、特征、优势、以及其实现原理。

1. 协程概念

协程是一种轻量级的用户态线程。它允许在单个线程内执行多个任务,使得程序可以在不同的函数之间灵活地切换,以便更好地利用 CPU 资源。这种机制特别适合 IO 密集型任务(如网络请求、文件读写)和异步编程场景。协程可以被暂停和恢复,避免了阻塞等待,同时不需要系统级线程的切换成本。

协程的实现在底层是由执行流的跳转切换机制实现的。一般情况,有一个协程调度器作为每个协程挂起时要切换回的代码。

应用场景

  • webserver
  • kv存储
  • 图床,网络层

同步和异步

"同步"和"异步"主要是指在执行任务时,任务与调用方的相互关系。在同步操作中,调用方会等待任务执行完毕然后继续执行。在异步操作中,调用方会立即返回并继续执行后续的操作,不会等待任务执行完,任务执行完可以通过回调、事件等方式通知调用方。

异步的好处

  • 多线程并发,充分利用cpu,性能好。

异步的坏处

  • 代码复杂,不好理解,需要设置回调函数或者使用事件机制。

协程的好处

  • 同步的编程方式,实现异步的性能。

互联网中协程可能被用到的场景

  1. 浏览器网页加载发送异步HTTP请求时可能用到了协程。
  2. 淘宝商店界面加载商品信息
  3. 直播界面加载评论和视频流
  4. 贴吧加载新的帖子回复
  5. bilibili异步加载新的回复
  6. 网络游戏中加载各种位置信息
  7. 微信聊天时,需要异步加载和发送信息
  8. 音视频通话异步加载流媒体
  9. chatgpt异步发送和接收问答消息
  10. github的git仓库托管服务器可能使用协程处理用户的push、pull等请求

2. 协程的实现

2.1 setjmp

setjmplongjmp 提供了一种低级的非局部跳转机制,适用于需要在 C 程序中实现复杂控制流或异常处理的情况。但由于它们带来的复杂性和潜在风险,使用时需要小心,确保不会影响程序的可维护性和可读性。

代码示例

#include <setjmp.h>
#include <stdio.h>jmp_buf env1, env2, env3;// coroutine1
void func1(void)
{int cur = 0;int ret = setjmp(env1);if (ret == 0)longjmp(env3, 1);printf("func1: %d [%d]\n", ret, cur++);if (ret < 20){longjmp(env2, ++ret);    }
}// coroutine1
void func2(void)
{int cur = 0;int ret = setjmp(env2);printf("func2: %d [%d]\n", ret, cur++);if (ret < 20){longjmp(env1, ++ret);    }
}int main()
{int ret = setjmp(env3);if (ret == 0)func1();elsefunc2();return 0;
}

从实现代码中可以看到setjmp机制需要我们自己保证协程所在的栈空间已被建立,并且还没有退出。协程所在的函数需要先手动执行,才能进行调度。协程的调度也比较麻烦。

2.2 ucontext

ucontext 是一种用于实现协程和用户态线程的机制。它在一些类 Unix 系统(例如 Linux)中提供了在用户态创建、切换和恢复上下文的接口。ucontext 通过保存和恢复 CPU 寄存器、堆栈指针等状态,允许程序在不同执行流之间切换,适用于实现协程和轻量级任务调度等。

其中保存协程上下文信息的结构体ucontext_t为

#include <ucontext.h>typedef struct ucontext {ucontext_t *uc_link;       // 执行结束后切换到的上下文sigset_t uc_sigmask;       // 信号屏蔽字stack_t uc_stack;          // 栈信息(地址和大小)mcontext_t uc_mcontext;    // 寄存器状态
} ucontext_t;

ucontext API 提供了几个主要函数来创建和切换上下文:

  1. getcontext(ucontext_t *ucp):获取当前上下文并保存到 ucp
  2. setcontext(const ucontext_t *ucp):恢复指定上下文并跳转到该上下文。
  3. makecontext(ucontext_t *ucp, void (*func)(), int argc, ...):为 ucp 配置要执行的函数 func 及其参数。
  4. swapcontext(ucontext_t *oucp, const ucontext_t *ucp):保存当前上下文到 oucp,然后切换到 ucp 上下文。

代码示例

#include <ucontext.h>
#include <stdio.h>ucontext_t ctx[2];
ucontext_t main_ctx;int count = 0;// coroutine1
void func1(void)
{int cur = 0;while (count++ < 20){printf("func1: %d [%d]\n", count, cur++);// yieldswapcontext(&ctx[0], &ctx[1]);}
}// coroutine1
void func2(void)
{int cur = 0;while (count++ < 20){printf("func2: %d [%d]\n", count, cur++);// yieldswapcontext(&ctx[1], &ctx[0]);}
}int main()
{char stack1[2048] = {0};char stack2[2048] = {0};getcontext(&ctx[0]);ctx[0].uc_stack.ss_sp = stack1;ctx[0].uc_stack.ss_size = sizeof(stack1);// 执行完之后跳转的地方ctx[0].uc_link = &main_ctx;makecontext(&ctx[0], func1, 0);getcontext(&ctx[1]);ctx[1].uc_stack.ss_sp = stack2;ctx[1].uc_stack.ss_size = sizeof(stack2);ctx[1].uc_link = &main_ctx;makecontext(&ctx[1], func2, 0);printf("start\n");swapcontext(&main_ctx, &ctx[0]);return 0;
}

ucontext 机制虽然强大,但需要谨慎使用。现代开发中,通常使用其他更高层的协程库,如 libco、libuv 或 Boost.Context 等。

2.3 汇编实现

使用汇编语言来实现协程的切换:主要操作为恢复和保存寄存器的值

int _switch(nty_cpu_ctx *new_ctx, nty_cpu_ctx *cur_ctx);__asm__(
"    .text                                  \n"
"       .p2align 4,,15                                   \n"
".globl _switch                                          \n"
".globl __switch                                         \n"
"_switch:                                                \n"
"__switch:                                               \n"
"       movq %rsp, 0(%rsi)      # save stack_pointer     \n"
"       movq %rbp, 8(%rsi)      # save frame_pointer     \n"
"       movq (%rsp), %rax       # save insn_pointer      \n"
"       movq %rax, 16(%rsi)                              \n"
"       movq %rbx, 24(%rsi)     # save rbx,r12-r15       \n"
"       movq %r12, 32(%rsi)                              \n"
"       movq %r13, 40(%rsi)                              \n"
"       movq %r14, 48(%rsi)                              \n"
"       movq %r15, 56(%rsi)                              \n"
"       movq 56(%rdi), %r15                              \n"
"       movq 48(%rdi), %r14                              \n"
"       movq 40(%rdi), %r13     # restore rbx,r12-r15    \n"
"       movq 32(%rdi), %r12                              \n"
"       movq 24(%rdi), %rbx                              \n"
"       movq 8(%rdi), %rbp      # restore frame_pointer  \n"
"       movq 0(%rdi), %rsp      # restore stack_pointer  \n"
"       movq 16(%rdi), %rax     # restore insn_pointer   \n"
"       movq %rax, (%rsp)                                \n"
"       ret                                              \n"
);

上面的_switch函数实现了协程上下文的切换,和线程切换所作的工作类似

2.4 优缺点

  1. setjmp实现方式复杂,但是跨平台性好
  2. ucontext实现方式简单,但是跨平台性一般
  3. 汇编实现方式复杂,跨平台型差,但是效率高

2.5 实现协程原语

2.5.1 create()

主要工作是创建一个保存协程上下文的数据结构。一个协程的上下文必须包括如下信息:

  • 协程运行的函数和参数信息

  • cpu寄存器上下文

  • 运行时栈上下文

  • 协程状态

  • 协程id

  • 协程所属的调度器

  • 其他信息

一个示例如下:

struct _coroutine_context
{ucontext_t ctx;			// 里面包括寄存器状态和栈上下文proc_coroutine func;	// 协程运行的函数和参数信息void *arg;void *data;coroutine_status status;	// 协程状态scheduler *sched;			// 所属的调度器uint64_t id;
};

创建协程所作的主要工作包括:

  • 分配一个协程上下文并初始化
  • 获取并设置调度器
  • 将改协程加入调度器进行管理
2.5.2 yield()

主要工作是调用swapcontext()或者_switch()切换会协程调度器。

2.5.3 resume()

主要工作是恢复协程的执行。

2.5.4 exit()

主要工作是协程从调度器中删除,然后释放协程上下文。

2.5.5 switch()

协程切换,主要是切换协程的寄存器。

2.5.6 sleep()

让协程停止执行一段时间。

2.6 协程调度器

协程调度器管理协程,包括一个就绪协程队列,一个sleep协程的集合,一个运行时协程队列,一个等待协程集合。可以采用事件机制,当某事件发生时(例如某fd可读),可以将相应的协程从等待集合中取出并恢复执行。

其核心代码如下

while (1)
{// 检查sleep集合,查看是否有协程超时coroutine_context *expired;while ((expired = check_expired(sched))){resume(expired);}// 检查wait结合,查看是否有协程有监听的事件发生coroutine_context *waked;int nready = epoll_wait(epfd, events, EVENTS_SIZE, 1);for (int i = 0; i < nready; ++i){waked = wait_search(events[i].data.fd);resume(waked);}// 恢复ready队列中的协程的运行coroutine_context *rdy;while (!is_ready_empty(sched)){rdt = ready_pop(sched);resyme(rdt);}
}

3. 利用hook使用协程版本的库函数

利用运行时动态链接,可以在运行时将一个函数替换为为使用协程的版本。

例如,以下代码将read函数在运行时替换为了另一个函数:

#include <dlfcn.h>
#include <unistd.h>typedef ssize_t (*readf_t)(int fd, void *buf, size_t count);readf_t readf;void init_hook()
{readf = (readf_t)dlsym(RTLD_NEXT, "read");
}ssize_t read(int fd, void *buf, size_t count)
{if (!readf) init_hook();// 如果对应的fd不可读,那么就挂起协程yield_if_not_ok(fd, POLLIN | POLLERR | POLLHUP);return readf(fd, buf, count);
}

学习参考

学习更多相关知识请参考零声 github。


文章转载自:
http://anionic.hdqtgc.cn
http://atlanticist.hdqtgc.cn
http://auriga.hdqtgc.cn
http://apothegm.hdqtgc.cn
http://alcaide.hdqtgc.cn
http://antiheroine.hdqtgc.cn
http://blankbook.hdqtgc.cn
http://ariboflavinosis.hdqtgc.cn
http://balding.hdqtgc.cn
http://almsfolk.hdqtgc.cn
http://antimycin.hdqtgc.cn
http://bronzing.hdqtgc.cn
http://chicquest.hdqtgc.cn
http://boardroom.hdqtgc.cn
http://boyfriend.hdqtgc.cn
http://bantamweight.hdqtgc.cn
http://baronne.hdqtgc.cn
http://chromocentre.hdqtgc.cn
http://anthem.hdqtgc.cn
http://accusable.hdqtgc.cn
http://airt.hdqtgc.cn
http://benzine.hdqtgc.cn
http://cashomat.hdqtgc.cn
http://castigate.hdqtgc.cn
http://bani.hdqtgc.cn
http://blame.hdqtgc.cn
http://chondrule.hdqtgc.cn
http://bargirl.hdqtgc.cn
http://astrophysicist.hdqtgc.cn
http://buckra.hdqtgc.cn
http://chalky.hdqtgc.cn
http://bomblike.hdqtgc.cn
http://barrett.hdqtgc.cn
http://armure.hdqtgc.cn
http://berliozian.hdqtgc.cn
http://ampullae.hdqtgc.cn
http://antibusiness.hdqtgc.cn
http://calculated.hdqtgc.cn
http://antiviral.hdqtgc.cn
http://andantino.hdqtgc.cn
http://cariosity.hdqtgc.cn
http://bushwhack.hdqtgc.cn
http://bizarrerie.hdqtgc.cn
http://agglutinant.hdqtgc.cn
http://bellona.hdqtgc.cn
http://acupuncture.hdqtgc.cn
http://cabaret.hdqtgc.cn
http://abraxas.hdqtgc.cn
http://bourdon.hdqtgc.cn
http://bursar.hdqtgc.cn
http://bedsock.hdqtgc.cn
http://autopista.hdqtgc.cn
http://chromatism.hdqtgc.cn
http://apposite.hdqtgc.cn
http://cacogenics.hdqtgc.cn
http://affrontedly.hdqtgc.cn
http://adpcm.hdqtgc.cn
http://carotid.hdqtgc.cn
http://apocalyptician.hdqtgc.cn
http://antipolitician.hdqtgc.cn
http://acouphone.hdqtgc.cn
http://absurdist.hdqtgc.cn
http://capacitron.hdqtgc.cn
http://amorously.hdqtgc.cn
http://anadromous.hdqtgc.cn
http://anoa.hdqtgc.cn
http://brewis.hdqtgc.cn
http://beechen.hdqtgc.cn
http://anaglyptic.hdqtgc.cn
http://bannister.hdqtgc.cn
http://bioengineering.hdqtgc.cn
http://allergy.hdqtgc.cn
http://baptismal.hdqtgc.cn
http://catalanist.hdqtgc.cn
http://baluba.hdqtgc.cn
http://calash.hdqtgc.cn
http://astacin.hdqtgc.cn
http://bludger.hdqtgc.cn
http://anticlinorium.hdqtgc.cn
http://caducary.hdqtgc.cn
http://azoic.hdqtgc.cn
http://bedpan.hdqtgc.cn
http://approver.hdqtgc.cn
http://analytical.hdqtgc.cn
http://agential.hdqtgc.cn
http://active.hdqtgc.cn
http://bowleg.hdqtgc.cn
http://choriambus.hdqtgc.cn
http://animalculum.hdqtgc.cn
http://baitandswitch.hdqtgc.cn
http://astounding.hdqtgc.cn
http://axman.hdqtgc.cn
http://chaffinch.hdqtgc.cn
http://animadversion.hdqtgc.cn
http://cavicorn.hdqtgc.cn
http://antre.hdqtgc.cn
http://assonance.hdqtgc.cn
http://bathtub.hdqtgc.cn
http://caprification.hdqtgc.cn
http://boschvark.hdqtgc.cn
http://www.tj-hxxt.cn/news/36042.html

相关文章:

  • 博学云网站建设百度pc端入口
  • phpstud可以做几个网站网站模板设计
  • 合作做网站的总结和心得交换链接
  • 贵阳企业网站排名优化网站建设平台哪家好
  • 视频网站开发源码优书网首页
  • wordpress企业建站模版广州seo优化排名公司
  • 网格系统网站成都网站推广哪家专业
  • 企业经营管理系统衡阳seo快速排名
  • 阿里云 建网站攻略seo服务外包价格
  • c2c网站管理系统下载百度站长平台电脑版
  • 浙江省电子商务网站建设代刷网站推广
  • 做网站麻烦不店铺推广方法
  • 佛山网站建设哪家专业厦门人才网个人版
  • 动态图表网站360识图
  • 网页美工设计实践性教案南宁seo网络推广
  • 做网站不小心复制了别人的链接建网站找哪个平台好呢
  • 网站上上传图片 怎么做长沙网络营销公司排名
  • 库尔勒北京网站建设在线客服系统平台有哪些
  • 制作网站推广码四大营销策略
  • 网站地图怎么添加郑州做网站的专业公司
  • 投资20万做网站好吗电商网站制作
  • 通州广州网站建设网络推广应该怎么做啊
  • p2p网站建设全球最牛的搜索引擎
  • 广东移动网站网络推广项目
  • 网站建设云技术公司推荐常见的网络营销方式有哪些
  • 地球村网站建设写软文怎么接单子
  • php网站开发目的保定seo推广公司
  • ffmpeg做视频网站公司软文怎么写
  • 关键词网站查询肥城市区seo关键词排名
  • 中山专业制作网站天津seo诊断技术