Linux 动态进程池

Linux 动态进程池,linux,process,c,fork,Linux,Process,C,Fork,我正在Unix系统上用C编写一个客户机-服务器(TCP)程序。客户端发送一些信息,服务器应答。每个子进程只有一个连接。新连接使用池中的预运行进程,并且池大小是动态的,因此如果空闲进程(不为客户机提供服务的进程)的数量降得太低,它应该创建新进程,同样,如果空闲进程的数量太高,则应该终止额外的进程 这是我的服务器代码。每个连接都使用fork()创建一个新的子进程。每个连接都在一个新进程中运行。如何创建如上所述的动态池 int main(int argc, char * argv[]) {

我正在Unix系统上用C编写一个客户机-服务器(TCP)程序。客户端发送一些信息,服务器应答。每个子进程只有一个连接。新连接使用池中的预运行进程,并且池大小是动态的,因此如果空闲进程(不为客户机提供服务的进程)的数量降得太低,它应该创建新进程,同样,如果空闲进程的数量太高,则应该终止额外的进程

这是我的服务器代码。每个连接都使用
fork()
创建一个新的子进程。每个连接都在一个新进程中运行。如何创建如上所述的动态池

int main(int argc, char * argv[])
{
        int cfd;
        int listener = socket(AF_INET, SOCK_STREAM, 0); //create listener socket 
        if(listener < 0){
            perror("socket error");
            return 1;
        }
        struct sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_port = htons(PORT);
        addr.sin_addr.s_addr = htonl(INADDR_ANY);
        int binding = bind(listener, (struct sockaddr *)&addr, sizeof(addr));
        if(binding < 0){
            perror("binding error");
            return 1;
        }
        listen(listener, 1); //listen for new clients
        signal(SIGCHLD,handler);
        int pid;

        for(;;) // infinity loop on server
        {
            cfd = accept(listener, NULL, NULL); //client socket descriptor
            pid = fork(); //make child proc
            if(pid == 0) //in child proc...
            {
                close(listener); //close listener socket descriptor
                ... //some server actions that I do.(receive or send) 
                close(cfd); // close client fd
                return 0;
            }
            close(cfd);
intmain(intargc,char*argv[])
{
国际计算流体力学;
int listener=socket(AF_INET,SOCK_STREAM,0);//创建侦听器套接字
if(侦听器<0){
perror(“套接字错误”);
返回1;
}
地址中的结构sockaddr\u;
addr.sin_family=AF_INET;
地址SINU port=htons(端口);
addr.sin_addr.s_addr=htonl(INADDR_ANY);
int binding=bind(监听器,(结构sockaddr*)&addr,sizeof(addr));
if(绑定<0){
perror(“绑定错误”);
返回1;
}
侦听(侦听器,1);//侦听新客户端
信号(SIGCHLD,处理器);
int-pid;
对于服务器上的(;)//无限循环
{
cfd=accept(侦听器,NULL,NULL);//客户端套接字描述符
pid=fork();//生成子进程
如果(pid==0)//在子进程中。。。
{
关闭(侦听器);//关闭侦听器套接字描述符
…//我执行的一些服务器操作。(接收或发送)
关闭(cfd);//关闭客户端fd
返回0;
}
关闭(cfd);

}

如果在同一侦听套接字上的
accept
中阻止了多个进程,则传入的新连接将传递给其中一个进程。(根据情况,可能会有几个进程被唤醒,但实际上只有一个进程会获得连接)。因此,您需要在
侦听
之后,但在
接受
之前分叉几个子项。处理请求后,子项返回到
接受
,而不是处理(1)和(2)的
退出

(3) 更难。您需要某种形式的IPC。通常情况下,您会有一个只管理拥有正确数量的子进程的父进程。您的子进程需要使用IPC告诉父进程它们有多忙。然后父进程可以分叉更多的子进程(进入上面的
accept
循环)或者向孩子们发送信号,告诉他们结束并离开。它还应该处理
等待
儿童,处理意外死亡等问题

您想要使用的IPC可能是共享内存。您的两个选项是SysV(
shmget)和POSIX(
shm_open`)共享内存。如果可用,您可能需要后者。您必须处理同步访问(POSIX和SysV都提供信号量来帮助这一点,还是更喜欢POSIX)或仅使用原子访问

(实际上,您可能不希望进程在超过X个空闲子进程的瞬间退出,这将导致重复收割和繁殖它们,这是非常昂贵的。相反,您可能希望了解它们在过去一秒钟中的利用率……因此,您的数据比使用/空闲位图更复杂。)

有很多守护进程都是这样工作的,因此您可以很容易地找到代码示例。当然,如果您查看Apache,您可能会发现它更加复杂,以获得良好的性能并在任何地方都可以移植