简化的nginx多进程模型demo
2015-06-08 00:01
639 查看
//version1:以下代码仅演示nginx多进程模型 [test@vmc]$catmynginx.c #include<stdio.h> #include<string.h> #include<unistd.h> char**os_argv; char*os_argv_last; init_setproctitle(void) { char*p; size_tsize; inti; size=0; os_argv_last=os_argv[0]; for(i=0;os_argv[i];i++){ if(os_argv_last==os_argv[i]){ os_argv_last=os_argv[i]+strlen(os_argv[i])+1; } } os_argv_last+=strlen(os_argv_last); } voidsetproctitle(char*title) { char*p; os_argv[1]=NULL; p=strncpy((char*)os_argv[0],(char*)title, strlen(title)); p+=strlen(title); if(os_argv_last-(char*)p>0){ memset(p,'',os_argv_last-(char*)p); } } voidstart_woker_processes() { setproctitle("mynginx:workerprocess"); for(;;) { sleep(1); printf("workerpid=%d\n",getpid()); } } voidstart_dispatcher_process() { setproctitle("mynginx:dispatcherprocess"); for(;;) { sleep(1); printf("\tdispatcherpid=%d\n",getpid()); } } voidsave_argv(intargc,char*const*argv) { os_argv=(char**)argv; } intmain(intargc,char**argv) { intfd; inti; pid_tpid; save_argv(argc,argv); init_setproctitle(); printf("fatherpid1=%d\n",getpid()); for(i=0;i<3;i++) { pid=fork(); if(pid==0) { start_woker_processes(); } } pid=fork(); if(pid==0) { start_dispatcher_process(); } printf("fatherpid2=%d\n",getpid()); while(1) sleep(1); return0; }
makemynginx
./mynginx
ps-ef|grepmynginx即可看到
test2055320463023:54pts/000:00:00./mynginx
test2055420553023:54pts/000:00:00mynginx:workerprocess
test2055520553023:54pts/000:00:00mynginx:workerprocess
test2055620553023:54pts/000:00:00mynginx:workerprocess
test2055720553023:54pts/000:00:00mynginx:dispatcherprocess
root2057420560023:54pts/200:00:00grepmynginx
version2:
改进:支持父进程重启被异常中断的子进程。
一个master,一个dispatcher,三个worker
[root@vm-10-154-252-59nginx-1.7.10]#ps-ef|grepgetslice
liubin7263469020:00pts/400:00:00./getslice
liubin727726020:00pts/400:00:00getslice:workerprocess
liubin728726020:00pts/400:00:00getslice:workerprocess
liubin740726020:00pts/400:00:00getslice:dispatcherprocess
liubin745726020:00pts/400:00:00getslice:workerprocess
[root@vm-10-154-252-59nginx-1.7.10]#kill-9745
[root@vm-10-154-252-59nginx-1.7.10]#ps-ef|grepgetslice
liubin7263469020:00pts/400:00:00./getslice
liubin727726020:00pts/400:00:00getslice:workerprocess
liubin728726020:00pts/400:00:00getslice:workerprocess
liubin740726020:00pts/400:00:00getslice:dispatcherprocess
liubin2714726020:30pts/400:00:00getslice:workerprocess
//可以看到,杀掉745后,马上又起来新的2714进程
下面是代码,可以直接编译
#include<errno.h>
#include<signal.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/prctl.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
#defineDefaultConfigFile"/opt/project/getslice/conf/getslice_lunbo.conf"
#definePID_FILENAME"/var/run/getslice_lunbo.pid"
#defineVERSION"1.0.0"
#defineMAX_PROCESSES128
#definePROCESS_NORESPAWN-1
#definePROCESS_JUST_SPAWN-2
#definePROCESS_RESPAWN-3
#definePROCESS_JUST_RESPAWN-4
#definePROCESS_DETACHED-5
constchar*appname="getslice_lunbo";
char*ConfigFile=NULL;
typedefvoid(*spawn_proc_pt)(void*data);
typedefstruct{
pid_tpid;
intstatus;
//intchannel[2];
spawn_proc_ptproc;
void*data;
char*name;
unsignedrespawn:1;
unsignedjust_spawn:1;
unsigneddetached:1;
unsignedexiting:1;
unsignedexited:1;
}process_t;
process_tprocesses[MAX_PROCESSES];
intprocess_slot;
/*getoptargs*/
intopt_no_daemon=0;
intopt_debug_stderr=-1;
intopt_parse_cfg_only=0;
intopt_send_signal=-1;
sig_atomic_treap;
sig_atomic_tterminate;
sig_atomic_tquit;
intlast_process;
intexiting;
char**os_argv;
char*os_argv_last;
init_setproctitle(void)
{
char*p;
size_tsize;
inti;
size=0;
os_argv_last=os_argv[0];
for(i=0;os_argv[i];i++){
if(os_argv_last==os_argv[i]){
os_argv_last=os_argv[i]+strlen(os_argv[i])+1;
}
}
os_argv_last+=strlen(os_argv_last);
}
voidsetproctitle(char*title)
{
char*p;
os_argv[1]=NULL;
p=strncpy((char*)os_argv[0],(char*)title,
strlen(title));
p+=strlen(title);
if(os_argv_last-(char*)p>0){
memset(p,'',os_argv_last-(char*)p);
}
}
voidworker_process_init(intworker)
{
}
voidworker_process_exit(void)
{
}
void
worker_process_cycle(void*data)
{
intworker=(intptr_t)data;
worker_process_init(worker);
setproctitle("getslice:workerprocess");
for(;;){
if(exiting){
fprintf(stderr,"exiting");
worker_process_exit();
}
sleep(1);
fprintf(stderr,"\tworkercyclepid:%d\n",getpid());
if(terminate){
fprintf(stderr,"exiting");
worker_process_exit();
}
if(quit){
quit=0;
fprintf(stderr,"gracefullyshuttingdown");
setproctitle("workerprocessisshuttingdown");
if(!exiting){
exiting=1;
}
}
}
}
voiddispatcher_process_init(intworker)
{
}
voiddispatcher_process_exit()
{
}
void
dispatcher_process_cycle(void*data)
{
intworker=(intptr_t)data;
dispatcher_process_init(worker);
setproctitle("getslice:dispatcherprocess");
for(;;){
if(exiting){
fprintf(stderr,"exiting\n");
dispatcher_process_exit();
}
sleep(1);
fprintf(stderr,"\tdispatchercyclepid:%d\n",getpid());
if(terminate){
fprintf(stderr,"exiting\n");
dispatcher_process_exit();
}
if(quit){
quit=0;
fprintf(stderr,"gracefullyshuttingdown\n");
setproctitle("workerprocessisshuttingdown");
if(!exiting){
exiting=1;
}
}
}
}
void
start_worker_processes(intn,inttype)
{
inti;
fprintf(stderr,"startworkerprocesses\n");
for(i=0;i<n;i++){
spawn_process(worker_process_cycle,(void*)(intptr_t)i,"workerprocess",type);
}
}
voidstart_dispatcher_process(inttype)
{
fprintf(stderr,"startdispatcherprocesses\n");
spawn_process(dispatcher_process_cycle,(void*)(intptr_t)0,"dispatcherprocess",type);
}
voidsave_argv(intargc,char*const*argv)
{
os_argv=(char**)argv;
}
void
sig_child(intsig)
{
reap=1;
intstatus;
inti;
pid_tpid;
do{
pid=waitpid(-1,&status,WNOHANG);
for(i=0;i<last_process;i++){
if(processes[i].pid==pid){
processes[i].status=status;
processes[i].exited=1;
//process=processes[i].name;
break;
}
}
}while(pid>0);
signal(sig,sig_child);
}
typedefvoidSIGHDLR(intsig);
voidsignal_set(intsig,SIGHDLR*func,intflags)
{
structsigactionsa;
sa.sa_handler=func;
sa.sa_flags=flags;
sigemptyset(&sa.sa_mask);
if(sigaction(sig,&sa,NULL)<0)
fprintf(stderr,"sigaction:sig=%dfunc=%p:%s\n",sig,func,strerror(errno));
}
voidinit_signals(void)
{
signal_set(SIGCHLD,sig_child,SA_NODEFER|SA_RESTART);
}
staticpid_treadPidFile(void)
{
FILE*pid_fp=NULL;
constchar*f=PID_FILENAME;
pid_tpid=-1;
inti;
if(f==NULL){
fprintf(stderr,"%s:error:nopidfilenamedefined\n",appname);
exit(1);
}
pid_fp=fopen(f,"r");
if(pid_fp!=NULL){
pid=0;
if(fscanf(pid_fp,"%d",&i)==1)
pid=(pid_t)i;
fclose(pid_fp);
}else{
if(errno!=ENOENT){
fprintf(stderr,"%s:error:couldnotreadpidfile\n",appname);
fprintf(stderr,"\t%s:%s\n",f,strerror(errno));
exit(1);
}
}
returnpid;
}
intcheckRunningPid(void)
{
pid_tpid;
pid=readPidFile();
if(pid<2)
return0;
if(kill(pid,0)<0)
return0;
fprintf(stderr,"getslice_masterisalreadyrunning!processid%ld\n",(longint)pid);
return1;
}
voidwritePidFile(void)
{
FILE*fp;
constchar*f=PID_FILENAME;
fp=fopen(f,"w+");
if(!fp){
fprintf(stderr,"couldnotwritepidfile'%s':%s\n",f,strerror(errno));
return;
}
fprintf(fp,"%d\n",(int)getpid());
fclose(fp);
}
voidusage(void)
{
fprintf(stderr,
"Usage:%s[-?hvVN][-dlevel][-cconfig-file][-ksignal]\n"
"-hPrinthelpmessage.\n"
"-vShowVersionandexit.\n"
"-NNodaemonmode.\n"
"-cfileUsegivenconfig-fileinsteadof\n"
"%s\n"
"-kreload|rotate|kill|parse\n"
"killisfastshutdown\n"
"Parseconfigurationfile,thensendsignalto\n"
"runningcopy(except-kparse)andexit.\n",
appname,DefaultConfigFile);
exit(1);
}
staticvoidshow_version(void)
{
fprintf(stderr,"%sversion:%s\n",appname,VERSION);
exit(1);
}
voidmainParseOptions(intargc,char*argv[])
{
externchar*optarg;
intc;
while((c=getopt(argc,argv,"hvNc:k:?"))!=-1){
switch(c){
case'h':
usage();
break;
case'v':
show_version();
break;
case'N':
opt_no_daemon=1;
break;
case'c':
ConfigFile=strdup(optarg);
break;
case'k':
if((int)strlen(optarg)<1)
usage();
if(!strncmp(optarg,"reload",strlen(optarg)))
opt_send_signal=SIGHUP;
elseif(!strncmp(optarg,"rotate",strlen(optarg)))
opt_send_signal=SIGUSR1;
elseif(!strncmp(optarg,"shutdown",strlen(optarg)))
opt_send_signal=SIGTERM;
elseif(!strncmp(optarg,"kill",strlen(optarg)))
opt_send_signal=SIGKILL;
elseif(!strncmp(optarg,"parse",strlen(optarg)))
opt_parse_cfg_only=1;/*parsecfgfileonly*/
else
usage();
break;
case'?':
default:
usage();
break;
}
}
}
voidenableCoredumps(void)
{
/*SetLinuxDUMPABLEflag*/
if(prctl(PR_SET_DUMPABLE,1,0,0,0)!=0)
fprintf(stderr,"prctl:%s\n",strerror(errno));
/*Makesurecoredumpsarenotlimited*/
structrlimitrlim;
if(getrlimit(RLIMIT_CORE,&rlim)==0){
rlim.rlim_cur=rlim.rlim_max;
if(setrlimit(RLIMIT_CORE,&rlim)==0){
fprintf(stderr,"EnableCoreDumpsOK!\n");
return;
}
}
fprintf(stderr,"EnableCoreDumpfailed:%s\n",strerror(errno));
}
int
reap_children(void)
{
inti,n;
intlive;
live=0;
for(i=0;i<last_process;i++){
//child[0]26718e:0t:0d:0r:1j:0
fprintf(stderr,"child[%d]%de:%dt:%dd:%dr:%dj:%d\n",
i,
processes[i].pid,
processes[i].exiting,
processes[i].exited,
processes[i].detached,
processes[i].respawn,
processes[i].just_spawn);
if(processes[i].pid==-1){
continue;
}
if(processes[i].exited){
if(!processes[i].detached){
for(n=0;n<last_process;n++){
if(processes
.exited
||processes
.pid==-1)
{
continue;
}
fprintf(stderr,"detached:%d\n",processes
.pid);
}
}
if(processes[i].respawn
&&!processes[i].exiting
&&!terminate
&&!quit)
{
if(spawn_process(processes[i].proc,processes[i].data,processes[i].name,i)==-1)
{
fprintf(stderr,"couldnotrespawn%s\n",processes[i].name);
continue;
}
live=1;
continue;
}
if(i==last_process-1){
last_process--;
}else{
processes[i].pid=-1;
}
}elseif(processes[i].exiting||!processes[i].detached){
live=1;
}
}
returnlive;
}
pid_t
spawn_process(spawn_proc_ptproc,void*data,char*name,intrespawn)
{
longon;
pid_tpid;
ints;
if(respawn>=0){
s=respawn;
}else{
for(s=0;s<last_process;s++){
if(processes[s].pid==-1){
break;
}
}
if(s==MAX_PROCESSES){
fprintf(stderr,"nomorethan%dprocessescanbespawned",
MAX_PROCESSES);
return-1;
}
}
process_slot=s;
pid=fork();
switch(pid){
case-1:
fprintf(stderr,"fork()failedwhilespawning\"%s\":%s",name,errno);
return-1;
case0:
pid=getpid();
proc(data);
break;
default:
break;
}
fprintf(stderr,"start%s%d\n",name,pid);
processes[s].pid=pid;
processes[s].exited=0;
if(respawn>=0){
returnpid;
}
processes[s].proc=proc;
processes[s].data=data;
processes[s].name=name;
processes[s].exiting=0;
switch(respawn){
casePROCESS_NORESPAWN:
processes[s].respawn=0;
processes[s].just_spawn=0;
processes[s].detached=0;
break;
casePROCESS_JUST_SPAWN:
processes[s].respawn=0;
processes[s].just_spawn=1;
processes[s].detached=0;
break;
casePROCESS_RESPAWN:
processes[s].respawn=1;
processes[s].just_spawn=0;
processes[s].detached=0;
break;
casePROCESS_JUST_RESPAWN:
processes[s].respawn=1;
processes[s].just_spawn=1;
processes[s].detached=0;
break;
casePROCESS_DETACHED:
processes[s].respawn=0;
processes[s].just_spawn=0;
processes[s].detached=1;
break;
}
if(s==last_process){
last_process++;
}
returnpid;
}
intmain(intargc,char**argv)
{
intfd;
inti;
pid_tpid;
sigset_tset;
mainParseOptions(argc,argv);
if(-1==opt_send_signal)
if(checkRunningPid())
exit(1);
enableCoredumps();
writePidFile();
save_argv(argc,argv);
init_setproctitle();
init_signals();
sigemptyset(&set);
printf("fatherpid1=%d\n",getpid());
intworker_processes=3;
start_worker_processes(worker_processes,PROCESS_RESPAWN);
start_dispatcher_process(PROCESS_RESPAWN);
printf("fatherpid2=%d\n",getpid());
intlive=1;
for(;;){
printf("fatherbeforesuspend\n");
sigsuspend(&set);
printf("fatheraftersuspend\n");
if(reap){
reap=0;
fprintf(stderr,"reapchildren\n");
live=reap_children();
}
}
return0;
}
相关文章推荐
- nginx+keepalived实现双机热备高可用
- 在linux下配置nginx+java+php的环境
- 搭建Nginx+Java环境
- Apache与Nginx的区别
- Apache与Nginx的区分比较
- nginx 安装配置 for window
- Nginx整合PHP原理
- linux下nginx+php+mysql 自助环境搭建
- linux下nginx+php+mysql一键安装
- win7-64-nginx-mysql-php
- Nginx配置文件详细说明
- nginx开机自动启动(添加到服务)
- Nginx的proxy_redirect作用
- nginx配备中proxy_redirect的作用(转)
- nginx配置中proxy_redirect的作用(转)
- nginx rewrite重写规则配置详解
- Nginx 重写URI
- ubuntu 安装nginx
- 用Nginx+Lua实现高性能、高可靠、安全的登陆验证
- 应对小规模DDOS:使用nginx_lua打造PHP应用防火墙