协程的设计与使用1(acl/libco)

一、概述

传统基于事件驱动的异步网络服务优势高、性能高、CPU利用率高,但编写困难,业务逻辑编码被拆分得支离破碎,难以维护与排查故障。
使用协程可以做到同步编码,异步执行,性能与异步通信查是一个数量级(底层实现其实都一样),但编写并发任务很方便。
acl 中lib_fiber封装了协程的实现方式, libco是腾讯实现的一款协程库。总的来说,acl的协程库做了大量的封装优化,libco看起来则更加简单易懂。

二、协程概述

  • 什么是协程?
    微线程,用户态线程、纤程。
    进程是分配资源的最小单位,线程是CPU调度的最小单位,协程是逻辑处理的最小单位。举个简单的例子,一个线程可以只处理一个tcp连接,也可以同时处理多个tcp连接请求(使用epoll等),但同一时刻,只能处理一个逻辑单元。

  • 协程切换?
    – 本协程上下文保存(寄存器/内存, 栈)
    – 目标协程上下文恢复
    – 指令跳转

  • 实现协程的关键技术?
    – 协程调度
    – 协程上下文切换
    – hook关键函数

  • 协程调度:
    当前一般使用epool/pool/select 等 用于底层调度;
  • 协程上下文切换:
    协程上下文切换,libco,以及acl都编写了底层汇编代码,但使用make_context等也可以实现;
  • hook 关键函数:
    协程Hook函数主要hook与网络相关的函数,如sleep, recv等;

下文就是模拟了协程的几个关键步骤实现的伪代码,其中没有实现调度。

#include "stdio.h"
#include "stdlib.h"
 
#define FIBER_STATUS_READY 1
#define FIBER_STATUS_RUNNING 2
#define FIBER_STATUS_EXITING 3
ucontenx_t ctx[3];

void run2();
void run1();
void shecdule(int from_id, int to_id);
int current_id = 1;

typedef unsigned (*sleep_fn)(unsigned int seconds)
static sleep_fn __sys_sleep = NULL;
__sys_sleep = (sleep_fn)dlsym(RTLD_NEXT, "sleep");
unsinged int sleep(unsigned int seconds) {
    if (!var_hool_sys_api) {
         return sys_sleep(1); //调用系统sleep(1);
    }
    sys_sleep(1);
    if (curent_id == 1) {
    	shecdule(1,2);
    } else {
      shecdule(2,1);
    }
}

void run1()  
{
   while (1) {
       int id = 1;
       current_id = id;
       printf("id is %d \r\n", id);
       sleep(1);
       printf("end sleep id is %d \r\n", id);
   }
}
void run2()
{
  while (1) {
    int id = 2;
    current_id = id;
    printf("id is %s \r\m", id);
    sleep(1);
    //schedule(2,1);
    printf("sleep end id is  %d \r\n", id);
}
}
void schedule(int from_id, int to_id) {
    swapcontext(&ctx[from_id], &ctx[to_id]);
}
int main()
{
   char st1[8192];
   char st2[8192];
   getcontext(&ctx[1]);
    ctx[1].uc_stack.ss_sp = st1; 
    ctx[1].uc_stack.ss_size = sizeof st1;
    ctx[1].uc_link = &ctx[0];
    makecontext(&ctx[1], run1, 0);
    printf("fiber 1 is ready\r\n");
    getcontext(&ctx[2]);
    ctx[2].uc_stack.ss_sp = st2;
    ctx[2].uc_stack.ss_size = sizeof st2;
    ctx[2].uc_link = &ctx[1];
    makecontext(&ctx[2], run2, 0);
    printf("fiber 2 is ready \r\n");
    swapcontext(&ctx[0], &ctx[2]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值