利用进程空间进行线程通信

/*
 * Returns a fresh connection queue item.
 */
static CQ_ITEM *cqi_new(void) {
    CQ_ITEM *item = NULL;
    pthread_mutex_lock(&cqi_freelist_lock);
    if (cqi_freelist) {
        item = cqi_freelist;
        cqi_freelist = item->next;
    }
    pthread_mutex_unlock(&cqi_freelist_lock);

    if (NULL == item) {
        int i;

        /* Allocate a bunch of items at once to reduce fragmentation */
        item = malloc(sizeof(CQ_ITEM) * ITEMS_PER_ALLOC);
        if (NULL == item)
            return NULL;

        /*
         * Link together all the new items except the first one
         * (which we'll return to the caller) for placement on
         * the freelist.
         */
        for (i = 2; i < ITEMS_PER_ALLOC; i++)
            item[i - 1].next = &item[i];

        pthread_mutex_lock(&cqi_freelist_lock);
        item[ITEMS_PER_ALLOC - 1].next = cqi_freelist;
        cqi_freelist = &item[1];
        pthread_mutex_unlock(&cqi_freelist_lock);
    }

    return item;
}

最近一直想给数据库代理模块做些优化,优化的点是将mysql阻塞的c api做成让epoll这种多路复用模型来进行非阻塞管理,提高系统的并发处理能力。google了下没找到有用的信息,本来打算agentzh大师里给nginx做的drizzle是怎么实现非阻塞的,下了代码也没来得及看,主要涉及nginx模块开发,不太了解 -_-。
最后还是用了多线程的方式来提高并发能力,充分利用mysql api阻塞时候cpu的能力。模型选的是memcached的多线程模型。由于多线程编程较少接触,在看memcached的线程通信部分代码时候被它惊艳到了(我太土了 T-T),memcached的多线程都在同一个进程空间(linux下的线程只是进程里的一个执行流,共享了进程大部分的数据)里,因此直接使用malloc()分配的堆空间构造的队列进行数据传递,通过pthread_mutex_t锁来解决互斥。而通知部分,主线程使用pipe()生成的管道来与每个工作线程来进行通信,这样主线程和工作线程都可以利用epoll这类事件驱动模型进行管理(进程打开的fd资源线程也是共享的)。
大概的工作流程:
1)主线程accept到新连接后,通过RR来选择工作线程,每个工作线程都会有个数据队列用于数据共享;
2)主线程将新连接push到被选择的工作线程的数据队列;
3)往工作线程的管道发送一个字节,以“唤醒”工作线程工作;
4)工作线程的eventloop返回与主线程的通信管道的读事件;
5)工作线程从数据队列队取出新连接,然后设置读事件以及相关回调函数,返回eventloop中;


另外,在看memcached源代码过程中,发现一个很trickky的地方,在给数据队列分配新数据时,如果空闲链表为空,则会一次性分配ITEMS_PER_ALLOC(默认64)个,返回第一个,然后将其他放到空闲链表中,以备下次使用。我也模仿它这么实现,防止内存碎片嘛,多帅。然后我在写测试代码时,发现我的程序在退出清理内存时,会出现double free的coredump,gdb查了十来分钟,一直没发现问题,指针明明是有内容的,但为什么释放就会core呢?各种折腾,都没发现问题。后来重新review这部分代码时才发现原来这部分空间是malloc分配的连续空间,但是在链表里用next指针连起来了,我的清理函数想当然的遍历整个链表进行free,结果杯具就发生了。可以看到,memcached为数据队列分配的这部分空间是不会有显式释放的,因为作为一个server,本来就不用考虑退出时候清理这些内存,由进程自己释放就好了。


memcached里有很多这种省内存或者是避免内存碎片化的细节,除了它本来为key-value做的内存管理之外,连接本身也会进行复用,close的或者是超时的连接都会被放到空闲连接链表中。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值