您的位置:首页 > 理论基础 > 计算机网络

UNIX网络编程卷1 服务器程序设计范式2 预先派生子进程,每个子进程调用accept

2014-08-25 21:56 274 查看
本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie

1.预先派生子进程:在启动阶段预先派生一定数量的子进程,当各个客户连接到达时,

这些子进程立即就能为它们服务。

2.优点是无须引入你进程执行 fork 的开销就能处理新到的客户。

缺点是父进程必须在服务器启动阶段猜测需要预先派生多少子进程。

3.父进程可以持续监视闲置子进程数,一旦该值降至低于某个阈值就派生额外的子进程,

一旦超另一个阈值就终止一些过剩的子进程。

4.如果有多个进程阻塞在引用同一个实体的描述符上,那么最好直接阻塞在诸如 accept 之类的函数而不是 select 之中。

/* include serv02 */
#include	"unp.h"

static int		nchildren;
static pid_t	*pids;

int
main(int argc, char **argv)
{
int			listenfd, i;
socklen_t	addrlen;
void		sig_int(int);
pid_t		child_make(int, int, int);

//0.创建监听套接字
if (argc == 3)
listenfd = Tcp_listen(NULL, argv[1], &addrlen);
else if (argc == 4)
listenfd = Tcp_listen(argv[1], argv[2], &addrlen);
else
err_quit("usage: serv02 [ <host> ] <port#> <#children>");

//1.增设一个命令行参数供用户指定预先派生的子进程个数。
//分配一个存放各个子进程 ID 的数组,用于在父进程即将终止时由 main 函数终止所有子进程
nchildren = atoi(argv[argc-1]);
pids = Calloc(nchildren, sizeof(pid_t));

//2.调用 child_make 创建各个子进程
for (i = 0; i < nchildren; i++)
pids[i] = child_make(i, listenfd, addrlen);	/* parent returns */

//3.设置中断信号 SIGINT 的处理函数
Signal(SIGINT, sig_int);

//4.子进程负责处理所有事情。 --> ?? 为什么不直接 pause(),而要在 for 循环里 pause()
for ( ; ; )
pause();	/* everything done by children */
}
/* end serv02 */

// SIGINT 信号处理函数
/* include sigint */
void
sig_int(int signo)
{
int		i;
void	pr_cpu_time(void);

//给每个子进程发送 SIGTERM 信号终止它们
for (i = 0; i < nchildren; i++)
kill(pids[i], SIGTERM);
//用 wait 回收所有子进程的资源
while (wait(NULL) > 0)		/* wait for all children */
;
if (errno != ECHILD)
err_sys("wait error");

//调用 pr_cpu_time 统计已终止子进程的资源利用统计
pr_cpu_time();
exit(0);
}
/* end sigint */

/* include child_make */
pid_t
child_make(int i, int listenfd, int addrlen)
{
pid_t	pid;
void	child_main(int, int, int);

//调用 fork 派生子进程
if ( (pid = Fork()) > 0)
return(pid);		//父进程返回子进程的 pid 给 main 函数,回到 main 函数里的循环继续派生其它子进程

child_main(i, listenfd, addrlen);	/* 子进程调用 child_main 函数,它是无限循环 */
}
/* end child_make */
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐