简体   繁体   中英

Dynamic pool of processes

I'm writing a client-server (TCP) program in C on a Unix system. The client sends some information and the server answers. There's only one connection per child process. New connections use pre-running processes from a pool, and the pool size is dynamic, so if the number of free processes (processes not servicing a client) drops too low, it should create new processes, and likewise if it gets too high extra processes should be terminated.

This is my server code. Every connection make a new child process using fork() . Each connection runs in a new process. How can I make a dynamic pool like I explained above?

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);

}

If you have several processes blocked in accept on the same listen socket, then a new connection that comes in will get delivered to one of them. (Depending, several may wake up, but only one will actually get the connection). So you need to fork several children after listen , but before accept . After handling a request, the child goes back to accept instead of exit . That handles (1) and (2).

(3) is harder. You need some form of IPC. Typically, you'd have a parent process that just manages having the right number of children. Your child processes need to use IPC to tell the parent how busy they are. The parent can then either fork more children (which go into the accept loop above) or send signals to children to tell them to finish up and exit. It should also handle wait ing on children, handle unexpected deaths, etc.

The IPC you want to use is probably shared memory. Your two options are SysV ( shmget) and POSIX ( shm_open`) shared memory. You probably want the latter if available. You'll have to deal with synchronizing access (both POSIX and SysV provide semaphores to help with this, again prefer POSIX) or using atomic access only.

(You probably don't actually want a process to exit the instant there are more than X free children, that'll lead to repeatedly reaping and spawning them, which is expensive. Instead you probably want some measure of how utilized they were over the last second... So your data is more complicated than a bitmap of in use/free.)

There are a lot of daemons that work like this, so you can fairly easily find code examples. Of course, if you go look at Apache, you'll probably find it more complicated, to get good performance and be portable everywhere.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM