2015-07-22 31 views
4

我正在尝试编写一个服务器程序,该程序会分叉处理多个客户端连接,从而为每个连接创建一个线程。但是这个进程可以创建的最大线程数永远不会超过382.流式套接字服务器在Linux中无法处理超过382个线程(每个连接一个)

为什么我不能创建更多数量的线程来处理一个文件描述符与一个客户端进行通信,而每个进程的文件描述符限制在Linux上是1024?

我使用的系统运行Kubuntu Core-i3与2GB RAM。

下面是主要功能的代码..在功能上没有声明

int server_start(void) 
{ 
listen(skid,10000); 
scnt=0; 
printf("Server Listening at port:%d\n",serdt.port); 
for(scnt=0;scnt<1000;) 
{ 
     sdata->cpid[scnt]=fork(); 
     switch(sdata->cpid[scnt]) 
     { 
      case -1: printf("Could not Fork\n"); break; 
      case 0: mxsubserver(scnt); exit(0); 
      default: scnt++; break; 
     } 
// } 
    //check for other parameters 
    pause(); 
} 
while(1); 
} 

变量是全局变量。信号编号为50的空白动作处理程序暂停了。

分叉进程在达到限制(文件描述符)时向父进程发送信号,然后分叉新进程。以下是在上面的代码中fork后所调用的服务器进程代码...

typedef struct 
{ 
    int cln; 
    int cnt; 
    int fd; 
    pthread_t ptid; 
}service_d; 

void mxsubserver(int cln) 
{//cln is the child sub-server number 
int ln,fd,rfp; 
pthread_t ptid; 
pthread_attr_t attr; 
iflag=1; 

sub_data = shmat(shmid,NULL,SHM_RND); 

signal(SIGINT,sub_sigint); 
signal(SIGPIPE,sub_sigpipe); 
signal(50,SIG_DFL); 
parg = malloc(sizeof(service_d)); 
parg->cln = cln; 
cnt=0; 
printf("Server Instance %d Started\n",cln); 
for(cnt=0;;) 
{ 
    if(iflag) 
    { 
     cnt++; 
     ln = (socklen_t)sizeof(struct sockaddr_in); 
     fd = accept(skid,(struct sockaddr *)&sktaddr,&ln); 
     parg->fd=fd; 
     parg->cnt=(cln*1000)+cnt; 
     pthread_attr_init(&attr); 
     pthread_create(&(parg->ptid),&attr,&service,parg); 
     pthread_detach(parg->ptid); 
     pthread_attr_destroy(&attr); 
     sub_data->openfd[cln]=cnt; 
    } 
    if(cnt>=1000) 
    { 
     printf("Limit Reached\n"); 
     iflag=getppid(); 
     printf("Signalling Parent\n"); 
     kill(iflag,50); 
     iflag=0; 
     pause(); 
    } 
    if(cnt==0) 
    { 
     free(parg); 
     exit(0); 
    } 
} 
kill(getppid(),50); 
while(1); 
return; 
} 
void sub_sigint(int sn) 
{ 
free(parg); 
shmdt(sub_data); 
exit(0); 
} 

void sub_sigpipe(int sn) 
{ 
cnt--; 
iflag=1; 
} 

void* service(void *arg) 
{//handle the client requests 
int fd,cln,l,ol; 
char im[100],*msg="This is from Server\n"; 
service_d *srd; 

srd = (service_d*)arg; 
//pthread_detach(srd->ptid); 
fd = srd->fd; 
cln = srd->cnt; 
printf("service cln: %d f: %d\n",cln,iflag); 
ol=strlen(msg); 

while(1) 
{ 
    read(fd,&l,sizeof(int)); //open to get sigpipe error if client closes 
    if(read(fd,im,l)<0) break; 
    im[l]='\0'; 
// printf("Server %d thread %d: Got >> %s\n",srd->cln,cln,im); 
    if(write(fd,&ol,sizeof(int))<0) break; 
    if(write(fd,msg,ol)<0) break;; 
} 
close(fd); 
pthread_exit("Done\n"); 
} 

谢谢。

+0

'/ proc/sys/kernel/pid_max'怎么样?和'/ proc/sys/kernel/threads-max'? – LPs

+1

最有可能的是你遇到了某种资源限制,我怀疑堆栈大小的默认设置会占用你的虚拟地址空间。 'ulimit -a'的堆栈大小告诉你什么? – Art

+0

pid_max是32768,thread_max是29138.堆栈大小是8192k字节。 –

回答

3

解决了它。

看到这个线程:Threads/Sockets limits in Linux

默认堆栈大小为8MB。当我创建382个线程时,为所有线程创建的堆栈总大小为8x382,即大约3GB。

因此,我使用pthread_attr_setstacksize将堆栈大小减少到30KB。 现在连接到大约6000个客户端后,它必须说出类似于libgcc_s.so.1 must be installed for pthread_cancel to work的内容。这可以通过以root身份运行命令apt-get install libgcc1-dbg来解决。

相关问题