我写了一个小的tcp服务器,它为每个传入连接创建一个新线程:
while (server_running)
{
client_sock = accept(server_sock,
(struct sockaddr *)&client_name,
&client_name_len);
if(!server_running)
break;
if (client_sock == -1)
continue;
/* accept_request(client_sock); */
if (pthread_create(&newthread , NULL, &accept_request, &client_sock) != 0)
perror("pthread_create");
}
大约380次成功连接后,出现错误消息
每次新连接尝试都会发生' pthread_create:无法分配内存'
。由于accept_request
正常运行,我真的不知道这是从哪里来的。我还注意到在运行期间有许多状态为TIME_WAIT
的连接(我使用了netstat
)。那么哪里出错了?
答案 0 :(得分:11)
当你的线程退出时,它仍会在内存中挂起。默认情况下,linux上的一个线程占用8或10MB的堆栈,因此对于380个线程,您可能会使用近4GB的虚拟内存 - 这可能会对您的系统造成限制。
要在完成执行时释放一个线程,您需要在该线程上调用pthread_join()
,或者您可以将该线程设置为'分离'线程。分离的线程在结束执行时将自动处理。你可以添加
pthread_detach(pthread_self());
到accept_request()
线程函数的开头,使其成为一个分离的线程。
作为旁注,你在
的召唤中遇到了竞争条件 pthread_create(&newthread , NULL, &accept_request, &client_sock)
在这里,您将& client_sock传递给线程,一个局部变量。如果有两个客户端几乎同时连接到您的服务器,则最后一个客户端将覆盖client_sock
变量,并且您的2个线程将看到相同的文件描述符。你可以,例如而是这样做:
int *new_fd = malloc(sizeof *new_fd);
*new_fd = client_sock;
pthread_create(&newthread , NULL, &accept_request, new_fd)
并确保你的accept_request线程free()
是传入的参数。