您的位置:首页 > 运维架构 > Nginx

简化的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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: