Chinaunix首页 | 论坛 | 博客
  • 博客访问: 92358
  • 博文数量: 31
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 380
  • 用 户 组: 普通用户
  • 注册时间: 2014-02-24 22:04
文章分类

全部博文(31)

文章存档

2014年(31)

我的朋友

分类: C/C++

2014-10-17 11:31:33



main
    |-----......
    |-----socketServer
    |-----tcpsetserveropt
    |-----daemon_init
    |-----tracker_service_init
    |-----.....


tracker_service_init函数对tracker服务进行初始化工作,主要完成的任务有下面几点
(1) 初始化线程锁与线程属性变量
(2) 初始化全局Task链表全局变量g_free_queue
(3) 初始化工作线程全局变量g_thread_data
(4) 创建工作线程

tracker_service_init函数如下

点击(此处)折叠或打开

  1. int tracker_service_init()
  2. {
  3.     int result;
  4.     struct tracker_thread_data *pThreadData;
  5.     struct tracker_thread_data *pDataEnd;
  6.     pthread_t tid;
  7.     pthread_attr_t thread_attr;
  8.     //初始化tracker_thread_lock锁
  9.     if ((result=init_pthread_lock(&tracker_thread_lock)) != 0)
  10.     {
  11.         return result;
  12.     }
  13.     //初始化lb_thread_lock锁
  14.     if ((result=init_pthread_lock(&lb_thread_lock)) != 0)
  15.     {
  16.         return result;
  17.     }
  18.     //初始化线程属性
  19.     if ((result=init_pthread_attr(&thread_attr, g_thread_stack_size)) != 0)
  20.     {
  21.         logError("file: "__FILE__", line: %d, " \
  22.             "init_pthread_attr fail, program exit!", __LINE__);
  23.         return result;
  24.     }
  25.     //初始化全局链表
  26.     if ((result=free_queue_init(g_max_connections, TRACKER_MAX_PACKAGE_SIZE,\
  27.                 TRACKER_MAX_PACKAGE_SIZE, sizeof(TrackerClientInfo))) != 0)
  28.     {
  29.         return result;
  30.     }

  31.     g_thread_data = (struct tracker_thread_data *)malloc(sizeof( \
  32.                 struct tracker_thread_data) * g_work_threads);
  33.     if (g_thread_data == NULL)
  34.     {
  35.         logError("file: "__FILE__", line: %d, " \
  36.             "malloc %d bytes fail, errno: %d, error info: %s", \
  37.             __LINE__, (int)sizeof(struct tracker_thread_data) * \
  38.             g_work_threads, errno, STRERROR(errno));
  39.         return errno != 0 ? errno : ENOMEM;
  40.     }

  41.     g_tracker_thread_count = 0;
  42.     pDataEnd = g_thread_data + g_work_threads;
  43.     for (pThreadData=g_thread_data; pThreadData<pDataEnd; pThreadData++)
  44.     {
  45.         pThreadData->ev_base = event_base_new();//创建eventbase
  46.         if (pThreadData->ev_base == NULL)
  47.         {
  48.             result = errno != 0 ? errno : ENOMEM;
  49.             logError("file: "__FILE__", line: %d, " \
  50.                 "event_base_new fail.", __LINE__);
  51.             return result;
  52.         }

  53.         if (pipe(pThreadData->pipe_fds) != 0)//创建管道
  54.         {
  55.             result = errno != 0 ? errno : EPERM;
  56.             logError("file: "__FILE__", line: %d, " \
  57.                 "call pipe fail, " \
  58.                 "errno: %d, error info: %s", \
  59.                 __LINE__, result, STRERROR(result));
  60.             break;
  61.         }

  62.         if ((result=set_nonblock(pThreadData->pipe_fds[0])) != 0)//设置非阻塞
  63.         {
  64.             break;
  65.         }

  66.         if ((result=pthread_create(&tid, &thread_attr, \//创建工作线程
  67.             work_thread_entrance, pThreadData)) != 0)
  68.         {
  69.             logError("file: "__FILE__", line: %d, " \
  70.                 "create thread failed, startup threads: %d, " \
  71.                 "errno: %d, error info: %s", \
  72.                 __LINE__, g_tracker_thread_count, \
  73.                 result, STRERROR(result));
  74.             break;
  75.         }
  76.         else //创建线程成功
  77.         {
  78.             if ((result=pthread_mutex_lock(&tracker_thread_lock)) != 0)//加锁
  79.             {
  80.                 logError("file: "__FILE__", line: %d, " \
  81.                     "call pthread_mutex_lock fail, " \
  82.                     "errno: %d, error info: %s", \
  83.                     __LINE__, result, STRERROR(result));
  84.             }
  85.             g_tracker_thread_count++; //修改全局线程数目,这里加锁是为了防止该变量在其他线程中被修改
  86.             if ((result=pthread_mutex_unlock(&tracker_thread_lock)) != 0)
  87.             {
  88.                 logError("file: "__FILE__", line: %d, " \
  89.                     "call pthread_mutex_lock fail, " \
  90.                     "errno: %d, error info: %s", \
  91.                     __LINE__, result, STRERROR(result));
  92.             }
  93.         }
  94.     }

  95.     pthread_attr_destroy(&thread_attr);//销毁线程属性变量

  96.     return 0;
  97. }
在tracker_thread_init函数的开头处初始化了线程锁与线程属性变量,初始化全局g_free_queue队列在函数free_queue_init中

tracker_thread_data数据结构如下

点击(此处)折叠或打开

  1. struct tracker_thread_data
  2. {
  3.         struct event_base *ev_base;
  4.         int pipe_fds[2];
  5. }
一个tracker_thread_data对象包括一个eventbase指针对象与一个管道pipe对象


free_queue_init函数代码如下:

点击(此处)折叠或打开

  1. //初始化g_free_queue与g_mpool,g_mpool表示链表首节点,g_free_queue表示链表
  2. int free_queue_init(const int max_connections, const int min_buff_size, \
  3.         const int max_buff_size, const int arg_size)
  4. {
  5.     struct fast_task_info *pTask;
  6.     char *p;
  7.     char *pCharEnd;
  8.     int block_size;
  9.     int alloc_size;
  10.     int64_t total_size;
  11.     int result;

  12.     if ((result=init_pthread_lock(&(g_free_queue.lock))) != 0)//加锁
  13.     {
  14.         logError("file: "__FILE__", line: %d, " \
  15.             "init_pthread_lock fail, errno: %d, error info: %s", \
  16.             __LINE__, result, STRERROR(result));
  17.         return result;
  18.     }

  19.     block_size = sizeof(struct fast_task_info) + arg_size;//一个块的大小=fast_task_info的大小+arg_size
  20.     alloc_size = block_size * max_connections;//需分配的字节数=一个块的大小*最大连接数

  21.     if (max_buff_size > min_buff_size)//如果参数中max大于min
  22.     {
  23.         total_size = alloc_size; //则总字节数=需分配字节数
  24.         g_free_queue.malloc_whole_block = false;//这里置为false,表示需要单独分配空间,空间已经包含在totalsize中了
  25.     }
  26.     else //当min==max 或者min>max
  27.     {
  28.         struct rlimit rlimit_data;
  29.         rlim_t max_data_size;

  30.         if (getrlimit(RLIMIT_DATA, &rlimit_data) < 0) //获取linux系统资源限制,这里获取的是一次malloc所能得到的
  31.         {//最大的空间的大小
  32.             logError("file: "__FILE__", line: %d, " \
  33.                 "call getrlimit fail, " \
  34.                 "errno: %d, error info: %s", \
  35.                 __LINE__, errno, STRERROR(errno));
  36.             return errno != 0 ? errno : EPERM;
  37.         }
  38.         if (rlimit_data.rlim_cur == RLIM_INFINITY)
  39.         {
  40.             max_data_size = 512 * 1024 * 1024;//512M
  41.         }
  42.         else
  43.         {
  44.             max_data_size = rlimit_data.rlim_cur;
  45.             if (max_data_size > 512 * 1024 * 1024)
  46.             {
  47.                 max_data_size = 512 * 1024 * 1024;
  48.             }
  49.         }

  50.         total_size = alloc_size+(int64_t)min_buff_size*max_connections;//这里相当于每个块增加了min_buff_size的大小
  51.         if (total_size <= max_data_size)//<=512M
  52.         {
  53.             g_free_queue.malloc_whole_block = true;//表示不需要单独分配空间,需要的空间已经包含在total_size中了
  54.             block_size += min_buff_size;//调整一个块的大小
  55.         }
  56.         else
  57.         {
  58.             g_free_queue.malloc_whole_block = false;//需要单独分配空间
  59.             total_size = alloc_size;//不包括min_buff_size*max_connections
  60.         }
  61.     }

  62.     g_mpool = (struct fast_task_info *)malloc(total_size);//为g_mpool分配空间
  63.     if (g_mpool == NULL)
  64.     {
  65.         logError("file: "__FILE__", line: %d, " \
  66.             "malloc "INT64_PRINTF_FORMAT" bytes fail, " \
  67.             "errno: %d, error info: %s", \
  68.             __LINE__, total_size, errno, STRERROR(errno));
  69.         return errno != 0 ? errno : ENOMEM;
  70.     }
  71.     memset(g_mpool, 0, total_size);//置0

  72.     pCharEnd = ((char *)g_mpool) + total_size;
  73.     for (p=(char *)g_mpool; p<pCharEnd; p += block_size)
  74.     {
  75.         pTask = (struct fast_task_info *)p;
  76.         pTask->size = min_buff_size;//表示单独分配的空间大小

  77.         pTask->arg = p + sizeof(struct fast_task_info);//fast_task_info结构后存放参数
  78.         if (g_free_queue.malloc_whole_block)//不需要单独分配,空间已包含在total_size
  79.         {
  80.             pTask->data = (char *)pTask->arg + arg_size;//让指针越过存放参数的空间
  81.         }
  82.         else//false,表示需要单独分配空间
  83.         {
  84.             pTask->data = (char *)malloc(pTask->size);//单独分配空间
  85.             if (pTask->data == NULL)//分配失败
  86.             {
  87.                 free_queue_destroy();

  88.                 logError("file: "__FILE__", line: %d, " \
  89.                     "malloc %d bytes fail, " \
  90.                     "errno: %d, error info: %s", \
  91.                     __LINE__, pTask->size, \
  92.                     errno, STRERROR(errno));
  93.                 return errno != 0 ? errno : ENOMEM;
  94.             }
  95.         }
  96.     }

  97.     g_free_queue.tail = (struct fast_task_info *)(pCharEnd - block_size);//找到尾部指针
  98.     for (p=(char *)g_mpool; p<(char *)g_free_queue.tail; p += block_size)//把分配的空间用指针串连起来
  99.     {
  100.         pTask = (struct fast_task_info *)p;
  101.         pTask->next = (struct fast_task_info *)(p + block_size);
  102.     }

  103.     g_free_queue.max_connections = max_connections;
  104.     g_free_queue.min_buff_size = min_buff_size;
  105.     g_free_queue.max_buff_size = max_buff_size;
  106.     g_free_queue.arg_size = arg_size;
  107.     g_free_queue.head = g_mpool;//设置队列的头节点
  108.     g_free_queue.tail->next = NULL;

  109.     return 0;
  110. }

fast_task_queue对象

点击(此处)折叠或打开

  1. struct fast_task_queue
  2. {
  3.     struct fast_task_info *head; //执行链表头节点
  4.     struct fast_task_info *tail; //指向链表尾节点
  5.     pthread_mutex_t lock; //互斥锁
  6.     int max_connections; //最大连接数
  7.     int min_buff_size; //最小的buffsize
  8.     int max_buff_size; //最大的buffsize
  9.     int arg_size; //参数size
  10.     bool malloc_whole_block; //标识fast_task_info中的数据缓冲区data是否包括在分配总内存中,还是单独进行了分配
  11. }
fast_task_info对象

点击(此处)折叠或打开

  1. struct fast_task_info
  2. {
  3.     char client_ip[IP_ADDRESS_SIZE]; //IP地址
  4.     struct event ev_read; //read event
  5.     struct event ev_write; //write event
  6.     void *arg; //extra argument pointer //指向参数
  7.     char *data; //buffer for write or recv //指向存放数据的缓冲区
  8.     int size; //alloc size //为data分配的空间的大小,默认8*1024byte
  9.     int length; //data length //当前数据缓冲区data的长度
  10.     int offset; //current offset //当前数据缓冲区data的偏移量
  11.     int req_count; //request count //request数目
  12.     struct fast_task_info *next; //下一个fast_task_info对象
  13.     TaskFinishCallBack finish_callback; //回调函数
  14. }
一个fast_task_info对象对应一个请求,请求的数据放入fast_task_info对象的数据缓冲区data中
free_queue_init函数执行完成后,全局变量g_free_queue对象初始化完成,g_free_queue对象指向的是一段连续内存,这段内存按照fast_task_info对象个数进行了划分,并使用fast_task_info对象中的next指针,进行了对象串联,info对象的空间中可能包括数据缓存区data,也有可能没有包括数据缓冲区data,是否包括数据缓冲区需要根据queue对象的malloc_whole_block指定,而malloc_whole_block又是根据连续内存分配的容量是否大于512M来决定。






阅读(1861) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~