[转]协程 及 Libco 介绍

libco example_cond.cpp分析 腾讯libco库的example分析 可以参考https://github.com/zhoudayang/libco example_cond.cpp /* 生产者消费者模型 */ #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <queue> #inc... 阅读详情

2015-7-21阅读32 评论0

libco 是腾讯开源的一个协程库,主要应用于微信后台RPC框架,下面我们从为什么使用协程、如何实现协程、libco使用等方面了解协程和libco。

 

why协程

为什么使用协程,我们先从server框架的实现说起,对于client-server的架构,server最简单的实现:

while(1) {accept();recv();do();send();}

串行地接收连接、读取请求、处理、应答,该实现弊端显而易见,server同一时间只能为一个客户端服务。

 

为充分利用好多核cpu进行任务处理,我们有了多进程/多线程的server框架,这也是server最常用的实现方式:

accept进程 - n个epoll进程 - n个worker进程

  1. accpet进程处理到来的连接,并将fd交给各个epoll进程
  2. epoll进程对各fd设置监控事件,当事件触发时通过共享内存等方式,将请求传给各个worker进程
  3. worker进程负责具体的业务逻辑处理并回包应答

以上框架以事件监听、进程池的方式,解决了多任务处理问题,但我们还可以对其作进一步的优化。

 

进程/线程是Linux内核最小的调度单位,一个进程在进行io操作时 (常见于分布式系统中RPC远程调用),其所在的cpu也处于iowait状态。直到后端svr返回,或者该进程的时间片用完、进程被切换到就绪态。是否可以把原本用于iowait的cpu时间片利用起来,发生io操作时让cpu处理新的请求,以提高单核cpu的使用率?

 

协程在用户态下完成切换,由程序员完成调度,结合对socket类/io操作类函数挂钩子、添加事件监听,为以上问题提供了解决方法。

 

用户态下上下文切换

Linux提供了接口用于用户态下保存进程上下文信息,这也是实现协程的基础:

  • getcontext(ucontext_t *ucp): 获取当前进程/线程上下文信息,存储到ucp中
  • makecontext(ucontext_t *ucp, void (*func)(), int argc, ...): 将func关联到上下文ucp
  • setcontext(const ucontext_t *ucp): 将上下文设置为ucp
  • swapcontext(ucontext_t *oucp, ucontext_t *ucp): 进行上下文切换,将当前上下文保存到oucp中,切换到ucp

以上函数与保存上下文的 ucontext_t 结构都在 ucontext.h 中定义,ucontext_t 结构中,我们主要关心两个字段:

  • struct ucontext *uc_link: 协程后继上下文
  • stack_t uc_stack: 保存协程数据的栈空间

stack_t 结构用于保存协程数据,该空间需要事先分配,我们主要关注该结构中的以下两个字段:

  • void __user *ss_sp: 栈头指针
  • size_t ss_size: 栈大小

获取进程上下文并切换的方法,总结有以下几步:

  1. 调用 getcontext(),获取当前上下文
  2. 预分配栈空间,设置 xxx.uc_stack.ss_sp 和 xxx.uc_stack.ss_size 的值
  3. 设置后继上下文环境,即设置 xxx.uc_link 的值
  4. 调用 makecontext(),变更上下文环境
  5. 调用 swapcontext(),完成跳转

 

Socket族函数/io异步处理

当进程使用socket族函数 (connect/send/recv等)、io函数 (read/write等),我们使用协程切换任务前,需对相应的fd设置监听事件,以便io完成后原有逻辑继续执行。

 

对io函数,我们可以事先设置钩子,在真正调用接口前,对相应fd设置事件监听。同样,Linux为我们设置钩子提供了接口,以read()函数为例:

  1. 编写名字为 read() 的函数,该函数先对fd调用epoll函数设置事件监听
  2. read() 中使用dlsym(),调用真正的 read()
  3. 将编写好的文件打包,编译成库文件:gcc -shared -Idl -fPIC prog2.c -o libprog2.so
  4. 执行程序时引用以上库文件:LD_PRELOAD=/home/qspace/lib/libprog2.so ./prog

当在prog程序中调用 read() 时,使用的就是我们实现的 read() 函数。

对于glibc函数设置钩子的方法,可参考:Let's Hook a Librarg Function

 

libco

有了以上准备工作,我们可以构建这样的server框架:

accept进程 - epoll进程(n个epoll协程) - n个worker进程(每个worker进程n个worker协程) 

该框架下,接收请求、业务逻辑处理、应答都可以看做单独的任务,相应的epoll、worker协程事先分配,服务流程如下:

  1. mainloop主循环,负责 i/监听请求事件,有请求则拉起一个worker协程处理;ii/如果timeout时间内没有请求,则处理就绪协程(即io操作已返回) 
  2. worker协程,如果遇到io操作则挂起,对fd加监听事件,让出cpu

libco 提供了以下接口:

  • co_create: 创建协程,可在程序启动时创建各任务协程
  • co_yield: 协程主动让出cpu,调io操作函数后调用
  • co_resume: io操作完成后(触发相应监听事件)调用,使协程继续往下执行

socket族函数(socket/connect/sendto/recv/recvfrom等)、io函数(read/write) 在libco的co_hook_sys_call.cpp中已经重写,以read为例:

复制代码
ssize_t read( int fd, void *buf, size_t nbyte )

{
    struct pollfd pf = { 0 };
    pf.fd = fd;
    pf.events = ( POLLIN | POLLERR | POLLHUP ); 

    int pollret = poll( &pf,1,timeout );  /*对相应fd设置监听事件*/
    ssize_t readret = g_sys_read_func( fd,(char*)buf ,nbyte );   /*真正调用read()*/
    return readret;
}
复制代码

 

小结

由最简单的单任务处理,到多进程/多线程(并行),再到协程(异步),server在不断地往极致方向优化,以更好地利用硬件性能的提升(多核cpu的出现、单核cpu性能不断提升)。

对程序员而言,可时常检视自己的程序,是否做好并行与异步,在硬件性能提升时,程序服务能力可不可以有相应比例的提升。

微信 libco 协程库原理剖析 作者:alexzmzheng同 Go 语言一样,libco 也是提供了同步风格编程模式,同时还能保证系统的高并发能力,本文主要剖析 libco 中的协程原理。简介libco 是微信后台大规... 阅读详情

相关推荐

libco协程学习

libco协程学习 参考资料 协程库libco学习使用入门示例 libco github官网 libco简介 libco是微信后台大规模使用的c/c++协程库,2013年至今稳定运行在微信后台的数万台机器上。 libco通过仅有的几个函数接口 co_create/co_resume/co_yield 再配合 co_poll,可以支持同步或者异步的写法,如线程库一样轻松。同时库里面提供了socket族函数的hook,使得后台逻辑服务几乎不用修改逻辑代码就可以完成异步化改造。 hook函数补充介绍: 钩子

baidu_15952103的博客 1178

协程 及 libco 介绍

libco是腾讯开源的一个协程库,主要应用于微信后台RPC框架,下面我们从为什么使用协程、如何实现协程、libco使用等方面了解协程和libco。 why协程 为什么使用协程,我们先从server框架的实现说起,对于client-server的架构,server最简单的实现: while(1) {accept();recv();do();send();} 串行地接收连接、读取请求、...

weixin_30753873的博客 302

libco:libco是一个用C89编写的协作式多线程库

力宝 libco是一个用C89编写的协作式多线程库。 尽管协作式多线程仅限于单个CPU内核,但其扩展性比抢先式多线程好得多。 对于每秒需要100,000或更多上下文切换的应用程序,抢占式多线程处理所涉及的内核开销最终可能成为应用程序的瓶颈。 libco可以轻松扩展到每秒10,000,000或更多的上下文切换。 理想的用例包括服务器(HTTP,RDBMS)和仿真器(CPU内核等)。 目前,它包含以下后端: x86 CPU amd64 CPU PowerPC CPU PowerPC64 ELFv1 CPU PowerPC64 ELFv2 CPU ARM 32位CPU ARM 64位(AArch64)CPU POSIX平台(setjmp) Windows平台(光纤) 有关详细信息,请参见[doc / targets.md]。 有关文档,请参见[doc / usage

arm64入栈出栈_使用 ARM64 汇编实现共享栈式协程

# 简述大约在半年以前,我曾经了解过协程的相关实现,也看过腾讯后台开源的协程库`libco`,对其中实现协程相关的汇编有很深的印象(`libco`适配的是 x86 平台)。接受了这样的思想,我在自己的毕业设计中,写出一套单片机汇编实现的协程。也自此之后,就有种念头在 iOS 端实现相关的代码。手机端使用的 CPU 跟单片机相差甚远,虽然我用的单片机也是 ARM 平台的,但和手机端 CPU 相比两者...

weixin_39639686的博客 849

C++ 开源协程库 libco——原理及应用1

(1) 有一段程序供其执行,这个是显然是必须的 (2) 有起码的“私有财产”,即线程专属的系统堆栈空间 (3) 有“户口”,操作系统教科书里叫做“进(线)程控制

7.7 数据分析助手:用AI洞察业务数据价值

摘要:AI数据分析助手构建指南 本文介绍了如何构建AI数据分析助手,帮助企业从业务数据中提取价值。系统包含四大核心模块:自然语言理解模块解析用户查询意图,查询规划模块转换为SQL语句,数据可视化模块生成图表,以及洞察生成模块提供深度分析。文章通过销售数据分析助手案例,展示了从数据库准备到自然语言处理的完整实现流程,包括示例代码和系统架构图。该解决方案可降低数据分析门槛,让业务人员直接参与数据探索,提升决策效率。

yonggeit的博客 4093

libco example_thread.cpp分析

程序 /*demo ./example_thread 1 */ #include "co_routine.h" #include "co_routine_inner.h" #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <pthread.h> #inc...

qq_38391187的博客 323

手把手教你用CubeMX给GD32F103点灯、调串口(附完整工程)

本文详细介绍了如何使用CubeMX为GD32F103开发板配置GPIO点灯和串口通信,包含完整的工程创建、代码构建和测试流程。特别强调了GD32与STM32的差异点及常见避坑技巧,帮助开发者快速上手GD32开发。

weixin_42566424的博客 313

coctx_swap.S、coctx.h、coctx.cpp上下文切换(汇编)—— libco源码分析、学习笔记

博客一级目录 二级目录——libco源码分析/学习笔记 参考大牛博客:传送门 coctx_swap.S大概功能 分析文件:coctx_swap.S、coctx.h、coctx.cpp 协程的调度和线程是很类似的。也需要保存和恢复上下文,这就要牵扯到各种寄存器了,而牵扯到寄存器,就不得不使用汇编指令。coctx_swap.S文件内实现的功能是协程之间上下文保存和切换。 贴一遍代码: ...

GreyBtfly的博客 1868

Echarts之风力风速玫瑰图

风力风速玫瑰图前言改进之路代码如下总结导出与导入 前言 今天上班收到任务,我们老大让我研究一下这个“风速风向玫瑰图”,还说这个是百度的雷达图的变异体,于是乎我直接找的雷达图,但是雷达图没有这种柱形的,都是点线,然后我又找了好久,最后突然在echarts官网上面看到了图1-2,才终于有了思路,原来这个图不是雷达图的变异体,而是极坐标系下的堆叠柱状图,于是就开始我的“改进”之路了。 图1-1 改进之路...

qq_38776605的博客 1万+

【异常】Claude Code CLI 模型调用异常 There‘s an issue with the selected model (claude-sonnet-4-6). It may not

摘要: Claude Code CLI v2.1.45版本存在适配缺陷,导致调用claude-sonnet-4-6模型时触发"模型不存在"的误报错误(跨Windows/Linux平台)。该问题为版本回归类异常,非模型或账户权限问题。解决方案包括:1) 校验模型名称格式为claude-sonnet-4-6;2) 降级至v2.1.34或等待官方修复;3) 检查API配置有效性;4) 通过CLI交互界面手动选择模型;5) 临时切换同系列可用模型。官方已确认该bug并将发布修复版本。

奶爸的编程之路,也就一周冷个三天 6390

libco源码解析(7) read,write与条件变量

引言 我挑选了几个比较有代表性的hook后的函数来说明hook后的函数具体干了什么,其他的函数也基本是大同小异。当然至此还是没有讨论hook机制,就放在下一篇文章中吧。 再看这些函数之前我们要知道为什么需要hook,当用户创建阻塞套接字的时候,如果操作了这些套接字会导致线程切换,这不是我们希望看到的,我们希望能够在用户无感的情况下把把同步的操作替换为异步。这需要我们在调用系统调用的时候加一些代码,这也是使用hook的原因。 read typedef ssize_t (*read_pfn_t)(int fil

李兆龙的博客 1391

重复点击提交、产生多笔数据、保持数据只操作一次---->接口幂等性校验

幂等校验一、工作真实场景 + 常出现场景二、工作解决方案 + 百度解决方案 一、工作真实场景 + 常出现场景 真实场景:在一次工作中进行成品出库创建成品出库单时,手抖了一下,重复点击了两次确定(提交表单)。结果很神奇的发现居然产生了两笔一模一样的数据(流水号都一样),当时就很懵逼,稍作思考,想想应该是在同一时刻创建了两个出库单。感觉很有意思(因为之前没有遇到过,写代码的时候也没有考虑到这个问题的发生),后面换了一种方式复现场景:提交表单时多次点击Enter按钮,还是会产生多笔重复数据。 常见场景: 订单接

私聊前往站内信:https://i.youkuaiyun.com/#/msg/chat/weixin_44976692 6万+

C++ libco 介绍与应用

文章目录导论准备知识协程的背景libco 使用简介libco 协程关键数据结构及其关系libco 协程的生命周期事件驱动与协程调度libco 总结 导论   使用 C++ 来编写高性能的网络服务器程序,从来都不是一件很容易的事。   在没有应用任何网络框架的情况下,从 epoll/kqueue 直接码起的时候更是如此。即便使用 libevent、libev 这样事件驱动的网络框架去构建你的服务,程序结构依然不会简单。   为何会这样?因为这类框架提供的都是非阻塞式的、异步的编程方式,这需要思维方式的转变。

qq_41033011的博客 6560

A算法的蒙特卡洛树搜索

A*算法的蒙特卡洛树搜索 作者:禅与计算机程序设计艺术 1. 背景介绍 在人工智能和游戏开发领域,搜索算法是一个非常重要的研究方向。其中A算法和蒙特卡洛树搜索是两种广泛应用的经典算法。A算法是一种启发式搜索算法,通过评估各个节点到目标节点的启发式代价来引导搜索方向,在

AI天才研究院 1747

《网络安全自学教程》- 802.1x协议

802.1x协议架构,工作原理/认证流程,认证方式,MAB认证,触发认证的三种方式,EAP报文格式,EAPOL报文格式

wangyuxiang946的博客 2万+

C++ 开源协程库 libco——原理及应用

1 导论 使用 C++ 来编写高性能的网络服务器程序,从来都不是件很容易的事情。在没有 应用任何网络框架,从 epoll/kqueue 直接码起的时候尤其如此。即便使用 libevent, libev 这样事件驱动的网络框架去构建你的服务,程序结构依然不会很简单。为何会这样?因 为这类框架提供的都是非阻塞式的、异步的编程接口,异步的编程方式,这需要思维方 式的转变。为什么 golang 近几年能够...

cool grass's blog 5334

添加USB wifi驱动到RK3568

在日常开发中我们经常需要用到wifi功能,一般来说soc厂家都会事先做好了几个厂家的wifi驱动在内核源码目录下,我们只需要按原理图配置对应的设备树即可。常用的wifi的接口有:USBSDIOPCIE下面来介绍这这种接口是如何使用wifi芯片。提示:以下是本篇文章正文内容,下面案例可供参考本小节介绍了一个配置一个USBwifi驱动的整个流程,并没有介绍到SDIO,下小节基于AP6256介绍如何使用。

qq_24093081的博客 2049

协程库libco学习使用入门示例

简介 libco是微信后台大规模使用的c/c++协程库,2013年至今稳定运行在微信后台的数万台机器上。 libco通过仅有的几个函数接口 co_create/co_resume/co_yield 再配合 co_poll,可以支持同步或者异步的写法,如线程库一样轻松。同时库里面提供了socket族函数的hook,使得后台逻辑服务几乎不用修改逻辑代码就可以完成异步化改造。 libco是一个源码简洁而...

Arbboter的专栏 7830

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

协程实现原理——以libco为例

协程是个很重要的概念,对于向我一样的在校生而言,或者对进程和线程比较熟悉,对协程一般不太理解,协程也确实不好理解,本篇文章希望以通俗易懂的方式讲述协程,并且以著名的libco为例,看看核心的协程实现代码。协程的概念非常不好理解,虽然网上文章众多,但大多数都给人一种云里雾里的感觉,对协程的理解也有一些不同的观点,我个人认为协程就是一种可以“暂停和恢复执行”的特殊函数。

新人博主,多多关照 1678

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

协程 及 libco介绍

libco 是腾讯开源的一个协程库,主要应用于微信后台RPC框架,下面我们从为什么使用协程、如何实现协程、libco使用等方面了解协程和libco。   why协程 为什么使用协程,我们先从server框架的实现说起,对于client-server的架构,se...

cool grass's blog 939

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

libco简介

好久都没在优快云上发博客了,大概两年了吧,看着以前写的博客,感觉自己更像是个前端工程师了,其实工作上我应该算是后端的吧。最近换了一份工作,新公司用到一个叫Colib的库,也在GitHub上开源了,虽然开源之后并没有人怎么维护,但这里面的代码的确也在线上用,这里面的思想也是挺有趣儿的,就研究了一下,也算是和后端相关了 https://github.com/Tencent/libco  1. 协...

ZZ的博客 1万+

libco协程切换原理详解

一 备用知识 之前不止一次的把libco的源码下下来看,但是每次看到协程切换汇编部分都放弃了,大学那点仅有的汇编基础也忘的一干二净,更不堪的是百度搜到的libco相关文章也看不懂,最近决定静下心来看一些相关的东西,终于像啃骨头一样把这块东西搞明白了。在网下阅读之前请先务必看懂下面的内容。 第一部分 汇编基础 1 CSAPP阅读笔记-汇编语言初探(数据传送类指令):CSAPP阅读笔记-汇编语言初探(数据传送类指令) 2 CSAPP阅读笔记-汇编语言初探(算术和逻辑操作类指令)...

D_Guco的专栏 2425

C++libco协程

什么是协程? 协程:协同运行的子程序(函数); 协程:协同运行的进程(shell中的概念) 协程是能暂停执行以在之后恢复的函数。协程是无栈的:它们通过返回到调用方暂停执行,并且从栈分离存储恢复所要求的数据。这允许编写异步执行的顺序代码(例如不使用显式的回调来处理非阻塞 I/O),还支持对惰性计算的无限序列上的算法及其他用途。 协程可以被视为提供特殊控制流的语言级构造。 与抢占式线程相比,协程开关是协作的(程序员控制开关何时发生)。协程开关中不涉及内核。 单核情况下,线程和协程都是不能并行的,但是谁快?是协程

NINE_world的博客 1320

协程库libco

协程库libco libco是微信后台大规模使用的c/c++协程库,2013年至今稳定运行在微信后台的数万台机器上。libco在2013年的时候作为腾讯六大开源项目首次开源,最近做了一次较大的更新。libco支持后台敏捷的同步风格编程模式,同时提供系统的高并发能力。 libco支持的特性 支持CGI框架,轻松构建web服务(New); 支持gethost

chenglinhust的专栏 4730

libco协程库原理解析与应用

       最近在准备一个libco协程库原理简析与应用的分享,顺便就整理下写个博客,一方面加深下自己对协程库的理解,另一方面也希望能对想了解协程的学者有所帮助。废话不多说了,言归正传吧。        想去剖析libco协程库的实现原理,首先我们要了解下什么是协程。维基百科上给协程的定义是协程(coroutine)又称微线程,是一个无优先级的子程序(函数)调度组件,允许子程序在特定的地方挂起和...

hhyjiayou的博客 3632
上一篇: [转]协程实现的基础
下一篇: [转]互联网的长在线、心跳和断线重连
编程小问号
博客等级 码龄15年 137粉丝 16原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值