高性能:协程

1.什么是协程?

        协程是一个“轻量级线程”,更倾向解释为一个特殊的函数。

2.为什么要用协程?

        在同步的编程方式,逻辑清晰易于编写,然而性能的却不如,异步的编程方式,异步的编程方式,逻辑不够清晰,性能较高。为了结合两者的优点:实现同步的编程方式异步的性能,由此协程就应运而生。

3.setjmp/longjmp实现函数的切换代码

#include <stdio.h>
#include <setjmp.h>

jmp_buf env;
void func(int arg)
{
    printf("func: %d\n",arg);
    longjmp(env,++arg);
}
int main()
{
   
    int ret=setjmp(env);
    if(0==ret){
        func(ret);
    }else if(1==ret){
        func(ret);
    }else if(2==ret){
        func(ret);
    } 
    return 0;
}

4.hook的代码


#define _GNU_SOURCE
#include <dlfcn.h>

#include <stdio.h>
#include <ucontext.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>

#include <sys/socket.h>
#include <errno.h>
#include <netinet/in.h>


#include <pthread.h>
#include <sys/poll.h>
#include <sys/epoll.h>



#define HOOK 1
#if HOOK
typedef ssize_t (*read_t)(int fd ,void*buf,size_t count);
read_t read_f=NULL;

typedef ssize_t (*write_t)(int fd ,void*buf,size_t count);
write_t write_f=NULL;

ssize_t read(int fd,void *buf,size_t count){

    struct pollfd fds[1]={0};

    fds[0].fd=fd;
    fds[0].events=POLLIN;
    int res=poll(fds,1,0);
    if(res<=0){//事件尚未就绪?
        // fd --> epoll_ctl();
        //swapcontext();
    }
    ssize_t ret=read_f(fd,buf,count);
    printf("read:%s \n",( char *)buf);
    return ret;

}

ssize_t writre(int fd,void *buf,size_t count){
    
    printf("write: %s\n", ( char *)buf);

	return write_f(fd, buf, count);

}

void init_hook(void){
    if(!read_f){
        read_f=dlsym(RTLD_NEXT,"read");
    }

     if(!write_f){
        write_f=dlsym(RTLD_NEXT,"write");
    }
}
#endif

int main()
{
    init_hook();

    int socketfd=socket(AF_INET,SOCK_STREAM,0);
    struct sockaddr_in serveraddr;

    memset(&serveraddr,0,sizeof(serveraddr));
    serveraddr.sin_family=AF_INET;
    serveraddr.sin_addr.s_addr=htons(INADDR_ANY);
    serveraddr.sin_port=htons(2048);
    if(-1==bind(socketfd,(struct sockaddr*)&serveraddr,sizeof(struct sockaddr)))
    {
        perror("bind error:");
        return -1;
    }
    listen(socketfd,10);

    struct sockaddr_in clientaddr;
    socklen_t len=sizeof(clientaddr);
    int clientfd =accept(socketfd,(struct sockaddr*)&clientaddr,&len);
    printf("accept");

    while(1)
    {
        char buffer[128]={0};
        int count =read(clientfd,buffer,128);
        if(0==count )
        {
            break;
        }
        write(clientfd,buffer,count);
        printf("sockfd: %d, clientfd: %d, count: %d, buffer: %s\n", socketfd, clientfd, count, buffer);
    }

    return 0;
    
}

5.ucontext代码实现

#define _GNU_SOURCE

#include <dlfcn.h>

#include <stdio.h>
#include <ucontext.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>

ucontext_t ctx[3];
ucontext_t main_ctx;

int count=0;

typedef ssize_t (*read_t)(int fd, void *buf, size_t count);
read_t read_f = NULL;

typedef ssize_t (*write_t)(int fd, const void *buf, size_t count);
write_t write_f = NULL;

ssize_t read(int fd, void *buf, size_t count) {

	ssize_t ret = read_f(fd, buf, count);
	printf("read: %s\n", (char *)buf);
	return ret;
}


ssize_t write(int fd, const void *buf, size_t count) {

	printf("write: %s\n", (const char *)buf);

	return write_f(fd, buf, count);
}

void init_hook() {

	if (!read_f) {
		read_f = dlsym(RTLD_NEXT, "read");
	}

	
	if (!write_f) {
		write_f = dlsym(RTLD_NEXT, "write");
	}

}

//coroutine 1
void func1(void){
    while(count++<30){
        printf("1\n");

        swapcontext(&ctx[0],&main_ctx);
        printf("4\n");

    }
}

//coroutine 2
void func2(void){
    while(count++<30){
        printf("2\n");

        swapcontext(&ctx[1],&main_ctx);
        printf("5\n");
        
    }
}

//coroutine 3
void func3(void){
    while(count++<30){
        printf("3\n");

        swapcontext(&ctx[2],&main_ctx);
        printf("6\n");
        
    }
}

int main(){
    
    init_hook();

    int fd =open("a.txt",O_CREAT|O_RDWR);
    if(fd<0){
        return -1;
    }

    char *str="Hello ,LuGaoyang!";
    write(fd,str,strlen(str));

    char buff[128]={0};
    read(fd,buff,128);

    printf("buffer :%s",buff);

#if 1
    char stack1[2048]={0};
    char stack2[2048]={0};
    char stack3[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_link=&main_ctx;
    ctx[1].uc_stack.ss_size=sizeof(stack2);
    makecontext(&ctx[1],func2,0);

     getcontext(&ctx[2]);
    ctx[2].uc_stack.ss_sp=stack3;
    ctx[2].uc_stack.ss_size=sizeof(stack3);
    ctx[2].uc_link=&main_ctx;
    makecontext(&ctx[2],func3,0);

    printf("swapcontext\n");
	//int i = 30;
	
	while (count <= 30) { // scheduler
		swapcontext(&main_ctx, &ctx[count%3]);
	}

	printf("\n");

#endif

}

6.协程的代码

         关于协程的代码具体实现见下链接:

https://github.com/wangbojing/NtyCoicon-default.png?t=N7T8https://github.com/wangbojing/NtyCo

学习链接:https://xxetb.xetslk.com/s/4cnbDc

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值