目录
架构
代码
相关阅读
“最近在做F-Stack相关内容,F-Stack协议栈单线程独占异步轮询网卡,所以要求异步。但是又有多线程需要利用F-Stack进行发包,并且发包ff_sendto需要由F-Stack线程调用,就这样引入了此篇命题。”
架构
代码
/**
* 异步管道
* rongtao@sylincom.com
* 2020年8月4日11:11:03
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <pthread.h>
#include <sys/epoll.h>
#include <string.h>
/* 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();/*主循环,由主进程执行 */
}