memched1.0源码阅读(3)——运行流程
2016-05-30 20:38
316 查看
一、主流程,直接从main函数开始入手。
1、调用settings_init函数,初始化全局变量settings,这个全局变量存放了memched的环境设置。
2、解析输入的参数,设置全局变量setting相关参数。
3、调用item_init函数,进行内存对象(item)的相关设置。
4、调用event_init函数,初始libevent框架。
5、调用stats_init函数,初始化memched的状态。
6、调用assoc_init函数,初始化关联数组(是一个hashmap,用于快速查找内存对象)
7、调用conn_init函数,初始化套接字会话的数组。
8、调用slabs_init函数,初始化slabs内存分配器。
9、如果以守护进程的模式运行,那么进行守护进程的相关设置
10、如果需要,就锁定进程当前的内存页
11、调用server_socket函数,创建监听套接字,并绑定到地址上
12、调用conn_new函数,根据监听套接字以及其他的相关参数,创建一个监听套接字会话。
13、分配一个数组,用于存放被删除的对象。
14、调用delete_handler函数,添加删除事件以及相应的回调函数到libevent中(libevent框架的需要)。
15、调用event_loop函数(libevent的接口),进入循环,等待各种事件的发生
下面讲解一些初始化的函数,他们都在main函数中被调用,对memched进行相关的初始化
二、环境的初始化
三、对象数组的初始化
memched中定义了三个全局变量,存放了32个链表,然后再初始化这32个链表
五、关联数组的初始化(使用了第三方库)
六、空闲套接字会话数组的初始化
七、slabs内存分配器的初始化
1、调用settings_init函数,初始化全局变量settings,这个全局变量存放了memched的环境设置。
2、解析输入的参数,设置全局变量setting相关参数。
3、调用item_init函数,进行内存对象(item)的相关设置。
4、调用event_init函数,初始libevent框架。
5、调用stats_init函数,初始化memched的状态。
6、调用assoc_init函数,初始化关联数组(是一个hashmap,用于快速查找内存对象)
7、调用conn_init函数,初始化套接字会话的数组。
8、调用slabs_init函数,初始化slabs内存分配器。
9、如果以守护进程的模式运行,那么进行守护进程的相关设置
10、如果需要,就锁定进程当前的内存页
11、调用server_socket函数,创建监听套接字,并绑定到地址上
12、调用conn_new函数,根据监听套接字以及其他的相关参数,创建一个监听套接字会话。
13、分配一个数组,用于存放被删除的对象。
14、调用delete_handler函数,添加删除事件以及相应的回调函数到libevent中(libevent框架的需要)。
15、调用event_loop函数(libevent的接口),进入循环,等待各种事件的发生
int main (int argc, char **argv) { int c; int l_socket; // 监听者 conn *l_conn; struct in_addr addr; int lock_memory = 0; int daemonize = 0; /* init settings */ settings_init(); /* process arguments */ while ((c = getopt(argc, argv, "p:s:m:c:khvdl:")) != -1) { switch (c) { case 'p': settings.port = atoi(optarg); break; case 's': settings.maxitems = atoi(optarg); break; case 'm': settings.maxbytes = atoi(optarg)*1024*1024; break; case 'c': settings.maxconns = atoi(optarg); break; case 'h': usage(); exit(0); case 'k': lock_memory = 1; break; case 'v': settings.verbose = 1; break; case 'l': if (!inet_aton(optarg, &addr)) { fprintf(stderr, "Illegal address: %s\n", optarg); return 1; } else { settings.interface = addr; } break; case 'd': daemonize = 1; break; default: fprintf(stderr, "Illegal argument \"%c\"\n", c); return 1; } } /* initialize other stuff stuff */ // 对象列表初始化 item_init(); // 监听事件处理器初始化,这是libevent中的函数 event_init(); // 状态初始化 stats_init(); // 关联数组的初始化 assoc_init(); // 连接数组的初始化 conn_init(); // slabs内存分配器初始化 slabs_init(settings.maxbytes); // 是否作为守护进程运行 if (daemonize) { int res; res = daemon(0, 0); if (res == -1) { fprintf(stderr, "failed to fork() in order to daemonize\n"); return 1; } } /* lock paged memory if needed */ // 如果需要,那么锁定当前内存页 if (lock_memory) { mlockall(MCL_CURRENT | MCL_FUTURE); } /* create the listening socket and bind it */ // 创建监听套接字 l_socket = server_socket(settings.port); if (l_socket == -1) { fprintf(stderr, "failed to listen\n"); exit(1); } /* create the initial listening connection */ // 创建监听者 if (!(l_conn = conn_new(l_socket, conn_listening, EV_READ | EV_PERSIST))) { fprintf(stderr, "failed to create listening connection"); exit(1); } /* initialise deletion array and timer event */ // 创建删除数组,被删除的对象放在这里,当超过指定的时间之后就删除 deltotal = 200; delcurr = 0; todelete = malloc(sizeof(item *)*deltotal); delete_handler(0,0,0); /* sets up the event */ /* enter the loop */ event_loop(0); return; }
下面讲解一些初始化的函数,他们都在main函数中被调用,对memched进行相关的初始化
二、环境的初始化
void settings_init(void) { // 监听端口 settings.port = 11211; // 在任何一个地址监听 settings.interface.s_addr = htonl(INADDR_ANY); // 使用的内存的最大数量 settings.maxbytes = 64*1024*1024; /* default is 64MB */ // 最大的项目的数量 settings.maxitems = 0; /* no limit on no. of items by default */ // 最大的连接的数量 settings.maxconns = 1024; /* to limit connections-related memory to about 5MB */ settings.verbose = 0; }
三、对象数组的初始化
memched中定义了三个全局变量,存放了32个链表,然后再初始化这32个链表
<span style="font-family: Arial, Helvetica, sans-serif;">// 0~31的链表id,每一个链表对应一个id,id对应存放了大小为(2^id)的内存块的链表</span>
#define LARGEST_ID 32 // 定义32个链表,每一个链表都存放了相同大小的item static item *heads[LARGEST_ID]; // 指向32链表的尾部 static item *tails[LARGEST_ID]; // 存放了32个链表的长度 unsigned int sizes[LARGEST_ID];
// 对象链表的初始化 void item_init(void) { int i; for(i=0; i<LARGEST_ID; i++) { heads[i]=0; tails[i]=0; sizes[i]=0; } }四、memched状态初始化
// 状态初始化 void stats_init(void) { // 当前对象的数量 stats.curr_items = stats.total_items = stats.curr_conns = stats.total_conns = stats.conn_structs = 0; // 命令的数量 stats.get_cmds = stats.set_cmds = stats.get_hits = stats.get_misses = 0; // 读写字节数量的初始化 stats.curr_bytes = stats.bytes_read = stats.bytes_written = 0; // 设置启动的时间 stats.started = time(0); }
五、关联数组的初始化(使用了第三方库)
// 关联数组的初始化 void assoc_init(void) { return; }
六、空闲套接字会话数组的初始化
// 空闲的套接字会话的初始化 void conn_init(void) { freetotal = 200; freecurr = 0; freeconns = (conn **)malloc(sizeof (conn *)*freetotal); return; }
七、slabs内存分配器的初始化
// 初始化一个slabs内存分配器 /* * 全局数组slabclass中的每一个元素都有一个链表 * 如果元素的下标是i,那么它对应的链表就存储着大小为(2的i次方)内存块 */ void slabs_init(unsigned int limit) { int i; int size=1; mem_limit = limit; // 初始化每一个类型的slabs for(i=0; i<=POWER_LARGEST; i++, size*=2) { slabclass[i].size = size; // 当前链表中可以存放多少个内存块 slabclass[i].perslab = POWER_BLOCK / size; slabclass[i].slots = 0; slabclass[i].sl_curr = slabclass[i].sl_total = slabclass[i].slabs = 0; } }下一章讲解套接字创建以及libevent中的一些机制
相关文章推荐
- TS流打包总结
- 二叉搜索树的查找、插入、删除操作
- tushare金融数据
- 夜间模式的实现
- Logistic & softmax
- poj2777 Count Color
- stack的功能
- Warp : Haskell 的高性能 Web 服务器(译文)
- mysql特殊处理
- 第一篇博文--自我介绍
- .net mvc web api上传图片/文件并重命名
- 友善之臂最新版mini2440学习笔记——u-boot 1.1.6移植(一)
- 第一章 JAVA初步
- [poj 1201]Intervals 差分约束
- 设计模式笔记-Strategy策略模式
- 上拉刷新--下拉加载XListView
- openwrt中使用ubus实现进程通信
- 无线通信大作业 开题报告
- 基因数据处理43之mango之503错误
- window 局域网下文件共享的开启与关闭方法