10.1 多进程服务器端

来源:互联网 发布:java编程思想 面试题 编辑:程序博客网 时间:2024/06/06 00:56

1. 并发服务器端实现模型和方法:

a. 多进程服务器:通过创建多个进程提供服务

b. 多路复用服务器:通过捆绑并统一管理IO对象提供服务

c. 多线程服务器:通过生成与客户端等量的线程提供服务


2. 通过fork函数创建进程:复制正在运行的调用fork函数的进程,复制相同的内存空间。两个进程都执行fork函数以后的语句。

#include <unistd.h>pid_t fork(void);成功时返回进程ID,失败时返回-1.

父进程Parent Prcess:fork函数返回子进程ID

子进程Child Process:fork函数返回0.


3. 示例一

#include <stdio.h>#include <unistd.h>int gval = 10;int main(int argc, char *argv[]){    pid_t pid;    int lval = 20;    gval++;    lval += 5;    pid = fork();    if(pid == 0){//child gval += 2;lval += 2;    }else{gval -= 2;  lval -= 2;    }    if(pid == 0){printf("child gval = %d, lval = %d \n",gval,lval);    }else{printf("parent gval = %d, lval = %d \n",gval,lval);    }    return 0;}
运行结果:

alex@alex-virtual-machine:/extra/tcpip/10$ ./a.outparent gval = 9, lval = 23alex@alex-virtual-machine:/extra/tcpip/10$ child gval = 13, lval = 27

4. 僵死Zombie进程:进程已死,但仍旧占用系统资源

a. 子进程终止方式:exit函数传递的参数和执行return并返回值。

b. 僵死进程的产生:exit的传递值和return返回值会传递给操作系统,操作系统不会销毁子进程,直到这些值传递到父进程。

c. 如何传递值到父进程:操作系统不会主动把值传递到父进程,而是父进程主动请求,函数调用。如果父进程不主动请求,则子进程会一直处于僵死状态,所以父进程要负责收回子进程。

5. 利用wait销毁僵死进程:父进程主动请求获取子进程的返回值。

#include <sys/wait.h>pid_t wait(int * statloc);成功时返回终止的子进程ID,失败返回-1


子进程终止参数保存在wait的参数中,里面还有其他信息,需要通过宏分离有效值。

WIFEXITED:子进程注册终止,返回TRUE

WEXITSTATUS:返回子进程的返回值

调用wait函数时,如果没有已终止的子进程,那么程序blocking,直到有子进程终止,所以调用wait需谨慎。


6. 示例二:wait销毁子进程

#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <sys/wait.h>int main(int argc, char *argv[]){    int status;    pid_t pid;    pid = fork();    if(pid == 0){    return 3;    }else{printf("Child1 PID :%d \n",pid);   pid = fork();  if(pid == 0){    exit(7);}else {    printf("Child2 PID :%d \n",pid);    wait(&status);    if(WIFEXITED(status)){    printf("Child one : %d \n",WEXITSTATUS(status));    }    wait(&status);    if(WIFEXITED(status)){    printf("Child two : %d \n",WEXITSTATUS(status));    }    sleep(5);}    }    return 0;}
执行结果:

alex@alex-virtual-machine:/extra/tcpip/10$ gcc wait.calex@alex-virtual-machine:/extra/tcpip/10$ ./a.outChild1 PID :4243Child2 PID :4244Child one : 3Child two : 7alex@alex-virtual-machine:/extra/tcpip/10$ ps auUSER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMANDroot      1949  0.0  0.1   4740  1836 tty1     Ss+  10:02   0:00 /sbin/agetty --root      1951  0.2  2.3 173444 24320 tty7     Ss+  10:02   0:17 /usr/bin/X -coralex      2819  0.0  0.3   9596  4084 pts/1    Ss+  10:05   0:00 bashalex      2914  0.0  0.5   9732  5364 pts/4    Ss   10:06   0:01 -bashalex      4247  0.0  0.2   7000  2532 pts/4    R+   12:03   0:00 ps aualex@alex-virtual-machine:/extra/tcpip/10$

7. waitpid函数销毁僵死进程

#include <sys/wait.h>pid_t waitpid(pid_t pid, int * statloc, int options);成功时返回终止子进程ID,失败返回-1
pid:等待终止的目标子进程ID,若传递-1,则与wait函数相同,等待任意子进程
statloc:与wait函数的statloc参数一致
options:传递头文件sys/wait.h中声明的常量WNOHANG,即使没有终止子进程也不会阻塞,而是返回0并退出函数


8. 示例三,waitpid

#include <stdio.h>#include <unistd.h>#include <sys/wait.h>int main(int argc, char *argv[]){    int status;    pid_t pid;    pid = fork();    if(pid == 0){sleep(5);    return 24;    }else{while(!waitpid(-1,&status,WNOHANG)){    sleep(1);    puts("sleep 1sec.");}if(WIFEXITED(status)){    printf("child send %d \n",WEXITSTATUS(status));}    }    return 0;}
执行结果:

alex@alex-virtual-machine:/extra/tcpip/10$ gcc waitpid.calex@alex-virtual-machine:/extra/tcpip/10$ ./a.outsleep 1sec.sleep 1sec.sleep 1sec.sleep 1sec.sleep 1sec.child send 24alex@alex-virtual-machine:/extra/tcpip/10$

0 0
原创粉丝点击