2015-07-22 37 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來解決。

相關問題