我正在尝试编写一个服务器程序,该程序分叉处理多个客户端连接的进程,每个连接创建一个线程。但是这个进程可以创建的最大线程数永远不会超过382。
为什么我不能创建更多数量的线程来处理一个文件描述符以便与一个客户端进行通信,而Linux中的每个进程的文件描述符限制为1024?
我正在使用Core-i3上运行Kubuntu的系统,内置2GB内存。
这是主要功能的代码..
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,用于突破暂停。
当达到限制(文件描述符)时,分叉进程将信号发送到父(this)进程,然后它将分叉一个新进程。下面是上面代码中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 :(得分: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
来解决。