多线程
就像上面提到的pthread_create可以用来创建一个线程,线程的主函数是listen_thread,你可以在后面提供的代码中找到它,这是一个非常简单的创建监听socket的函数(只有linux的版本)。另外需要做的是指定一个线程ID(pid)。
而pthread_cancel则是取消掉监听线程,当然这不意味着会自动清理各种资源,所以最安全的策略是自己手动把资源释放。(我刚看了代码,貌似在代码里面也没有在取消线程的时候释放资源)
线程有多个状态,幸好在这里并不需要担忧这个问题,但是下面的问题却是一个比较麻烦的事情。
数据共享
线程间的数据不能像普通的数据一样,因为这可能导致读写冲突。简单来说,可能遇到一个线程想要去读某段内存数据,却正好有另外一个线程正在写某段数据,当两个操作同时进行的时候,就会出现问题。通常的方法是使用互斥量。当一个线程想要去操作可能冲突的数据时,先检查互斥量的状态再决定后续的逻辑,是等待其他线程解锁或者取消自己的操作。
这是设计给外部逻辑用来读取数据的接口,根据传入的参数决定是以等待解锁的方式读取数据,还是尝试解锁读取(如果尝试失败返回NULL)。大多数情况下,我都是采用不断的查询来检查是否有新的数据。如果有新数据自然会被获取出去处理。
在读取完数据之后,必须执行这个函数来解锁互斥量。这样相当于是告诉其他线程这个资源“我”已经使用完成,其他人可以用了。大多数情况下,需要把数据情况。
写入数据的过程也是如此,写入数据之前要尝试上锁,写入完毕之后要解锁。这样,共享数据的读写流程就建立起来了:当前的子线程使用这个写入数据的接口时候,也会先去检查是否被锁住,如果锁住了就等待主线程获取数据完毕再继续执行操作;而父线程需要获取共享数据的时候也会去先检查子线程是否上锁。
更好的选择
我向来有一个一般性原则,使用自己的代码是最后的选择。现在有非常多的非常优秀的开源库,可以提供各种方便的功能来实现自己的想要的功能。为了实现一个高性能的网络消息响应系统,我们可以用libevent库,地址在http://www.monkey.org/~provos/libevent/,文档方面比较少,我在这里简单介绍一下,详细的地址请看http://blog.csdn.net/eroswang/archive/2009/05/21/4206284.aspx,这里有一个有用的例子分析"http://blog.csdn.net/liutaoxwl/archive/2008/09/22/2962143.aspx。
libevent是一个通用的IO事件处理库,除了网络IO之外,也可以处理文件IO,信号量IO。它可以支持/dev/poll,kqueue,event ports,select,poll,epoll。
在使用的时候,你需要先创建好相关的IO操作句柄,然后将它交给libevent来管理。普通的文件可以再打开之后处理READ事件时候读取,当然这有点多此一举。信号量的消息处理我没有研究过。网络消息的处理是我所关心的部分,特别是服务端的创建有一些特别。在创建完自己的listen socket之后,需要给它设置一个ev_accept事件,并提供一个accept_handle的回调来处理接受连接请求的函数。
每当有新连接连到我们的监听端口时,这个函数会被调用。在这个函数中我们需要做的事情是accept新入的请求连接。
libevnet提供了一个自动处理IO消息的机制:bufferevent。使用bufferevent,你不需要关心read/write消息的注册,只需要创建bufferevent的时候提供给它on_read和on_write的处理函数,这非常的方便。
那么,还有其他更好的选择么?也许你可以试试libev,一个建立在libevnet基础上的功能更强的开源事件驱动库,它提供了一种watcher的方式来监控消息,官方地址在http://software.schmorp.de/pkg/libev.html,里面提供了比较详尽的文档说明。