epoll_pool_test

C++高性能网络服务器实战:从Reactor模式到epoll并发编程 网络编程是计算机系统领域的核心基础,其核心在于高效管理多个并发连接。I/O多路复用技术通过单线程监控多个文件描述符状态变化,解决了传统阻塞模型的性能瓶颈。在Linux环境下,epoll作为高性能I/O事件通知机制,采用事件驱动架构显著提升并发处理能力。这项技术的工程价值在于能够构建高吞吐、低延迟的网络服务,广泛应用于Web服务器、实时通信和分布式系统等场景。本文以epoll和Reactor模式为核心,结合线程池与内存池优化,详细解析如何实现一个支持C10K级别并发的高性能HTTP服务器,为构建稳定可靠的网络 阅读详情

实现流程

  1. 网络初始化,创建服务器socket,绑定服务器地址,返回服务器sock

  2. epoll监听树初始化,创建监听树,监听服务器socket,返回监听树fd

  3. pool初始化,pool创建存储空间,pool扩容/缩容参数初始化,pool任务tid数组创建存储空间,pool条件变量初始化,pool任务队列创建存储空间,相关参数初始化,循环创建最小数量任务。创建管理任务,创建打印任务;返回pool指针

  4. epoll监听,如果线程池没有关闭循环监听,处理返回的就绪socket,如果是服务器sock,task添加为accept;如果不是,task添加为recv,处理完毕调用 producer将任务添加到线程执行。循环结束回收服务器sock

  5. 生产者添加任务,如果线程池在运行,检测。如果当前任务等一最大任务,队列满,生产者等待,如果线程池关闭,解锁。队伍不满,给队列头指针添加任务,头指针后移1,当前指针++,pthread_kill发送SIGUSR1打印消息,通知消费者唤醒,解锁。

  6. 消费者分离线程,取线程池参数,线程池没有关闭循环获取任务执行。加锁,如果cur不为0(不为空),唤醒消费者。如果线程池关闭,解锁退出。如果需要销毁当前线程,活跃数量-1,销毁数量-1,从线程tid数组中移除当前线程,释放锁,退出当前线程,发送SIGUSR1信号。

    获取队列尾任务,队列尾+1,busy+1,唤醒生产者,解锁。执行任务,加锁,busy-1,发送SIGUSR1信号,解锁。

    如果线程池关闭返回NULL

  7. recv接收任务,取出参数客户sock,使用用户sock接收数据。如果接收成功,检查是否是time,是取时间,发送时间buf,不是时间,发送提示信息,清空接收buf,时间buf。如果接收失败,客户端退出,取消监听,关闭客户端sock,打印消息。

  8. accept任务,取出服务器sock,接收连接,如果成功,添加监听,打印客户端连接ip

  9. manager任务,线程分离,取出pool*。线程池没有关闭的时候,上锁,取出线程忙闲,大小,当前指针参数,解锁。如果当前数量>可用||忙占比>70%&&max>live+min,扩容min,循环如果tids数组不为空,循环添加min数量thread,live++,解锁。

    如果现存>2倍忙&&现有-min>=min,缩容。加锁,exit+10,解锁,循环挂起消费者

    如果线程池关闭,返回NULL

  10. 线程销毁,取出pool参数,销毁条件变量,销毁锁,释放队列,释放tids,释放pool

  11. 设置信号,备份信号。信号设为空,添加信号,设置屏蔽码并备份。

    初始化网络,初始化epoll,初始化pool,开始epoll监听

    如果线程池关闭,销毁线程。

  12. 打印线程池信息

  13. 打印线程。分离线程,取出pool参数。设置信号行为,设为空,处理函数设置为打印函数,参数设置为0。绑定信号SIGUSR1与信号行为,备份。设置信号屏蔽信息。

    如果线程池没有关闭,休眠1s。如果关闭,线程退出。

pool.h

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>
#include <signal.h>
#include <sys/epoll.h>
#include <errno.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>

typedef struct
{
	void* arg;
	void* (*busines)(void*);
}bs_t;

typedef struct
{
	int thread_shutdown;
	int thread_alive;
	int thread_busy;
	int thread_max;
	int thread_min;
	int thread_killnum;

	bs_t* queue;
	int front;
	int rear;
	int qmax;
	int cur;

	pthread_t *ctids;
	pthread_t mid;

	pthread_cond_t notEmpty;
	pthread_cond_t notFull;
}pool_t;

int epfd;
pthread_t ptid;
pthread_mutex_t lock;
pool_t* ptr;

int net_init(char* ip,int port);
int epoll_init(int sockfd,int listen_num);
void epoll_listen(int sockfd,pool_t* pt);
void producer_add(pool_t* pt,bs_t tmp);

pool_t* pool_init(int tmax,int tmin,int qmax);
void* manager(void* arg);
void* customer(void* arg);
void* recv_busines(void* arg);
void* accept_busines(void* arg);
void sig_usr(int n);
void* thread_printf(void* arg);
void thread_destroy(void* arg);

accept_task

#include <pool.h>

void* accept_busines(void* arg)
{
	int sockfd=*(int*)arg;
	int clientsock;
	struct sockaddr_in clientaddr;
	socklen_t len=sizeof(clientaddr);
	if((clientsock=accept(sockfd,(struct sockaddr*)&clientaddr,&len))==-1)
	{
		perror("accept_busines accept failed");
		exit(0);
	}
	char ip[16];
	char response[1024];
	bzero(response,1024);
	bzero(ip,16);
	struct epoll_event node;
	node.data.fd=clientsock;
	node.events=EPOLLIN|EPOLLET;
	if((epoll_ctl(epfd,EPOLL_CTL_ADD,clientsock,&node))!=0)
	{
		perror("accept_busines epoll_ctl failed");
		exit(0);
	}
	sprintf(response,"connection successful\n");
	inet_ntop(AF_INET,&clientaddr.sin_addr.s_addr,ip,16);
	send(clientsock,response,strlen(response),MSG_NOSIGNAL);
	return NULL;
}

recv_task

#include <pool.h>

void *recv_busines(void* arg)
{
	int sockfd=*(int*)arg;
	ssize_t recvNum;
	char recvBuf[1024];
	char ctime[1024];
	time_t tp;
	char* msg="tryagain\n";
	if((recvNum=recv(sockfd,recvBuf,sizeof(recvBuf),MSG_DONTWAIT))>0)
	{
		if((strcmp(recvBuf,"time\n"))==0)
		{
			tp=time(NULL);
			ctime_r(&tp,ctime);
			send(sockfd,ctime,strlen(ctime),MSG_NOSIGNAL);
		}
		else
		{
			send(sockfd,msg,strlen(msg),MSG_NOSIGNAL);
		}
		sleep(10);
		bzero(ctime,sizeof(ctime));
		bzero(recvBuf,sizeof(recvBuf));
	}
	else if(recvNum==0)
	{
		
		if((epoll_ctl(epfd,EPOLL_CTL_DEL,sockfd,NULL))==-1)
		{
			perror("recv_busines epoll_ctl del failed");
			exit(0);
		}
		close(sockfd);
		printf("client exit...\n");
	}
}

net_init

#include <pool.h>

int net_init(char* ip,int port)
{
	int sockfd;
	if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
	{
		perror("net_init socket failed");
		return -1;
	}
	struct sockaddr_in addr;
	addr.sin_family=AF_INET;
	addr.sin_port=htons(port);
	addr.sin_addr.s_addr=htonl(INADDR_ANY);
	if((bind(sockfd,(struct sockaddr*)&addr,sizeof(addr)))==-1)
	{
		perror("net_init bind failed");
		return -1;
	}
	listen(sockfd,128);
	return sockfd;
}

pool_init

#include <pool.h>

pool_t* pool_init(int tmax,int tmin,int qmax)
{
	pool_t* pt;
	if((pt=(pool_t*)malloc(sizeof(pool_t)))==NULL)
	{
		printf("pool_init pool_t malloc failed\n");
		return NULL;
	}
	pt->thread_shutdown=1;
	pt->thread_alive=0;
	pt->thread_busy=0;
	pt->thread_max=tmax;
	pt->thread_min=tmin;
	pt->thread_killnum=0;
	if((pt->queue=(bs_t*)malloc(sizeof(bs_t)*qmax))==NULL)
	{
		printf("pool_init bs_t* malloc failed\n");
		return NULL;
	}
	pt->front=0;
	pt->rear=0;
	pt->qmax=qmax;
	pt->cur=0;
	if((pthread_cond_init(&pt->notEmpty,NULL)!=0)||(pthread_cond_init(&pt->notFull,NULL)!=0)||(pthread_mutex_init(&lock,NULL)!=0))
	{
		printf("pool_init cond or mutex init failed\n");
		return NULL;
	}
	if((pt->ctids=(pthread_t*)malloc(sizeof(pthread_t)*tmax))==NULL)
	{
		printf("pool_init ctids malloc failed\n");
		return NULL;
	}
	bzero(pt->ctids,sizeof(pthread_t)*tmax);
	//yuchuangjian 
	int err;
	for(int i=0;i<tmin;i++)
	{
		if((err=pthread_create(&pt->ctids[i],NULL,customer,(void*)pt))>0)
		{
			printf("pool_init pthread_create customer failed: %s\n",strerror(err));
			return NULL;
		}
		++pt->thread_alive;
	}
	if((err=pthread_create(&pt->mid,NULL,manager,(void*)pt))>0)
	{
		printf("pool_init pthead_create manager failed: %s\n",strerror(err));
		return NULL;
	}
	if((err=pthread_create(&ptid,NULL,thread_printf,(void*)pt))>0)
	{
		printf("pool_init pthread_create thread_printf failed: %s\n",strerror(err));
		return NULL;
	}
	return pt;
}

producer

#include <pool.h>

void producer_add(pool_t* pt,bs_t tmp)
{
	if(pt->thread_shutdown)
	{
		pthread_mutex_lock(&lock);
		while(pt->cur==pt->qmax)
		{
			pthread_cond_wait(&pt->notFull,&lock);
			if(!pt->thread_shutdown)
			{
				pthread_mutex_unlock(&lock);
				printf("producer shut %d,exit...\n",pt->thread_shutdown);
				exit(0);
			}
		}
		pt->queue[pt->front].arg=tmp.arg;
		pt->queue[pt->front].busines=tmp.busines;
		pt->front=(pt->front+1)%pt->qmax;
		++pt->cur;
		pthread_kill(ptid,SIGUSR1);
		pthread_mutex_unlock(&lock);
		pthread_cond_signal(&pt->notEmpty);
	}
}

comsumer

#include <pool.h>

void* customer(void* arg)
{
	pthread_detach(pthread_self());
	pool_t* pt=(pool_t*)arg;
	
	while(pt->thread_shutdown)
	{
		pthread_mutex_lock(&lock);
		while(pt->cur==0)
		{
			pthread_cond_wait(&pt->notEmpty,&lock);
			if(!pt->thread_shutdown)
			{
				printf("customer shutdown %d failed\n",pt->thread_shutdown);
				pthread_mutex_unlock(&lock);
				exit(0);
			}
			if(pt->thread_killnum)
			{
				--pt->thread_alive;
				--pt->thread_killnum;
				int n=pthread_self();
				for(int i=0;i<pt->thread_max;i++)
				{
					if(pt->ctids[i]==n)
					{
						pt->ctids[i]=0;
						break;
					}
				}
				pthread_mutex_unlock(&lock);
				pthread_exit(NULL);
				pthread_kill(ptid,SIGUSR1);
			}
		}
		bs_t tmp;
		//huoqurenwu
		tmp.arg=pt->queue[pt->rear].arg;
		tmp.busines=pt->queue[pt->rear].busines;
		pt->rear=(pt->rear+1)%pt->qmax;
		--pt->cur;
		++pt->thread_busy;
		pthread_kill(ptid,SIGUSR1);
		pthread_mutex_unlock(&lock);
		pthread_cond_signal(&pt->notFull);
		//zhixingrenwu
		tmp.busines(tmp.arg);
		pthread_mutex_lock(&lock);
		--pt->thread_busy;
		pthread_kill(ptid,SIGUSR1);
		pthread_mutex_unlock(&lock);
	}
	return NULL;
}

manager

#include <pool.h>

void* manager(void* arg)
{
	pthread_detach(pthread_self());
	pool_t* pt=(pool_t*)arg;
	int alive,busy,cur,tmax,tmin;
	while(pt->thread_shutdown)
	{
		pthread_mutex_lock(&lock);
		alive=pt->thread_alive;
		busy=pt->thread_busy;
		cur=pt->cur;
		tmax=pt->thread_max;
		tmin=pt->thread_min;
		pthread_mutex_unlock(&lock);
		int flag,add;
		//kuorong
		int err;
		if((cur>=alive-busy||(double)busy/alive*100>=70)&&alive+tmin<=tmax)
		{
			for(flag=0,add=0;flag<tmax&&add<tmin;flag++)
			{
				if(pt->ctids[flag]==0)
				{
					pthread_mutex_lock(&lock);
					if((err=pthread_create(&pt->ctids[flag],NULL,customer,(void*)pt))>0)
					{
						printf("manager pthread_create failed: %s\n",strerror(err));
						pthread_mutex_unlock(&lock);
					}					
					++pt->thread_alive;
					pthread_mutex_unlock(&lock);
					++add;
				}
			}
		}

		//suojian
		if(alive-busy>=2*busy && alive-tmin>=tmin)
		{
			pthread_mutex_lock(&lock);
			pt->thread_killnum=pt->thread_min;
			pthread_mutex_unlock(&lock);
			for(int i=0;i<tmin;i++)
			{
				pthread_cond_signal(&pt->notEmpty);
			}
		}
	}
	return NULL;
}

epoll_init

#include <pool.h>

int epoll_init(int sockfd,int listen_num)
{
	if((epfd=epoll_create(listen_num))==-1)
	{
		perror("epoll_init epoll_create failed");
		return -1;
	}
	struct epoll_event node;
	node.data.fd=sockfd;
	node.events=EPOLLIN|EPOLLET;
	if((epoll_ctl(epfd,EPOLL_CTL_ADD,sockfd,&node))==-1)
	{
		perror("epoll_init epoll_ctl failed");
		return -1;
	}
	return 0;
}

epoll_listen

#include <pool.h>

void epoll_listen(int sockfd,pool_t *pt)
{
	int readyNum;
	struct epoll_event readyArray[100000];
	int flag;
	bs_t tmp;
	while(pt->thread_shutdown)
	{
		if((readyNum=epoll_wait(epfd,readyArray,100000,-1))==-1)
		{
			perror("epoll_listen epoll_wait failed");
			exit(0);
		}
		flag=0;
		while(readyNum)
		{
			if(readyArray[flag].data.fd==sockfd)
			{
				tmp.arg=(void*)&readyArray[flag].data.fd;
				tmp.busines=accept_busines;
			}
			else
			{
				tmp.arg=(void*)&readyArray[flag].data.fd;
				tmp.busines=recv_busines;
			}
			producer_add(pt,tmp);
			--readyNum;
			++flag;
		}
	}
	close(sockfd);
	exit(0);
}

thread_printf

#include <pool.h>

void* thread_printf(void* arg)
{
	pthread_detach(pthread_self());
	ptr=(pool_t*)arg;
	struct sigaction act,oact;
	sigemptyset(&act.sa_mask);
	act.sa_handler=&sig_usr;
	act.sa_flags=0;
	sigaction(SIGUSR1,&act,&oact);
	sigprocmask(SIG_SETMASK,&act.sa_mask,NULL);
	while(ptr->thread_shutdown)
	{
		sleep(1);
	}
	pthread_exit(NULL);
}

thread_destroy

#include <pool.h>

void thread_destroy(void* arg)
{
	pool_t* pt=(pool_t*)arg;
	pthread_cond_destroy(&pt->notEmpty);
	pthread_cond_destroy(&pt->notFull);
	pthread_mutex_destroy(&lock);

	free(pt->queue);
	free(pt->ctids);
	free(pt);
}

sig_usr

#include <pool.h>

void sig_usr(int n)
{
	printf("alive %d , busy %d , idel %d , cur %d , a/m %.2f%% , b/a %.2f%%\n",ptr->thread_alive,ptr->thread_busy,ptr->thread_alive-ptr->thread_busy,ptr->cur,(double)ptr->thread_alive/ptr->thread_max*100,(double)ptr->thread_busy/ptr->thread_alive*100);
}

main

#include <pool.h>

int main(void)
{
	sigset_t set,oset;
	sigemptyset(&set);
	sigaddset(&set,SIGUSR1);
	sigprocmask(SIG_SETMASK,&set,&oset);
	int sockfd=net_init(NULL,8080);
	pool_t* pt;
	epoll_init(sockfd,100000);
	pt=pool_init(100,10,1000);
	epoll_listen(sockfd,pt);
	if(!pt->thread_shutdown)
	{
		thread_destroy((void*)pt);
	}
	return 0;
}

client.c

#include<sock.h>

#define server_ip "192.168.206.150"
#define server_port 8080

int main()
{
    struct sockaddr_in addr;
    bzero(&addr,sizeof(addr));
    addr.sin_family=AF_INET;
    addr.sin_port=htons(server_port);
    addr.sin_addr.s_addr=inet_addr(server_ip);
    // 创建套接字
    int sock=SOCKET(AF_INET,SOCK_STREAM,0);
    // 连接服务器
    int err=CONNECT(sock,(struct sockaddr*)&addr,sizeof(addr));
    if(err==-1)
    {
        // 若连接失败,关闭套接字并退出程序
        close(sock);
        exit(0);
    }
    char buf[1500];
    // 清空缓冲区
    bzero(buf,1500);
    // 接收服务器的首次响应
    RECV(sock,buf,sizeof(buf),0);
    printf("%s\n",buf);

    while(1)
    {
        // 清空缓冲区
        bzero(buf,sizeof(buf));
        if(fgets(buf,sizeof(buf),stdin)==NULL)
            // 若读取输入失败,退出循环
            break;
        // 发送请求到服务器
        SEND(sock,buf,strlen(buf),0);
        // 清空缓冲区
        bzero(buf,sizeof(buf));
        // 接收服务器响应
        RECV(sock,buf,sizeof(buf),0);
        printf("%s\n",buf);
    }
    // 关闭套接字
    close(sock);
    return 0;
}
从零构建Linux高性能HTTP文件服务器:epoll与线程池实战 在Linux高性能网络编程领域,I/O多路复用是解决高并发连接的核心技术。其原理是通过单个线程监控多个文件描述符的状态变化,当某个描述符就绪时再进行I/O操作,从而大幅提升资源利用率。其中epoll作为Linux特有的I/O事件通知机制,相比传统的select/poll具有更高的性能和可扩展性,成为构建现代高并发服务器的基石。结合线程池技术,可以将I/O事件监听与业务逻辑处理解耦,实现高效的任务调度与资源复用。这种架构模式特别适用于需要处理大量并发连接的文件服务器、Web服务器等场景。本文通过一个支持文件上 阅读详情

相关推荐

Linux C++进阶:从系统视角到AI Infra与高性能服务器实战

C++作为一门系统级编程语言,其核心价值在于对计算机底层资源的精细控制和高性能计算能力。其原理在于通过直接操作内存、管理硬件资源,实现极致的执行效率。这一技术价值在当今云计算、人工智能和实时音视频处理等对性能有严苛要求的领域尤为凸显。在这些应用场景中,系统编程能力是构建基础设施的关键。本文聚焦于Linux C++开发者的进阶之路,深入探讨了内存管理、并发模型与IO优化等核心系统概念,并提供了构建高性能HTTP服务器和集成ONNX Runtime进行模型推理的实战项目。通过剖析AI Infra和音视频处理等热

congsikuai0611的博客 535

C/C++ HTTP服务器开发:从请求解析到高并发epoll实现

网络编程是构建互联网服务的基石,其核心在于理解客户端与服务器之间通过协议进行通信的原理。HTTP协议作为Web通信的标准,定义了请求与响应的格式。在技术实现上,服务器需要高效处理并发连接,传统多进程/多线程模型面临资源开销大的挑战,而I/O多路复用技术(如epoll)通过事件驱动机制,用单个线程监控大量连接,显著提升了并发性能。这种高并发架构对于构建高性能Web服务具有重要价值,广泛应用于网关、API服务器等场景。本文以C/C++ HTTP服务器开发为例,深入探讨了从基础请求解析、响应构建到支持动态CGI程

weixin_30600197的博客 478

Linux C/C++ 进阶实战:从系统编程到高性能服务开发

系统编程是理解计算机如何运行的核心,它涉及进程、线程、内存管理和I/O等底层机制。其原理在于操作系统通过抽象硬件资源,为应用程序提供稳定、安全的执行环境。掌握系统编程的技术价值在于能够开发出高性能、高可靠性的软件,如数据库、Web服务器和分布式系统。应用场景广泛,涵盖后端服务、AI基础设施和嵌入式开发等领域。本文聚焦于Linux C/C++开发,通过构建HTTP服务器、线程池等实战项目,深入讲解epoll、内存池等关键技术,帮助开发者从原理到实践,系统提升在高性能计算和系统软件领域的工程能力。

weixin_34199335的博客 432

Linux C++高性能网络通信架构实战:从epoll到多Reactor模型

在后台服务开发领域,高性能网络通信架构是支撑游戏服务器、金融交易系统等核心业务的技术基石。其核心原理在于采用事件驱动模型与I/O多路复用技术,以高效管理海量并发连接。其中,epoll作为Linux下高性能的I/O事件通知机制,通过水平触发或边缘触发模式,成为构建高并发服务器的关键技术。结合多Reactor线程模型与线程池,能够充分利用多核CPU资源,实现计算与I/O的高效分离。这种架构的技术价值在于提供了稳定、可扩展的底层框架,使开发者能聚焦于业务逻辑。本文以一套实战的C++配套资源为例,深入解析了从基础网

shirlly 555

C++高性能Web服务器TinyWebServer源码解析与并发模型实践

在Linux服务器开发中,I/O多路复用与并发模型是构建高性能网络服务的核心基础。epoll作为Linux下高效的I/O事件通知机制,通过水平触发(LT)与边沿触发(ET)两种模式管理海量连接,其本质是操作系统提供的事件驱动编程接口。结合线程池技术,可构建出Reactor与Proactor两种经典并发架构,前者将I/O操作交由工作线程处理,后者则由主线程完成数据读写,实现业务逻辑与I/O的解耦,从而大幅提升吞吐量与资源利用率。这些技术广泛应用于需要高并发的Web服务器、API网关及实时通信系统中。本文以Gi

weixin_30457551的博客 624

Java I/O模型穿透指南:从Linux系统调用到WebFlux实战

I/O模型是后端性能的底层基石,其本质是操作系统对文件描述符的调度策略——阻塞/非阻塞由O_NONBLOCK标志控制,同步/异步反映API结果获取方式。理解epoll_wait、read系统调用与JVM线程状态(如WAITING/RUNNABLE)的映射关系,才能真正诊断高并发下的RT毛刺与线程堆积。NIO通过事件驱动提升连接复用率,而WebFlux依赖Reactive生态实现全链路非阻塞;但若混用JDBC等阻塞调用,将触发BlockingOperationError。本文结合strace、jstack、s

as2886089的博客 390

Nginx高性能架构解析:6张图揭秘Master-Worker与epoll事件驱动机制

在构建高并发Web服务时,I/O多路复用和事件驱动架构是核心技术基础。其原理在于通过操作系统提供的epoll、kqueue等机制,使单个进程能够同时监控大量网络连接,仅在数据就绪时进行非阻塞处理,从而极大提升资源利用率。这种设计的技术价值在于解决了传统多线程/进程模型因上下文切换和内存开销导致的性能瓶颈,尤其适用于HTTP短连接、API网关等高并发场景。Nginx正是这一理念的典范,其Master-Worker多进程模型将管理面与数据面分离,Worker进程内部采用单线程事件循环,结合内存池、连接池等优化,

weixin_33721344的博客 281

Ubuntu 18.04 搭建 GlusterFS 冗余存储池实战指南

分布式文件系统是构建高可用共享存储的基础技术,其核心在于通过多节点协同实现数据冗余与故障自愈。GlusterFS 作为成熟的 POSIX 兼容分布式文件系统,依托 Trusted Storage Pool 机制提供强一致的副本管理能力,相比 Ceph 更轻量、比 MinIO 更契合传统应用的文件语义。在 Ubuntu 18.04 这一长期支持且生态稳定的发行版上,结合 GlusterFS 6.10 版本,可构建出资源占用低、运维路径清晰、恢复确定性强的冗余存储池,广泛适用于边缘计算、AI 训练数据共享、媒体

weixin_34121282的博客 307

Linux进程池实战:基于POSIX IPC的高可靠进程管理方案

进程池是Linux系统中实现高并发、强隔离任务处理的核心工程模式,其本质是对fork、共享内存、信号量、管道等底层IPC机制的封装与协同调度。它解决的不是‘能否通信’,而是‘如何在真实生产环境中安全、可控、可观测地复用进程资源’——尤其在需要内存隔离(如非线程安全第三方库)、故障隔离(如嵌入式设备处理)或信号/资源上下文约束(如工业SDK初始化)等场景下,进程池相比线程池具有不可替代的技术价值。本文聚焦POSIX标准接口实现,涵盖共享内存安全边界、非阻塞pipe+epoll多路复用、命名与无名信号量混合使用

weixin_34007020的博客 306

C++高性能服务器开发实战:从Reactor模型到零拷贝优化

网络编程是构建分布式系统的基石,其核心在于高效管理海量并发连接。传统多线程模型因资源开销巨大而难以应对C10K问题,于是I/O多路复用技术应运而生。通过select、poll到epoll/kqueue的演进,系统能够用单个线程监控大量文件描述符的状态变化,这正是事件驱动架构的原理。这种技术价值在于极大提升了资源利用率,使单机承载数万并发连接成为可能,为高并发服务提供底层支撑。应用场景广泛,从Web服务器、实时通信到游戏后端均依赖于此。本文以热门的“30天C++服务器”项目为蓝本,深入剖析如何基于Reacto

weixin_34367257的博客 443

2080Ti双卡开启NVLink

本文介绍了如何在Ubuntu 22.04系统下给2080Ti双卡开启NVLink的方法。

flymyd的博客 2900

Modbus RTU 转 TCP 网关实战:基于树莓派4B与libmodbus 3.1.7 实现双向协议转换

本文详细介绍了如何基于树莓派4B与libmodbus 3.1.7实现Modbus RTU到TCP的双向协议转换网关。通过硬件配置、系统优化和核心代码实现,该方案支持10ms级延迟、自动重连和多客户端并发,适用于工业物联网场景。文章还提供了性能测试数据和工业现场部署建议,帮助工程师高效完成老旧设备的网络化改造。

weixin_34198453的博客 319

FPGA实战:手把手教你配置4个Aurora 8B/10B IP核共享时钟(附完整工程文件)

本文详细介绍了在Xilinx FPGA上配置四个Aurora 8B/10B IP核并实现时钟共享的实战指南。从工程规划、IP核基础配置到共享逻辑的实现,再到多核时钟域与复位架构的设计,以及时序约束与调试技巧,提供了完整的解决方案和可复用的工程文件。特别强调了GT参考时钟的共享和复位信号的处理,帮助工程师高效解决多通道高速串行通信的设计挑战。

weixin_30879169的博客 411

C++网络编程:高性能实现与核心技巧

网络编程是现代软件开发的核心技术之一,涉及数据传输、协议实现和并发处理等关键概念。在底层原理上,通过Socket API实现进程间通信,结合I/O多路复用技术(如epoll/kqueue)处理高并发请求。C++凭借其零成本抽象和精准内存控制能力,成为构建高性能网络服务的首选语言,特别适合需要处理海量并发连接和低延迟场景。在实际工程中,通过零拷贝技术、连接池优化等手段可显著提升吞吐量,而Boost.Asio等成熟库则提供了跨平台解决方案。无论是开发Web服务器、实时通信系统还是分布式中间件,掌握C++网络编程

weixin_34279579的博客 369

【SpringBoot香樟转转】debugDay01

在学黑马程序员的苍穹外卖项目,刚开始学,想用maven编译一下代码,结果报错,找不到符号。本着先理解原则,看着能找到这个变量呀。

m0_72696598的博客 1737

Python爬虫实战:西瓜视频m3u8解析与FFmpeg下载合并

网络爬虫与流媒体解析是Python工程实践中的常见需求,其核心在于通过HTTP请求获取数据并解析特定格式。m3u8作为HLS协议索引文件,将视频切分为ts分片,便于流式传输。结合FFmpeg的多线程处理能力,可高效完成分片下载与合并,技术价值在于提升视频处理效率。典型应用场景包括视频下载、离线缓存等。本文以西瓜视频为例,详细讲解如何使用requests库提取m3u8地址,并调用FFmpeg批量下载ts分片合并为mp4,涵盖请求伪装、索引解析及常见问题排查。

weixin_31856057的博客 15万+

C++高并发HTTP服务器实战:从Reactor模式到性能调优

网络编程是系统软件开发的核心领域,其关键在于如何高效管理大量并发连接。I/O多路复用技术(如epoll、kqueue)通过事件驱动机制,允许单个线程监控多个文件描述符的状态变化,从而避免了传统阻塞I/O模型下线程资源浪费的问题。结合Reactor设计模式,可以将事件分发与业务处理解耦,构建出高性能、可扩展的服务器架构。这种架构在现代互联网基础设施中价值显著,广泛应用于Web服务器、API网关、实时通信服务等场景。本文以C++实现高并发HTTP服务器为例,深入剖析了线程池管理、缓冲区设计及HTTP协议解析等关

diaohong5075的博客 372

华为产品安全基线

一、敏感信息安全传输 1、采用HTTPS安全协议传输 2、客户端本地保存的敏感信息,需要先加密再保存使用,不可逆支持PBKDF2(迭代10000次)加密保存,可逆支持AES256+IV保存,密钥支持可更新 二、认证鉴权 1、License中心与分析节点分布式部署,需要做用户名+口令安全认证,支持使用HTTPS安全协议。 2、客户端登录支持防暴力破解,支持验证码,多次连续尝试登陆失败后锁定账...

zileixu的博客 1万+

RAG微调与智能体优化:解决准确率、失败率和GPU瓶颈

RAG(检索增强生成)和AI智能体是当前大模型落地的核心技术路径,其本质是通过外部知识注入与任务编排提升LLM的可靠性与可控性。RAG并非简单检索+生成,而需实现query意图与文档语义的精准对齐;智能体也不仅是链式调用,更依赖状态隔离、决策缓存与可回滚机制保障稳定性。在工程实践中,Fine-Tuning RAG常因query改写失真、chunk粒度错配和reranker时效性缺失导致准确率骤降;Smarter Agents则易因会话污染与状态耦合引发高失败率;GPU Bottlenecks多源于CUDA

weixin_30258901的博客 324

HBase批量导入工具:BulkLoad使用详解

HBase作为分布式NoSQL数据库,在大数据领域有着广泛应用。传统的数据写入方式(如Put操作)在面对海量数据导入时存在性能瓶颈。BulkLoad提供了一种高效的大批量数据导入方案,可以显著提高数据加载速度并降低集群负载。BulkLoad的核心原理和架构与传统写入方式的性能对比详细的使用方法和实现步骤性能优化技巧和最佳实践实际应用案例分析本文首先介绍BulkLoad的基本概念和原理,然后深入讲解其实现机制和关键技术。接着通过实际案例演示BulkLoad的使用方法,并分析性能优化策略。

大数据洞察的博客 1236

彻底解析 DDIC_TYPE_INCONSISTENCY:从 ABAP ST22 连环 Dump 到 SE14 一键修复

听上去像内核级的致命故障,实则更多源于日常运维的细枝末节。只要掌握的排查三板斧,结合严格的变更流程与周期性的字典体检,再严重的 Dump 也能化险为夷。希望本文的案例与步骤能帮助读者在下一次遇到类似问题时,既能快速止血,也能追根溯源,避免重蹈覆辙。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 629

Linux C/C++进阶实战:从系统编程到AI与音视频开发

C++作为高性能计算和系统编程的核心语言,其现代特性(如智能指针、移动语义)与内存模型是构建高效、安全软件的基础。理解这些原理,结合Linux系统编程(进程、网络、I/O多路复用)和调试工具链(GDB、Valgrind),是解决复杂工程问题的关键。这种技术组合在需要极致性能与控制的场景中价值显著,例如AI基础设施(AI Infra)中的模型部署与高性能算子开发,以及音视频处理中的实时编解码与流媒体服务。本文聚焦于如何将C++语言能力与系统知识转化为解决AI Infra、后端服务等实际问题的项目实战能力,提供

weixin_30800987的博客 311

MIPI CPHY学习笔记01:TX物理层一致性测试项解析(LP信令模式)

在手机、平板、智能手表等移动设备中,MIPI C-PHY是负责图像、数据传输的核心接口,它就像设备内部的“高速数据线”,而低功耗(LP)信令模式,是这条“数据线”的“省电模式”,专门用于设备待机、低负载等场景,既要保证信号稳定,又要最大限度降低功耗。物理层一致性测试,就是给这个“省电模式”做的“全面体检”,确保不同厂商的设备能兼容互通。今天,我们就聚焦MIPI C-PHY TX(发射端)的Group 1 LP信令测试,用通俗的语言拆解8个核心测试项,看懂“省电信号”的合格标准。

一只豌豆象的博客 300

C++ 仿 muduo 库实现高并发服务器

该项目实现了一个基于Reactor模式的高并发TCP服务器组件,包含Server模块(管理连接、事件、定时任务)和HTTP协议模块。采用多Reactor多线程模型,利用I/O多路复用、时间轮超时管理和自定义缓冲区,支持非活跃连接释放、协议切换和静态资源处理,最终搭建出灵活可扩展的高性能HTTP服务器。

wefg1的博客 231

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

C++键值数据库ddkv:从哈希表到多线程Reactor的深度实现

键值存储(Key-Value Store)是现代软件架构中处理高速数据访问的核心组件,其原理是通过哈希表、跳表等数据结构实现键到值的快速映射。在系统编程领域,高效的内存管理、并发控制和持久化机制是其技术价值的关键,直接决定了数据库的吞吐量和延迟。这些技术广泛应用于缓存、会话存储和实时数据处理等场景。本文聚焦于使用C++实现一个高性能键值数据库(ddkv)的工程实践,深入探讨了分片哈希表、多线程Reactor网络模型和AOF持久化等核心模块的设计与优化,特别是通过分片锁和缓冲写入机制来应对高并发挑战,为理解底

weixin_33749131的博客 324

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

Memcached Docker 缓存三步上线:15MB 镜像调出万级并发

凌晨两点告警群炸了:缓存集群全挂,请求全打到 MySQL,CPU 瞬间拉满。 memcached 是一个分布式内存 key-value 缓存,把它用 Docker 跑起来只要 5 分钟,再靠三个 flag 就能撑住千级连接。看完这篇指南你能拿到: - 一个 15MB 以内的 Alpine 镜像 - 冷启动不到 3 秒的缓存容器 - 可支撑 10240 并发连接、4 个工作线程的配置 ☐ 镜像

gitblog_00253的博客 620

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

上一篇: 3-IM聊天系统-Mediator
小姨火辣辣
博客等级 码龄4年 38粉丝 5原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值