“最近在做F-Stack相关内容,F-Stack协议栈单线程独占异步轮询网卡,所以要求异步。但是又有多线程需要利用F-Stack进行发包,并且发包ff_sendto需要由F-Stack线程调用,就这样引入了此篇命题。”
/* 管道两头的FD */static int pipe_fd[2] = {-1};/* 管道两头的打开方式 */static FILE *pipe_in_fp = NULL;static FILE *pipe_out_fp = NULL;
关于异步多路复用,我们采用epoll(关于epoll也进行过讲解:浅谈epoll)。
/* epoll fd */static int epoll_fd = -1;/* epoll events */static struct epoll_event epoll_evs[MAX_EVENTS];
使用连个线程向管道发送数据,一个线程用于管道数据的接收。
/* 管道两头的线程 */static pthread_t tpipe_in1;static pthread_t tpipe_in2;static pthread_t tpipe_out;
初始化管道相当简单。
/* 初始化管道 */void pipe_initial() { pipe(pipe_fd); /* 打开管道两端 */ pipe_in_fp = fdopen(pipe_fd[1], "w"); pipe_out_fp = fdopen(pipe_fd[0], "r");}
使用epoll对管道出口进行监听。
/* 初始化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);}
接下来,启动线程。
/* 启动任务 */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"); }
按照以上循序进行初始化。
/* 主函数 */int main () { pipe_initial();/* 初始化管道 */ epoll_initial();/* 初始化epoll */ thread_execute();/* 开始执行任务 */ main_loop();/*主循环,由主进程执行 */}
--往期回顾--浅谈epollF-Stack实现UDP服务端、客户端吞吐量测试F-Stack DPDK lcore与cpe_set的配置点击“阅读原文”,查看源码。