【项目】----基于C语言实现协程

1.协程简介

提起协程,我们不免要和多进程和多线程进行比较,我粗浅的理解为用户态的轻量级线程;并且由程序员控制调度策略,非抢占式的特点使得不用加锁,用户态控制执行流,相比于系统调用非常简便。

关于多线程和多进程我找了一张图
在这里插入图片描述

2.设计思路

协程的实现,需要一个协程结构体和一个调度器。
协程结构体:回调函数,回调函数参数,协程状态,上下文信息,栈
协程调度器结构体:指向协程数据的指针,当前运行协程id,协程最大数,主函数上下文信息

我们需要用到的函数:getcontext、setcontext、makecontext、swapcontext
int getcontext(ucontext_t *ucp)—保存当前寄存器信息到ucp中

int setcontext(const ucontext_t *ucp)—将ucp中保存的寄存器信息恢复

void makecontext(ucontext_t *ucp, void (*func)(), int argc)
在这里插入图片描述

改造ucp上下文信息,下一步执行func,func执行完毕之后执行 link之后的函数

int swapcontext(ucontext_t *oucp, ucontext_t *ucp)
将oucp寄存器信息保存起来,将ucp的寄存器信息加载到CPU中

3.代码实现
  • main.c
#include"coroutine.h"

//获取监听描述符
int tcp_init()
{
   
    printf(" tcp_init()\n");
    //创建套接字
    int lfd = socket(AF_INET,SOCK_STREAM,0);
    if (lfd == -1)
    {
   
        perror("socket");
        exit(1);
    }
    //设置套接字复用
    int op = 1;
    setsockopt(lfd,SOL_SOCKET,SO_REUSEADDR,&op,sizeof(op));
    //绑定地址信息
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(9999);
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    int fd = bind(lfd,(struct sockaddr*)&addr,sizeof(addr));
    if (fd == -1)
    {
   
        perror("bind");
        exit(1);
    }
    //开始监听
    listen(lfd,SOMAXCONN);

    printf("tcp_init-> lfd = %d\n",lfd);
    return lfd;
}

//设置成非阻塞
void set_nonblock(int fd)
{
   
    //获取描述符的访问模式和文件状态
    int flgs = fcntl(fd, F_GETFL, 0);
    //设置为非阻塞
    flgs |= O_NONBLOCK;
    fcntl(fd,F_SETFL, flgs);
}

//获取新连接
void accept_conn(int lfd, schedule_t* s, int co_ids[], void*(*call_back)(schedule_t* s, void *argc))
{
   
    while (1)
    {
   
        sleep(3);
        int cfd = accept(lfd,NULL, NULL);
        printf("accept_conn-> cfd = %d\n",cfd);
        if (cfd > 0)
        {
   
            set_nonblock(cfd);//设置为非阻塞
            int argc[] = {
   lfd,cfd};
            int id = coroutine_create(s,call_back,argc);//创建协程,并且设置好上下文等信息
            int i=0;
            for (i=0 ;i<CORSZ; ++i)
            {
   
                if (co_ids[i] == -1)
                {
   
                    co_ids[i] = id;
                    break;
                }
            }
            if (i == CORSZ)
            {
   
                printf("连接太多\n");
            }
            printf("accept_conn -> coroutine_running\n");
            //启动协程
            coroutine_running(s,id);
        }
        else 
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值