基础组件(线程池、内存池、异步请求池、Mysql连接池)

文章目录

  • 1、概述
  • 2、线程池
  • 2、异步请求池
  • 3、内存池

1、概述

池化技术,减少了资源创建次数,提高了程序响应性能,特别是在高并发场景下,当程序7*24小时运行,创建资源可能会出现耗时较长和失败等问题,池化技术,主要是程序初始化之前创建多个可用连接,集中管理起来,后续直接使用,使用完并归还。

2、线程池

线程池主要解决问题:
1、解决线程创建和消耗所浪费的资源和时间
2、控制线程数量,减少资源竞争

代码解读

一共由三个接口组成:
1、CreatePthreadPool创建工作线程
初始化线程池结构下的条件变量和互斥锁,创建多个线程通过头插法,插入到线程池结构worker成员中
2、thread_func线程入口函数
进入while循环,第一件事先拿锁,然后再去判断,任务队列中是否有数据,要是没有则进入循环中的条件等待,进入条件等待会先释放锁,所以初始化完成之后所有线程全部都会进入条件等待,然后一旦条件满足则会去拿锁。
3、threadPoolQueue将任务加入到任务链表中
先加锁,然后通过头插法插入到线程池结构中的wait_jobs成员中,通知条件变量,然后解锁
4、threadPoolShutdown回收线程池中线程
将工作线程中的标识位全部置为一,然后通知所有线程,然后等待回收所有线程并释放每个节点

总结

线程池就是一个很典型的生产者消费者模型,不断地向任务队列中投放任务,工作线程不断地去队伍队列中去取任务消费掉。

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>#define LL_ADD(item, list) do { 	\item->prev = NULL;				\item->next = list;				\list = item;					\
} while(0)#define LL_REMOVE(item, list) do {						\if (item->prev != NULL) item->prev->next = item->next;	\if (item->next != NULL) item->next->prev = item->prev;	\if (list == item) list = item->next;					\item->prev = item->next = NULL;							\
} while(0)// 工作线程结构体
typedef struct NWORKER{pthread_t id;               // 线程idint terminate;              // 终止条件struct NTHREADPOLL *worqueue;struct NWORKER *prev;       // 前向指针struct NWORKER *next;       // 后项指针
}nWorker;// 任务队列
typedef struct NJOB{void (*job_function)(struct NJOB* job);void* user_data;struct NJOB *prev;struct NJOB *next;
}nJob;typedef struct NTHREADPOLL{struct NWORKER *workers;struct NJOB *wait_jobs;pthread_cond_t cond;pthread_mutex_t mtx;
}nThreadpoll;// 操作线程池函数
#define MAX_PTHREAD 80
#define MAX_JOB 8// 毁掉函数
void job_fun(nJob *job){if(job == NULL) return;int *data = (int*)job->user_data;printf("user_data:%d-thread_id:%ld,line:%d\n",*data,pthread_self(),__LINE__);free(job->user_data);job->user_data = NULL;free(job);job = NULL;return;
}// 线程入口函数
void* thread_func(void* data){nWorker *worker = (nWorker*)data;while (1){pthread_mutex_lock(&(worker->worqueue->mtx));while(worker->worqueue->wait_jobs == NULL){if(worker->terminate) break;pthread_cond_wait(&(worker->worqueue->cond),&(worker->worqueue->mtx));}if(worker->terminate){pthread_mutex_unlock(&(worker->worqueue->mtx));break;}nJob *job = worker->worqueue->wait_jobs;if(job != NULL)LL_REMOVE(job,worker->worqueue->wait_jobs);pthread_mutex_unlock(&(worker->worqueue->mtx));if(job == NULL) continue;job->job_function(job);}// free(worker);// worker = NULL;pthread_exit(0);
}// 创造线程
int CreatePthreadPool(nThreadpoll* threadpoll,int max_pthread)
{if(max_pthread <= 0) max_pthread = MAX_PTHREAD;memset(threadpoll,0x00,sizeof(nThreadpoll));pthread_cond_t blank_cond = PTHREAD_COND_INITIALIZER;memcpy(&threadpoll->cond, &blank_cond, sizeof(threadpoll->cond));pthread_mutex_t blank_mutex = PTHREAD_MUTEX_INITIALIZER;memcpy(&threadpoll->mtx, &blank_mutex, sizeof(threadpoll->mtx));int i;for(i=0; i<max_pthread; i++){nWorker *worker = (nWorker*)malloc(sizeof(nWorker));if(worker == NULL){perror("threadpoll->workers");return -1;}memset(worker,0x00,sizeof(nWorker));worker->worqueue = threadpoll;worker->terminate = 0;int ret = pthread_create(&(worker->id),NULL,thread_func,(void*)worker);if(ret != 0){perror("pthread_create");free(worker);worker = NULL;return -1;}LL_ADD(worker,worker->worqueue->workers);}return 0;
}// 向线程中添加任务,唤醒一个线程去处理
void threadPoolQueue(nThreadpoll* threadpool,nJob *job){pthread_mutex_lock(&(threadpool->mtx));LL_ADD(job,threadpool->wait_jobs);pthread_cond_signal(&(threadpool->cond));pthread_mutex_unlock(&(threadpool->mtx));return;
}void threadPoolShutdown(nThreadpoll *workerqueue){nWorker *woker = NULL;for(woker = workerqueue->workers;woker!=NULL;woker = woker->next){woker->terminate = 1;}pthread_cond_broadcast(&workerqueue->cond);struct NWORKER *tmp = workerqueue->workers;while (tmp){pthread_join(tmp->id,NULL);if(tmp){free(tmp);tmp = NULL;}tmp = tmp->next;}pthread_cond_destroy(&workerqueue->cond);pthread_mutex_destroy(&workerqueue->mtx);workerqueue->workers = NULL;workerqueue->wait_jobs = NULL;
}int main(){nThreadpoll workerQueue;if(CreatePthreadPool(&workerQueue,MAX_PTHREAD) != 0){perror("CreatePthreadPool faile");return -1;}int i;for(i=0;i<MAX_JOB;i++){nJob *job = (nJob*)malloc(sizeof(nJob));if(job == NULL){perror("nJob malloc faile");exit(-1);}job->job_function = job_fun;job->user_data = (int*)malloc(sizeof(int));*(int*)job->user_data = i;threadPoolQueue(&workerQueue,job);}getchar();return 0;
}

2、异步请求池

当我们向数据库或者DNS服务器发送请求时,需要同步等待他的返回结果,这个过程是比较耗时的,所以衍生出异步发起请求,当发出请求之后,不等待请求的响应,而是通过一个线程去监听,主线程去做其他事情,当请求响应之后如何去做其他事情。
在这里插入图片描述
在这里插入图片描述

同步向DNS服务器发送请求

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>#include <errno.h>
#include <fcntl.h>#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>#include <sys/epoll.h>
#include <netdb.h>
#include <arpa/inet.h>#include <pthread.h>#define DNS_SVR				"114.114.114.114"#define DNS_HOST			0x01
#define DNS_CNAME			0x05struct dns_header {unsigned short id;unsigned short flags;unsigned short qdcount;unsigned short ancount;unsigned short nscount;unsigned short arcount;
};struct dns_question {int length;unsigned short qtype;unsigned short qclass;char *qname;
};struct dns_item {char *domain;char *ip;
};int dns_create_header(struct dns_header *header) {if (header == NULL) return -1;memset(header, 0, sizeof(struct dns_header));srandom(time(NULL));header->id = random();header->flags |= htons(0x0100);header->qdcount = htons(1);return 0;
}int dns_create_question(struct dns_question *question, const char *hostname) {if (question == NULL) return -1;memset(question, 0, sizeof(struct dns_question));question->qname = (char*)malloc(strlen(hostname) + 2);if (question->qname == NULL) return -2;question->length = strlen(hostname) + 2;question->qtype = htons(1);question->qclass = htons(1);const char delim[2] = ".";char *hostname_dup = strdup(hostname);char *token = strtok(hostname_dup, delim);char *qname_p = question->qname;while (token != NULL) {size_t len = strlen(token);*qname_p = len;qname_p ++;strncpy(qname_p, token, len+1);qname_p += len;token = strtok(NULL, delim);}free(hostname_dup);return 0;}int dns_build_request(struct dns_header *header, struct dns_question *question, char *request) {int header_s = sizeof(struct dns_header);int question_s = question->length + sizeof(question->qtype) + sizeof(question->qclass);int length = question_s + header_s;int offset = 0;memcpy(request+offset, header, sizeof(struct dns_header));offset += sizeof(struct dns_header);memcpy(request+offset, question->qname, question->length);offset += question->length;memcpy(request+offset, &question->qtype, sizeof(question->qtype));offset += sizeof(question->qtype);memcpy(request+offset, &question->qclass, sizeof(question->qclass));return length;}static int is_pointer(int in) {return ((in & 0xC0) == 0xC0);
}static void dns_parse_name(unsigned char *chunk, unsigned char *ptr, char *out, int *len) {int flag = 0, n = 0, alen = 0;char *pos = out + (*len);while (1) {flag = (int)ptr[0];if (flag == 0) break;if (is_pointer(flag)) {n = (int)ptr[1];ptr = chunk + n;dns_parse_name(chunk, ptr, out, len);break;} else {ptr ++;memcpy(pos, ptr, flag);pos += flag;ptr += flag;*len += flag;if ((int)ptr[0] != 0) {memcpy(pos, ".", 1);pos += 1;(*len) += 1;}}}}static int dns_parse_response(char *buffer, struct dns_item **domains) {int i = 0;unsigned char *ptr = buffer;ptr += 4;int querys = ntohs(*(unsigned short*)ptr);ptr += 2;int answers = ntohs(*(unsigned short*)ptr);ptr += 6;for (i = 0;i < querys;i ++) {while (1) {int flag = (int)ptr[0];ptr += (flag + 1);if (flag == 0) break;}ptr += 4;}char cname[128], aname[128], ip[20], netip[4];int len, type, ttl, datalen;int cnt = 0;struct dns_item *list = (struct dns_item*)calloc(answers, sizeof(struct dns_item));if (list == NULL) {return -1;}for (i = 0;i < answers;i ++) {bzero(aname, sizeof(aname));len = 0;dns_parse_name(buffer, ptr, aname, &len);ptr += 2;type = htons(*(unsigned short*)ptr);ptr += 4;ttl = htons(*(unsigned short*)ptr);ptr += 4;datalen = ntohs(*(unsigned short*)ptr);ptr += 2;if (type == DNS_CNAME) {bzero(cname, sizeof(cname));len = 0;dns_parse_name(buffer, ptr, cname, &len);ptr += datalen;} else if (type == DNS_HOST) {bzero(ip, sizeof(ip));if (datalen == 4) {memcpy(netip, ptr, datalen);inet_ntop(AF_INET , netip , ip , sizeof(struct sockaddr));printf("%s has address %s\n" , aname, ip);printf("\tTime to live: %d minutes , %d seconds\n", ttl / 60, ttl % 60);list[cnt].domain = (char *)calloc(strlen(aname) + 1, 1);memcpy(list[cnt].domain, aname, strlen(aname));list[cnt].ip = (char *)calloc(strlen(ip) + 1, 1);memcpy(list[cnt].ip, ip, strlen(ip));cnt ++;}ptr += datalen;}}*domains = list;ptr += 2;return cnt;}int dns_client_commit(const char *domain) {int sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd < 0) {perror("create socket failed\n");exit(-1);}printf("url:%s\n", domain);struct sockaddr_in dest;bzero(&dest, sizeof(dest));dest.sin_family = AF_INET;dest.sin_port = htons(53);dest.sin_addr.s_addr = inet_addr(DNS_SVR);int ret = connect(sockfd, (struct sockaddr*)&dest, sizeof(dest));printf("connect :%d\n", ret);struct dns_header header = {0};dns_create_header(&header);struct dns_question question = {0};dns_create_question(&question, domain);char request[1024] = {0};int req_len = dns_build_request(&header, &question, request);int slen = sendto(sockfd, request, req_len, 0, (struct sockaddr*)&dest, sizeof(struct sockaddr));char buffer[1024] = {0};struct sockaddr_in addr;size_t addr_len = sizeof(struct sockaddr_in);int n = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&addr, (socklen_t*)&addr_len);printf("recvfrom n : %d\n", n);struct dns_item *domains = NULL;dns_parse_response(buffer, &domains);return 0;
}char *domain[] = {
//	"www.ntytcp.com","bojing.wang","www.baidu.com","tieba.baidu.com","news.baidu.com","zhidao.baidu.com","music.baidu.com","image.baidu.com","v.baidu.com","map.baidu.com","baijiahao.baidu.com","xueshu.baidu.com","cloud.baidu.com","www.163.com","open.163.com","auto.163.com","gov.163.com","money.163.com","sports.163.com","tech.163.com","edu.163.com","www.taobao.com","q.taobao.com","sf.taobao.com","yun.taobao.com","baoxian.taobao.com","www.tmall.com","suning.tmall.com","www.tencent.com","www.qq.com","www.aliyun.com","www.ctrip.com","hotels.ctrip.com","hotels.ctrip.com","vacations.ctrip.com","flights.ctrip.com","trains.ctrip.com","bus.ctrip.com","car.ctrip.com","piao.ctrip.com","tuan.ctrip.com","you.ctrip.com","g.ctrip.com","lipin.ctrip.com","ct.ctrip.com"
};int main(int argc, char *argv[]) {int count = sizeof(domain) / sizeof(domain[0]);int i = 0;for (i = 0;i < count;i ++) {dns_client_commit(domain[i]);}getchar();}

异步发送请求

1、dns_async_client_init初始化函数
创建epoll、创建线程,用来监控dns的响应消息
2、dns_async_client_commit创建连接,发送请求,将fd加入到epoll中进行监听
3、dns_async_client_proc线程入口函数
通过epoll_wait进行监听,调用取出数据,调用对应的回调函数,epoll_ctl删除节点。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>#include <errno.h>
#include <fcntl.h>#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>#include <sys/epoll.h>
#include <netdb.h>
#include <arpa/inet.h>#include <pthread.h>#define DNS_SVR				"114.114.114.114"#define DNS_HOST			0x01
#define DNS_CNAME			0x05#define ASYNC_CLIENT_NUM		1024struct dns_header {unsigned short id;unsigned short flags;unsigned short qdcount;unsigned short ancount;unsigned short nscount;unsigned short arcount;
};struct dns_question {int length;unsigned short qtype;unsigned short qclass;char *qname;
};struct dns_item {char *domain;char *ip;
};typedef void (*async_result_cb)(struct dns_item *list, int count);struct async_context {int epfd;
};struct ep_arg {int sockfd;async_result_cb cb;
};int dns_create_header(struct dns_header *header) {if (header == NULL) return -1;memset(header, 0, sizeof(struct dns_header));srandom(time(NULL));header->id = random();header->flags |= htons(0x0100);header->qdcount = htons(1);return 0;
}int dns_create_question(struct dns_question *question, const char *hostname) {if (question == NULL) return -1;memset(question, 0, sizeof(struct dns_question));question->qname = (char*)malloc(strlen(hostname) + 2);if (question->qname == NULL) return -2;question->length = strlen(hostname) + 2;question->qtype = htons(1);question->qclass = htons(1);const char delim[2] = ".";char *hostname_dup = strdup(hostname);char *token = strtok(hostname_dup, delim);char *qname_p = question->qname;while (token != NULL) {size_t len = strlen(token);*qname_p = len;qname_p ++;strncpy(qname_p, token, len+1);qname_p += len;token = strtok(NULL, delim);}free(hostname_dup);return 0;}int dns_build_request(struct dns_header *header, struct dns_question *question, char *request) {int header_s = sizeof(struct dns_header);int question_s = question->length + sizeof(question->qtype) + sizeof(question->qclass);int length = question_s + header_s;int offset = 0;memcpy(request+offset, header, sizeof(struct dns_header));offset += sizeof(struct dns_header);memcpy(request+offset, question->qname, question->length);offset += question->length;memcpy(request+offset, &question->qtype, sizeof(question->qtype));offset += sizeof(question->qtype);memcpy(request+offset, &question->qclass, sizeof(question->qclass));return length;}static int is_pointer(int in) {return ((in & 0xC0) == 0xC0);
}static int set_block(int fd, int block) {int flags = fcntl(fd, F_GETFL, 0);if (flags < 0) return flags;if (block) {        flags &= ~O_NONBLOCK;    } else {        flags |= O_NONBLOCK;    }if (fcntl(fd, F_SETFL, flags) < 0) return -1;return 0;
}static void dns_parse_name(unsigned char *chunk, unsigned char *ptr, char *out, int *len) {int flag = 0, n = 0, alen = 0;char *pos = out + (*len);while (1) {flag = (int)ptr[0];if (flag == 0) break;if (is_pointer(flag)) {n = (int)ptr[1];ptr = chunk + n;dns_parse_name(chunk, ptr, out, len);break;} else {ptr ++;memcpy(pos, ptr, flag);pos += flag;ptr += flag;*len += flag;if ((int)ptr[0] != 0) {memcpy(pos, ".", 1);pos += 1;(*len) += 1;}}}}static int dns_parse_response(char *buffer, struct dns_item **domains) {int i = 0;unsigned char *ptr = buffer;ptr += 4;int querys = ntohs(*(unsigned short*)ptr);ptr += 2;int answers = ntohs(*(unsigned short*)ptr);ptr += 6;for (i = 0;i < querys;i ++) {while (1) {int flag = (int)ptr[0];ptr += (flag + 1);if (flag == 0) break;}ptr += 4;}char cname[128], aname[128], ip[20], netip[4];int len, type, ttl, datalen;int cnt = 0;struct dns_item *list = (struct dns_item*)calloc(answers, sizeof(struct dns_item));if (list == NULL) {return -1;}for (i = 0;i < answers;i ++) {bzero(aname, sizeof(aname));len = 0;dns_parse_name(buffer, ptr, aname, &len);ptr += 2;type = htons(*(unsigned short*)ptr);ptr += 4;ttl = htons(*(unsigned short*)ptr);ptr += 4;datalen = ntohs(*(unsigned short*)ptr);ptr += 2;if (type == DNS_CNAME) {bzero(cname, sizeof(cname));len = 0;dns_parse_name(buffer, ptr, cname, &len);ptr += datalen;} else if (type == DNS_HOST) {bzero(ip, sizeof(ip));if (datalen == 4) {memcpy(netip, ptr, datalen);inet_ntop(AF_INET , netip , ip , sizeof(struct sockaddr));printf("%s has address %s\n" , aname, ip);printf("\tTime to live: %d minutes , %d seconds\n", ttl / 60, ttl % 60);list[cnt].domain = (char *)calloc(strlen(aname) + 1, 1);memcpy(list[cnt].domain, aname, strlen(aname));list[cnt].ip = (char *)calloc(strlen(ip) + 1, 1);memcpy(list[cnt].ip, ip, strlen(ip));cnt ++;}ptr += datalen;}}*domains = list;ptr += 2;return cnt;}int dns_client_commit(const char *domain) {int sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd < 0) {perror("create socket failed\n");exit(-1);}printf("url:%s\n", domain);set_block(sockfd, 0); //nonblockstruct sockaddr_in dest;bzero(&dest, sizeof(dest));dest.sin_family = AF_INET;dest.sin_port = htons(53);dest.sin_addr.s_addr = inet_addr(DNS_SVR);int ret = connect(sockfd, (struct sockaddr*)&dest, sizeof(dest));//printf("connect :%d\n", ret);struct dns_header header = {0};dns_create_header(&header);struct dns_question question = {0};dns_create_question(&question, domain);char request[1024] = {0};int req_len = dns_build_request(&header, &question, request);int slen = sendto(sockfd, request, req_len, 0, (struct sockaddr*)&dest, sizeof(struct sockaddr));while (1) {char buffer[1024] = {0};struct sockaddr_in addr;size_t addr_len = sizeof(struct sockaddr_in);int n = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&addr, (socklen_t*)&addr_len);if (n <= 0) continue;printf("recvfrom n : %d\n", n);struct dns_item *domains = NULL;dns_parse_response(buffer, &domains);break;}return 0;
}void dns_async_client_free_domains(struct dns_item *list, int count) {int i = 0;for (i = 0;i < count;i ++) {free(list[i].domain);free(list[i].ip);}free(list);
}//dns_async_client_proc()
//epoll_wait
//result callback
static void* dns_async_client_proc(void *arg) {struct async_context *ctx = (struct async_context*)arg;int epfd = ctx->epfd;while (1) {struct epoll_event events[ASYNC_CLIENT_NUM] = {0};int nready = epoll_wait(epfd, events, ASYNC_CLIENT_NUM, -1);if (nready < 0) {if (errno == EINTR || errno == EAGAIN) {continue;} else {break;}} else if (nready == 0) {continue;}printf("nready:%d\n", nready);int i = 0;for (i = 0;i < nready;i ++) {struct ep_arg *data = (struct ep_arg*)events[i].data.ptr;int sockfd = data->sockfd;char buffer[1024] = {0};struct sockaddr_in addr;size_t addr_len = sizeof(struct sockaddr_in);int n = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&addr, (socklen_t*)&addr_len);struct dns_item *domain_list = NULL;int count = dns_parse_response(buffer, &domain_list);data->cb(domain_list, count); //call cbint ret = epoll_ctl(epfd, EPOLL_CTL_DEL, sockfd, NULL);//printf("epoll_ctl DEL --> sockfd:%d\n", sockfd);close(sockfd); /dns_async_client_free_domains(domain_list, count);free(data);}}}//dns_async_client_init()
//epoll init
//thread init
struct async_context *dns_async_client_init(void) {int epfd = epoll_create(1); // if (epfd < 0) return NULL;struct async_context *ctx = calloc(1, sizeof(struct async_context));if (ctx == NULL) {close(epfd);return NULL;}ctx->epfd = epfd;pthread_t thread_id;int ret = pthread_create(&thread_id, NULL, dns_async_client_proc, ctx);if (ret) {perror("pthread_create");return NULL;}usleep(1); //child go firstreturn ctx;
}//dns_async_client_commit(ctx, domain)
//socket init
//dns_request
//sendto dns send
int dns_async_client_commit(struct async_context* ctx, const char *domain, async_result_cb cb) {int sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd < 0) {perror("create socket failed\n");exit(-1);}printf("url:%s\n", domain);set_block(sockfd, 0); //nonblockstruct sockaddr_in dest;bzero(&dest, sizeof(dest));dest.sin_family = AF_INET;dest.sin_port = htons(53);dest.sin_addr.s_addr = inet_addr(DNS_SVR);int ret = connect(sockfd, (struct sockaddr*)&dest, sizeof(dest));//printf("connect :%d\n", ret);struct dns_header header = {0};dns_create_header(&header);struct dns_question question = {0};dns_create_question(&question, domain);char request[1024] = {0};int req_len = dns_build_request(&header, &question, request);int slen = sendto(sockfd, request, req_len, 0, (struct sockaddr*)&dest, sizeof(struct sockaddr));struct ep_arg *eparg = (struct ep_arg*)calloc(1, sizeof(struct ep_arg));if (eparg == NULL) return -1;eparg->sockfd = sockfd;eparg->cb = cb;struct epoll_event ev;ev.data.ptr = eparg;ev.events = EPOLLIN;ret = epoll_ctl(ctx->epfd, EPOLL_CTL_ADD, sockfd, &ev); //printf(" epoll_ctl ADD: sockfd->%d, ret:%d\n", sockfd, ret);return ret;}char *domain[] = {"www.ntytcp.com","bojing.wang","www.baidu.com","tieba.baidu.com","news.baidu.com","zhidao.baidu.com","music.baidu.com","image.baidu.com","v.baidu.com","map.baidu.com","baijiahao.baidu.com","xueshu.baidu.com","cloud.baidu.com","www.163.com","open.163.com","auto.163.com","gov.163.com","money.163.com","sports.163.com","tech.163.com","edu.163.com","www.taobao.com","q.taobao.com","sf.taobao.com","yun.taobao.com","baoxian.taobao.com","www.tmall.com","suning.tmall.com","www.tencent.com","www.qq.com","www.aliyun.com","www.ctrip.com","hotels.ctrip.com","hotels.ctrip.com","vacations.ctrip.com","flights.ctrip.com","trains.ctrip.com","bus.ctrip.com","car.ctrip.com","piao.ctrip.com","tuan.ctrip.com","you.ctrip.com","g.ctrip.com","lipin.ctrip.com","ct.ctrip.com"
};static void dns_async_client_result_callback(struct dns_item *list, int count) {int i = 0;for (i = 0;i < count;i ++) {printf("name:%s, ip:%s\n", list[i].domain, list[i].ip);}
}int main(int argc, char *argv[]) {
#if 0dns_client_commit(argv[1]);
#elsestruct async_context *ctx = dns_async_client_init();if (ctx == NULL) return -2;int count = sizeof(domain) / sizeof(domain[0]);int i = 0;for (i = 0;i < count;i ++) {dns_async_client_commit(ctx, domain[i], dns_async_client_result_callback);//sleep(2);}getchar();
#endif}

3、内存池

内存池主要是解决,频繁开辟和释放内存,造成的内存碎片问题,大量的内存碎片,会导致我们分配内存失败。
内存池是通过,申请比较大的内存块,后面慢慢的去使用他,避免重复申请和释放内存带来的效率消耗和大量内存碎片

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>#include <fcntl.h>#define MP_ALIGNMENT       		32
#define MP_PAGE_SIZE			4096
#define MP_MAX_ALLOC_FROM_POOL	(MP_PAGE_SIZE-1)#define mp_align(n, alignment) (((n)+(alignment-1)) & ~(alignment-1))
#define mp_align_ptr(p, alignment) (void *)((((size_t)p)+(alignment-1)) & ~(alignment-1))struct mp_large_s {struct mp_large_s *next;void *alloc;
};struct mp_node_s {unsigned char *last;unsigned char *end;struct mp_node_s *next;size_t failed;
};struct mp_pool_s {size_t max;struct mp_node_s *current;struct mp_large_s *large;struct mp_node_s head[0];};struct mp_pool_s *mp_create_pool(size_t size);
void mp_destory_pool(struct mp_pool_s *pool);
void *mp_alloc(struct mp_pool_s *pool, size_t size);
void *mp_nalloc(struct mp_pool_s *pool, size_t size);
void *mp_calloc(struct mp_pool_s *pool, size_t size);
void mp_free(struct mp_pool_s *pool, void *p);struct mp_pool_s *mp_create_pool(size_t size) {struct mp_pool_s *p;int ret = posix_memalign((void **)&p, MP_ALIGNMENT, size + sizeof(struct mp_pool_s) + sizeof(struct mp_node_s));if (ret) {return NULL;}p->max = (size < MP_MAX_ALLOC_FROM_POOL) ? size : MP_MAX_ALLOC_FROM_POOL;p->current = p->head;p->large = NULL;p->head->last = (unsigned char *)p + sizeof(struct mp_pool_s) + sizeof(struct mp_node_s);p->head->end = p->head->last + size;p->head->failed = 0;return p;}void mp_destory_pool(struct mp_pool_s *pool) {struct mp_node_s *h, *n;struct mp_large_s *l;for (l = pool->large; l; l = l->next) {if (l->alloc) {free(l->alloc);}}h = pool->head->next;while (h) {n = h->next;free(h);h = n;}free(pool);}void mp_reset_pool(struct mp_pool_s *pool) {struct mp_node_s *h;struct mp_large_s *l;for (l = pool->large; l; l = l->next) {if (l->alloc) {free(l->alloc);}}pool->large = NULL;for (h = pool->head; h; h = h->next) {h->last = (unsigned char *)h + sizeof(struct mp_node_s);}}static void *mp_alloc_block(struct mp_pool_s *pool, size_t size) {unsigned char *m;struct mp_node_s *h = pool->head;size_t psize = (size_t)(h->end - (unsigned char *)h);int ret = posix_memalign((void **)&m, MP_ALIGNMENT, psize);if (ret) return NULL;struct mp_node_s *p, *new_node, *current;new_node = (struct mp_node_s*)m;new_node->end = m + psize;new_node->next = NULL;new_node->failed = 0;m += sizeof(struct mp_node_s);m = mp_align_ptr(m, MP_ALIGNMENT);new_node->last = m + size;current = pool->current;for (p = current; p->next; p = p->next) {if (p->failed++ > 4) {current = p->next;}}p->next = new_node;pool->current = current ? current : new_node;return m;}static void *mp_alloc_large(struct mp_pool_s *pool, size_t size) {void *p = malloc(size);if (p == NULL) return NULL;size_t n = 0;struct mp_large_s *large;for (large = pool->large; large; large = large->next) {if (large->alloc == NULL) {large->alloc = p;return p;}if (n ++ > 3) break;}large = mp_alloc(pool, sizeof(struct mp_large_s));if (large == NULL) {free(p);return NULL;}large->alloc = p;large->next = pool->large;pool->large = large;return p;
}void *mp_memalign(struct mp_pool_s *pool, size_t size, size_t alignment) {void *p;int ret = posix_memalign(&p, alignment, size);if (ret) {return NULL;}struct mp_large_s *large = mp_alloc(pool, sizeof(struct mp_large_s));if (large == NULL) {free(p);return NULL;}large->alloc = p;large->next = pool->large;pool->large = large;return p;
}void *mp_alloc(struct mp_pool_s *pool, size_t size) {unsigned char *m;struct mp_node_s *p;if (size <= pool->max) {p = pool->current;do {m = mp_align_ptr(p->last, MP_ALIGNMENT);if ((size_t)(p->end - m) >= size) {p->last = m + size;return m;}p = p->next;} while (p);return mp_alloc_block(pool, size);}return mp_alloc_large(pool, size);}void *mp_nalloc(struct mp_pool_s *pool, size_t size) {unsigned char *m;struct mp_node_s *p;if (size <= pool->max) {p = pool->current;do {m = p->last;if ((size_t)(p->end - m) >= size) {p->last = m+size;return m;}p = p->next;} while (p);return mp_alloc_block(pool, size);}return mp_alloc_large(pool, size);}void *mp_calloc(struct mp_pool_s *pool, size_t size) {void *p = mp_alloc(pool, size);if (p) {memset(p, 0, size);}return p;}void mp_free(struct mp_pool_s *pool, void *p) {struct mp_large_s *l;for (l = pool->large; l; l = l->next) {if (p == l->alloc) {free(l->alloc);l->alloc = NULL;return ;}}}int main(int argc, char *argv[]) {int size = 1 << 12;struct mp_pool_s *p = mp_create_pool(size);int i = 0;for (i = 0;i < 10;i ++) {void *mp = mp_alloc(p, 512);
//		mp_free(mp);}//printf("mp_create_pool: %ld\n", p->max);printf("mp_align(123, 32): %d, mp_align(17, 32): %d\n", mp_align(24, 32), mp_align(17, 32));//printf("mp_align_ptr(p->current, 32): %lx, p->current: %lx, mp_align(p->large, 32): %lx, p->large: %lx\n", mp_align_ptr(p->current, 32), p->current, mp_align_ptr(p->large, 32), p->large);int j = 0;for (i = 0;i < 5;i ++) {char *pp = mp_calloc(p, 32);for (j = 0;j < 32;j ++) {if (pp[j]) {printf("calloc wrong\n");}printf("calloc success\n");}}//printf("mp_reset_pool\n");for (i = 0;i < 5;i ++) {void *l = mp_alloc(p, 8192);mp_free(p, l);}mp_reset_pool(p);//printf("mp_destory_pool\n");for (i = 0;i < 58;i ++) {mp_alloc(p, 256);}mp_destory_pool(p);return 0;}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/137944.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

小谈设计模式(5)—开放封闭原则

小谈设计模式&#xff08;5&#xff09;—开放封闭原则 专栏介绍专栏地址专栏介绍 开放封闭原则核心思想关键词概括扩展封闭 解释抽象和接口多态 代码示例代码解释 优缺点优点可扩展性可维护性可复用性高内聚低耦合 缺点抽象设计的复杂性需要预留扩展点可能引入过度设计 总结 专…

软件工程第一次作业参考答案

题目 名词解释&#xff1a;软件危机、软件、软件工程、软件生命周期、瀑布模型、原型模型、增量模型、喷泉模型、敏捷过程模型。 答案 软件危机&#xff1a;软件危机是指在软件开发过程中所面临的一系列问题和挑战&#xff0c;包括成本超支、进度延误、质量不达标等。 软件…

ubuntu 22.04 服务器网卡无IP地址

ssh连接服务器连接不上&#xff0c;提示如下&#xff1b; 连接显示器&#xff0c;ip addr ls 命令查看IP地址&#xff0c;有网卡但没有IP地址 solution&#xff1a; sudo dhclient enp10s0用于通过 DHCP 协议获取网络配置信息并为名为 enp10s0 的网络接口分配 IP 地址,enp1…

TiDB 7.1.0 LTS 特性解读丨关于资源管控 (Resource Control) 应该知道的 6 件事

TiDB 7.1.0 LTS 在前段时间发布&#xff0c;相信很多同学都已经抢先使用了起来&#xff0c;甚至都已然经过一系列验证推向了生产环境。面对 TiDB 7.1 若干重要特性&#xff0c;新 GA 的资源管控 (Resource Control) 是必须要充分理解、测试的一个重量级特性。对于常年奋斗在一线…

一个热爱自动驾驶但妥妥外行之人的思考-2023

时间节点为2023年9月&#xff0c;有效期当下及过往&#xff0c;不含未来。 这些年准确说从10年就很关注自动驾驶行业&#xff0c;包括物流/机器人/汽车等。 也和行业内&#xff0c;行业外的朋友做了大量的交流。点滴沟通放在如下链接中&#xff1a; 动态 - CSDN 一些过去的观…

新型智慧公厕“1+3+N”架构,平台、系统、应用的创新

近年来&#xff0c;随着人民生活水平的提高&#xff0c;人们对公共设施的要求也越来越高。其中&#xff0c;如厕问题一直是人们关注的焦点&#xff0c;但传统的公厕设施已经不能满足人们对干净、舒适、安全的需求&#xff0c;这促使了新型智慧公厕的诞生与应用&#xff0c;以如…

八月份跳槽了,历经华为测开岗4轮面试,不出意外,被刷了...

大多数情况下&#xff0c;测试员的个人技能成长速度&#xff0c;远远大于公司规模或业务的成长速度。所以&#xff0c;跳槽成为了这个行业里最常见的一个词汇。 前几天&#xff0c;我看到有朋友留言说&#xff0c;他在面试华为的测试开发工程师的时候&#xff0c;灵魂拷问三小…

c++ 纯虚函数、抽象类

一、 纯虚函数 抽象类 只要有一个纯虚函数&#xff0c;这个类称为抽象类 抽象类的特点 1、无法实例化 2、抽象类的子类&#xff0c;必须要重写父类中的纯虚函数&#xff0c;否者也属于抽象类 例子一 #include <iostream> #include <string.h> using namespa…

MySQL数据库详解 三:索引、事务和存储引擎

文章目录 1. 索引1.1 索引的概念1.2 索引的作用1.3 如何实现索引1.4 索引的缺点1.5 建立索引的原则依据1.6 索引的分类和创建1.6.1 普通索引1.6.2 唯一索引1.6.3 主键索引1.6.4 组合索引1.6.5 全文索引 1.7 查看索引1.8 删除索引 2. 事务2.1 事务的概念2.2 事务的ACID特性2.2.1…

单片机学习--->Keil多文件工程

1、在文件夹中创建新的文件夹 目录&#xff1a; App 文件夹&#xff1a;用于存放外设驱动文件&#xff0c;如 LED、数码管、定时器等。 Obj 文件夹&#xff1a;用于存放编译产生的 c/汇编/链接的列表清单、调试信息、 hex 文件、预览信息、封装库等文件。 Public 文件夹&#x…

蓝桥杯 题库 简单 每日十题 day3

01 约数个数 题目描述 本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。 1200000 有多少个约数&#xff08;只计算正约数&#xff09;。 解题思路 枚举&#xff0c;从1开始一直到1200000本身都作为1200000的除数&#xff0c;…

Spring 6.0 新特性

文章目录 Spring的发展历史AOTGraalVMSpringBoot实战AOTRuntimeHints案例分析RuntimeHintsRegistrar SpringBoot中AOT核心代码 Spring的发展历史 AOT Spring 6.0的新特性Ahead of Time&#xff08;AOT&#xff09;编译是一种技术&#xff0c;可以提前将Spring应用程序编译成原…

JWT安全及案例实战

文章目录 JWT 安全1. Cookie2. Session3. Token4. JWT4.1 JWT概述4.1.1 JWT头4.1.2 有效载荷4.1.3 签名哈希4.1.4 通信流程 4.2 JWT 漏洞描述4.3 JWT 漏洞原理4.4 JWT 安全防御 5. WebGoat 靶场实验5.1 第四关5.2 第五关5.3 第七关 越权与逻辑漏洞 Web漏洞点只有一个入口&#…

Direct3D融合技术

该技术能使我们将当前要进行光栅化的像素的颜色与先前已已光栅化并处于同一位置的像素的颜色进行合成&#xff0c;即将正在处理的图元颜色值与存储在后台缓存中的像素颜色值进行合成(混合)&#xff0c;利用该技术我们可得到各种各样的效果&#xff0c;尤其是透明效果。 在融合…

云渲染是怎么做到不排队的

云渲染排队严重影响了用户的使用体验&#xff0c;还会导致用户的流失&#xff0c;因此解决渲染不排队的问题对于云渲染平台来说是非常重要的。而作为云渲染平台&#xff0c;自己的机器基本都是固定的&#xff0c;哪如何解决用户渲染排队的问题呢&#xff1f;我们一起来看看全国…

天地图绘制区域图层

背景&#xff1a; 业务方要求将 原效果图 参考效果图 最终实现效果 变更点&#xff1a; 1.将原有的高德地图改为天地图 2.呈现形式修改&#xff1a;加两层遮罩&#xff1a;半透明遮罩层mask区域覆盖物mask 实现过程&#xff1a; 1.更换地图引入源 <link rel"style…

免杀对抗-java语言-shellcode免杀-源码修改+打包exe

JAVA-ShellCode免杀-源码修改&打包EXE Shellcode-生成/上线 1.msf生成shellcode 命令&#xff1a;msfvenom -p java/meterpreter/reverse_tcp LHOSTx.x.x.x LPORTxxxx -f jar -o msf.jar 2.msf设置监听 3.执行msf生成的shellcode jar包&#xff0c;成功上线 命令&#xff1…

网络安全第一次作业

1、什么是防火墙 防火墙是一种网络安全系统&#xff0c;它根据预先确定的安全规则监视和控制传入和传出的网络流量。其主要目的是阻止对计算机或网络的未经授权的访问&#xff0c;同时允许合法通信通过。 防火墙可以在硬件、软件或两者的组合中实现&#xff0c;并且可以配置为根…

西部数据硬盘查询

保修状态 | WD 支持 保修状态 | WD 支持 https://support-cn.wd.com/app/warrantystatusweb https://support-cn.wd.com/app/warrantystatusweb 选择大陆

【C++】STL—— unordered_map的介绍和使用、 unordered_map的构造函数和迭代器、 unordered_map的增删查改函数

文章目录 1. unordered_map的介绍2. unordered_map的使用2.1unordered_map的构造函数2.2unordered_map的迭代器2.3unordered_map的容量和访问函数2.4unordered_map的增删查改函数 1. unordered_map的介绍 unordered_map的介绍 &#xff08;1&#xff09;unordered_map是存储&l…