美文网首页服务器开发
一起来写web server 02 -- 多进程版本

一起来写web server 02 -- 多进程版本

作者: Yihulee | 来源:发表于2016-10-27 22:54 被阅读22次

UNP的第30章客户/服务器程序设计范式中提到了这种模型.

主要的思想

这种模型的思想非常简单,具体来说,就是,没当用户connect到来之后,立马fork一个子进程去处理连接,代码如下:

int main(int argc, char *argv[])
{
    int listenfd = Open_listenfd(8080); /* 8080号端口监听 */

    while (true) /* 无限循环 */
    {
        struct sockaddr_in clientaddr;
        socklen_t len = sizeof(clientaddr);
        int connfd = Accept(listenfd, (SA*)&clientaddr, &len);
        addsig(SIGCHLD, sig_chld); /* 添加信号处理函数 */
        int pid;
        if ((pid = Fork()) == 0) /* 子线程 */
        {
            printf("\nnew process:%d\n", getpid());
            close(listenfd);
            doit(connfd); /* 处理连接 */
            close(connfd); /* 关闭socket描述符 */
            printf("\nend of process:%d\n", getpid());
            exit(0);
        }
        close(connfd);
    }
    return 0;
}

借用stevens老爷子的一张图,应该是这么干的:
首先客户端通过conncect函数请求和服务器的连接.


接下来服务器调用Accept函数接收了对方的连接,connfd指代这个连接.

然后父进程调用fork函数生成了一个子进程.生成的子进程里面的数据和父进程是一模一样的,它也包含了这个connfd,所以现在客户和两个进程连接.

父进程关闭这个连接,然后由子进程来处理连接,这样一个交互就完成了.

需要注意的地方

僵死进程

子进程运行完毕之后,如果父进程不调用wait或者waitpid函数来处理处理的话,这些已经运行完成的子进程便成为了僵死进程,僵死进程会占用系统的资源,小部分的僵死进程还好,不过像我们这种需要长时间运行的服务器程序,点滴的僵死进程积累起来,这个量是非常恐怖的.所以对于僵死进程,我们是不能够忍受的.你可能会奇怪,为什么子进程运行完了还要父进程来收尸,直接释放资源不就好了吗?其实操作系统这么安排必定有它的道理,只是我们暂时用不到罢了.

设置僵死状态的目的是维护子进程的信息,以便父进程在以后某个时候获取,这些信息包括子进程的进程ID,终止状态以及资源利用信息(cpu时间,内存使用量等等).如果一个进程终止,而该进程有子进程处于僵死状态,那么它的所有僵死进程的父进程ID将会重置为1(init进程).继承这些子进程的init进程将清理他们(也就是说,init进程将wait它们,从而去除它们的僵死进程).

值得我们注意的是,当一个子进程运行完毕之后,系统会给父进程发送一个SIGCHLD信号,只要我们处理这个信号,就能够及时地回收子进程占用的一些资源.

所以在代码的第10行处addsig(SIGCHLD, sig_chld);,我们添加了SIGCHLD的信号处理函数.
函数如下:

void
sig_chld(int signo) /* 处理僵死进程 */
{
    pid_t pid;
    int stat;
    while ((pid = waitpid(-1, &stat, WNOHANG)) > 0)
        printf("child %d terminated\n", pid);
    return;
}

waitpid函数的第一个参数-1表示等待第一个终止的子进程,&stat可以获取终止进程的一些信息,而WNOHANG表示不用阻塞,不管有没有子进程终止,立即返回,没有子进程终止的话,会返回一个小于0的数,否则的话返回的是一个大于0的数.为什么要用while循环呢?很简单,因为系统是有子进程终止的时候才通知我们,不会因为僵死的子进程还未处理而同通知我们,所以我们要一次性将已经挂掉的子进程全部处理掉才行.

总结

这次的代码也非常简单,但是性能比之前的要强上不少.当然,这个能够同时处理的连接数目取决于系统可以生成的进程的数目.这次的代码是多进程版本的,下次的代码,我们就要编程多线程版本的啦.

代码可以在这里查看:https://github.com/lishuhuakai/Spweb

相关文章

网友评论

    本文标题:一起来写web server 02 -- 多进程版本

    本文链接:https://www.haomeiwen.com/subject/mipsuttx.html