Linux下实现多线程异步管道

目录

架构

代码

相关阅读


​“最近在做F-Stack相关内容,F-Stack协议栈单线程独占异步轮询网卡,所以要求异步​。但是又有多线程需要利用F-Stack进行发包,并且发包ff_sendto需要由F-Stack线程调用,就这样引入了​此篇命题。”

架构

Linux下实现多线程异步管道_第1张图片

代码

/**
 *	异步管道
 *	[email protected]
 *	2020年8月4日11:11:03
 */

#include 
#include 
#include 
#include 
#define _GNU_SOURCE             /* See feature_test_macros(7) */
#include 
#include 
#include 

/* epoll最大event数 */
#define MAX_EVENTS 64

/* 管道两头的线程 */
static pthread_t tpipe_in1;
static pthread_t tpipe_in2;
static pthread_t tpipe_out;

/* 管道两头的FD */
static int pipe_fd[2] = {-1};

/* 管道两头的打开方式 */
static FILE *pipe_in_fp = NULL;
static FILE *pipe_out_fp = NULL;

/* epoll fd */
static int epoll_fd = -1;

/* epoll events */
static struct epoll_event epoll_evs[MAX_EVENTS];


/* 向管道发送数据,数据将从另一端输出 */
inline int mysendto(void *buf, size_t size) {
    int n = write(fileno(pipe_in_fp), buf, size);
//    printf("<< pipe << %s\n", buf);
}

/* 管道进口任务1 */
void * thread_pipe_in(void*arg) {

    char threadname[16];
    unsigned long int tid = pthread_self();
    pthread_getname_np(pthread_self(), threadname, 16);
    
	while(1) {
		usleep(tid%521233);
        char buf[100] = {0};
        sprintf(buf, "I'm thread %s-%lu.", threadname, tid);
        mysendto(buf, strlen(buf));
	}
}

/* 管道出口任务主循环 */
int pipe_out_loop(void*arg) {

    static char buffer[1024] = {0};
    int nr_events = 0, iev;

    nr_events = epoll_wait(epoll_fd, epoll_evs, MAX_EVENTS, -1);
    
    for(iev = 0; iev < nr_events; iev ++) {
        if(epoll_evs[iev].data.fd == fileno(pipe_out_fp) 
            && epoll_evs[iev].events&EPOLLIN) {
            
            int n = read(fileno(pipe_out_fp), buffer, 1024);
            printf(">> pipe >> %s\n", buffer);
            
        }
    }
    
}

/* 管道出口任务 */
void * thread_pipe_out(void*arg) {
    
	while(1) {
        /* 该loop类比于fstack的ff_run(loop, NULL) */
        pipe_out_loop(NULL);
	}
}

/* 初始化管道 */
void pipe_initial() {

	pipe(pipe_fd);
    
	/* 打开管道两端 */
    pipe_in_fp = fdopen(pipe_fd[1], "w");
    pipe_out_fp = fdopen(pipe_fd[0], "r");

}

/* 启动任务 */
void thread_execute() {

	pthread_create(&tpipe_in1, NULL, thread_pipe_in, NULL);
	pthread_create(&tpipe_in2, NULL, thread_pipe_in, NULL);

	pthread_create(&tpipe_out, NULL, thread_pipe_out, NULL);

    pthread_setname_np(tpipe_in1, "pipe-in1");
	pthread_setname_np(tpipe_in2, "pipe-in2");
    
	pthread_setname_np(tpipe_out, "pipe-out");
    
}

/* 主进程loop */
void main_loop() {

	while(1) {
		sleep(1);
        /* do nothing */
	}
}

/* 初始化epoll */
void epoll_initial() {
	epoll_fd = epoll_create(1);
	struct epoll_event pipe_ev;
	pipe_ev.data.fd = fileno(pipe_out_fp);
	pipe_ev.events = EPOLLIN;
	epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fileno(pipe_out_fp), &pipe_ev);
}

/* 主函数 */
int main () {

	pipe_initial();/* 初始化管道 */
	
	epoll_initial();/* 初始化epoll */

	thread_execute();/* 开始执行任务 */

    main_loop();/*主循环,由主进程执行 */
}

相关阅读

《Linux异步管道多线程速率测试》https://rtoax.blog.csdn.net/article/details/107812606

你可能感兴趣的:(基础知识)