memched1.0源码阅读(3)——运行流程
来源:互联网 发布:mac如何卸载opera 编辑:程序博客网 时间:2024/05/22 17:27
一、主流程,直接从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的接口),进入循环,等待各种事件的发生
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个链表,每一个链表都存放了相同大小的itemstatic 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中的一些机制
0 0
- memched1.0源码阅读(3)——运行流程
- memched1.0源码阅读(4)——事件的处理流程
- memched1.0源码阅读(1)——介绍
- memched1.0源码阅读(2)——基础数据结构
- Horizon 源码阅读(四)—— 调用Novaclient流程
- Horizon 源码阅读(四)—— 调用Novaclient流程
- ibatis源码分析—运行流程解析(一)
- ibatis源码分析—运行流程解析(二)
- tinyhttpd源码阅读(1)——服务器执行流程
- Android入门 —— activity的启动流程源码阅读
- QUnit源码阅读(3):asyncTest基本执行流程
- Diksam代码阅读(2)——Diksam编译运行的主要流程
- Horizon 源码阅读(三)—— Horizon 用户登录流程
- Horizon 源码阅读(三)—— Horizon 用户登录流程
- FAAC源码阅读(2)——AAC的编解码流程
- Gaea源码阅读(二):客户端流程
- 阅读源码流程
- Tomcat连接器运行过程(源码阅读)
- poj2777 Count Color
- TS流打包总结
- 什么是一阶逻辑(First-order Logic)
- tushare金融数据
- 视图
- memched1.0源码阅读(3)——运行流程
- GCC编译和GDB调试
- Easy-题目45:58. Length of Last Word
- [Maven]5,相关配置
- Java性能提高小常识
- 怎么快速看懂别人写的module和ipcore
- Android基础知识整合篇——Activity知识点
- Easy-题目46:205. Isomorphic Strings
- 鼠标经过旋转特效