前面简单浏览了st_vio和st_net这两个结构体,在此稍微总结下,mysql是一个连接一个线程专门去处理的,线程用THD结构体描述,其中包含了st_net字段用来描述这个连接的网络属性,st_net包含st_vio,而st_vio则抽象化了网络接口。
下面就看看st_vio和st_net的初始化代码:
thd = new THD; // mysql简单暴力的直接new出thd // 此处new和初始化vio,type标志是一个remote还是local socket, // tcp则标志这是一个tcp连接,new_sock是accept出来的socket vio = vio_new(new_sock, type, tcp); // 初始化net这个结构体,主要是设置tcp option my_net_init(&thd->net, vio); // 启动线程 create_new_thread(thd);
主题mysql_main函数中就走了上面四步,还是很简单的,下面看看vio_new干了什么:
vio* vio_new(new_sock, type, tcp){ // my_malloc是一个简单对malloc的封装,主要封装了错误处理的逻辑 vio = my_malloc(sizeof(vio)); // vio_init是填充vio这个结构体对象,刚才说了,vio抽象了io函数 // 那么这里就是为了把vio中的函数指针指向正确的实现函数 // 注意,读函数调用的是vio_read vio_init(vio, type, new_sock, 0 , tcp); }
然后,把vio放入net中,并设置一些基本网络属性,诸如:设置最大包大小,读写超时时间,非阻塞模式,用nodelay模式禁止nagle算法(快速发包,不等拥塞处理)
my_bool my_net_init(net, vio) { net->vio = vio; my_net_local_init(net); net->buff = my_malloc(net->max_packet + NET_HEADER_SIZE + COMP_HEAD_SIZE, flag); net->buff_end = net->buff + net->max_packet; net->error=0; net->return_status=0; net->pkt_nr=net->compress_pkt_nr=0; net->write_pos=net->read_pos = net->buff; //??? net->last_error[0]=0; net->compress=0; net->reading_or_writing=0; net->where_b = net->remain_in_buf=0; net->last_errno=0; net->unused= 0; // 此处传入FALSE设置为非阻塞 vio_blocking(vio, FALSE, &old_mode); // no blocking mode // 直接发送,禁用nagle算法,没有拥塞控制 vio_fastsend(vio, 0); // set on the nondelay to forbid the nale argorithm } void my_net_local_init(net) { // set max_packet, read write time out, retry_count, packet_size }
自此,网络部分就初始化完毕了,后面的create_thread会开始处理mysql的连接逻辑。