本篇内容主要讲解“PostgreSQL中PostgresMain函数的实现逻辑是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“PostgreSQL中PostgresMain函数的实现逻辑是什么”吧!

一、源码解读

PostgresMain函数

/*----------------------------------------------------------------*PostgresMain*postgresmainloop--allbackends,interactiveorotherwisestarthere**argc/argvarethecommandlineargumentstobeused.(Whenbeingforked*bythepostmaster,thesearenottheoriginalargvarrayoftheprocess.)*dbnameisthenameofthedatabasetoconnectto,orNULLifthedatabase*nameshouldbeextractedfromthecommandlineargumentsordefaulted.*usernameisthePostgreSQLusernametobeusedforthesession.*----------------------------------------------------------------*//*输入:argc/argv-Main函数的输入参数dbname-数据库名称username-用户名输出:无*/voidPostgresMain(intargc,char*argv[],constchar*dbname,constchar*username){intfirstchar;//临时变量,读取输入的CommandStringInfoDatainput_message;//字符串增强结构体sigjmp_buflocal_sigjmp_buf;//系统变量volatileboolsend_ready_for_query=true;//booldisable_idle_in_transaction_timeout=false;/*Initializestartupprocessenvironmentifnecessary.*/if(!IsUnderPostmaster//未初始化?initializedforthebootstrap/standalonecaseInitStandaloneProcess(argv[0]);//初始化进程SetProcessingMode(InitProcessing);//设置进程状态为InitProcessing/**Setdefaultvaluesforcommand-lineoptions.*/if(!IsUnderPostmaster)InitializeGUCOptions();//初始化GUC参数,GUC=GrandUnifiedConfiguration/**Parsecommand-lineoptions.*/process_postgres_switches(argc,argv,PGC_POSTMASTER,&dbname);//解析输入参数/*Musthavegottenadatabasename,orhaveadefault(theusername)*/if(dbname==NULL)//输入的dbname为空{dbname=username;//设置为用户名if(dbname==NULL)//如仍为空,报错ereport(FATAL,(errcode(ERRCODE_INVALID_PARAMETER_VALUE),errmsg("%s:nodatabasenorusernamespecified",progname)));}/*Acquireconfigurationparameters,unlessinheritedfrompostmaster*/if(!IsUnderPostmaster){if(!SelectConfigFiles(userDoption,progname))//读取配置文件conf/hba文件&定位数据目录proc_exit(1);}/**Setupsignalhandlersandmasks.**Notethatpostmasterblockedallsignalsbeforeforkingchildprocess,*sothereisnoraceconditionwherebywemightreceiveasignalbefore*wehavesetupthehandler.**Alsonote:it'sbestnottouseanysignalsthatareSIG_IGNoredinthe*postmaster.Ifsuchasignalarrivesbeforeweareabletochangethe*handlertonon-SIG_IGN,it'llgetdropped.Instead,makeadummy*handlerinthepostmastertoreservethesignal.(Ofcourse,thisisn't*anissueforsignalsthatarelocallygenerated,suchasSIGALRMand*SIGPIPE.)*/if(am_walsender)//walsender进程?WalSndSignals();//如果是,则调用WalSndSignalselse//不是walsender进程{pqsignal(SIGHUP,PostgresSigHupHandler);/*setflagtoreadconfig*file*/pqsignal(SIGINT,StatementCancelHandler);/*cancelcurrentquery*/pqsignal(SIGTERM,die);/*cancelcurrentqueryandexit*//**Inastandalonebackend,SIGQUITcanbegeneratedfromthekeyboard*easily,whileSIGTERMcannot,sowemakebothsignalsdodie()*ratherthanquickdie().*/if(IsUnderPostmaster)pqsignal(SIGQUIT,quickdie);/*hardcrashtime*/elsepqsignal(SIGQUIT,die);/*cancelcurrentqueryandexit*/InitializeTimeouts();/*establishesSIGALRMhandler*//**Ignorefailuretowritetofrontend.Note:iffrontendcloses*connection,wewillnoticeitandexitcleanlywhencontrolnext*returnstoouterloop.Thisseemssaferthanforcingexitinthe*midstofoutputduringwho-knows-whatoperation...*/pqsignal(SIGPIPE,SIG_IGN);pqsignal(SIGUSR1,procsignal_sigusr1_handler);pqsignal(SIGUSR2,SIG_IGN);pqsignal(SIGFPE,FloatExceptionHandler);/**Resetsomesignalsthatareacceptedbypostmasterbutnotby*backend*/pqsignal(SIGCHLD,SIG_DFL);/*system()requiresthisonsome*platforms*/}pqinitmask();//InitializeBlockSig,UnBlockSig,andStartupBlockSig.if(IsUnderPostmaster){/*WeallowSIGQUIT(quickdie)atalltimes*/sigdelset(&BlockSig,SIGQUIT);}PG_SETMASK(&BlockSig);/*blockeverythingexceptSIGQUIT*/if(!IsUnderPostmaster){/**Validatewehavebeengivenareasonable-lookingDataDir(ifunder*postmaster,assumepostmasterdidthisalready).*/checkDataDir();//确认数据库路径OK,使用stat命令/*ChangeintoDataDir(ifunderpostmaster,wasdonealready)*/ChangeToDataDir();//切换至数据库路径,使用chdir命令/**Createlockfilefordatadirectory.*/CreateDataDirLockFile(false);//创建锁定文件,CreateLockFile(DIRECTORY_LOCK_FILE,amPostmaster,"",true,DataDir);/*readcontrolfile(errorcheckingandcontainsconfig)*/LocalProcessControlFile(false);//Readthecontrolfile,setrespectiveGUCs./*InitializeMaxBackends(ifunderpostmaster,wasdonealready)*/InitializeMaxBackends();//InitializeMaxBackendsvaluefromconfigoptions.}/*Earlyinitialization*/BaseInit();//基础的初始化/**Createaper-backendPGPROCstructinsharedmemory,exceptinthe*EXEC_BACKENDcasewherethiswasdoneinSubPostmasterMain.Wemustdo*thisbeforewecanuseLWLocks(andintheEXEC_BACKENDcasewealready*hadtodosomestuffwithLWLocks).*///initializeaper-processdatastructureforthisbackend#ifdefEXEC_BACKENDif(!IsUnderPostmaster)InitProcess();#elseInitProcess();#endif/*WeneedtoallowSIGINT,etcduringtheinitialtransaction*/PG_SETMASK(&UnBlockSig);/**Generalinitialization.**NOTE:ifyouaretemptedtoaddcodeinthisvicinity,considerputting*itinsideInitPostgres()instead.Inparticular,anythingthat*involvesdatabaseaccessshouldbethere,nothere.*/InitPostgres(dbname,InvalidOid,username,InvalidOid,NULL,false);//InitializePOSTGRES/**IfthePostmasterContextisstillaround,recyclethespace;wedon't*needitanymoreafterInitPostgrescompletes.Notethisdoesnottrash**MyProcPort,becauseConnCreate()allocatedthatspacewithmalloc()*...elsewe'dneedtocopythePortdatafirst.Also,subsidiarydata*suchastheusernameisn'tlosteither;seeProcessStartupPacket().*/if(PostmasterContext){MemoryContextDelete(PostmasterContext);PostmasterContext=NULL;}SetProcessingMode(NormalProcessing);//完成初始化后,设置进程模式为NormalProcessing/**NowallGUCstatesarefullysetup.Reportthemtoclientif*appropriate.*/BeginReportingGUCOptions();//ReportGUC/**Alsosetuphandlertologsessionend;wehavetowaittillnowtobe*sureLog_disconnectionshasitsfinalvalue.*/if(IsUnderPostmaster&&Log_disconnections)on_proc_exit(log_disconnections,0);//thisfunctionaddsacallbackfunctiontothelistoffunctionsinvokedbyproc_exit()/*PerforminitializationspecifictoaWALsenderprocess.*/if(am_walsender)InitWalSender();//初始化WALsenderprocess/**processanylibrariesthatshouldbepreloadedatbackendstart(this*likewisecan'tbedoneuntilGUCsettingsarecomplete)*/process_session_preload_libraries();//加载LIB/**Sendthisbackend'scancellationinfotothefrontend.*/if(whereToSendOutput==DestRemote){StringInfoDatabuf;pq_beginmessage(&buf,'K');pq_sendint32(&buf,(int32)MyProcPid);pq_sendint32(&buf,(int32)MyCancelKey);pq_endmessage(&buf);/*NeednotflushsinceReadyForQuerywilldoit.*/}/*Welcomebannerforstandalonecase*/if(whereToSendOutput==DestDebug)printf("\nPostgreSQLstand-alonebackend%s\n",PG_VERSION);/**Createthememorycontextwewilluseinthemainloop.**MessageContextisresetonceperiterationofthemainloop,ie,upon*completionofprocessingofeachcommandmessagefromtheclient.*///初始化内存上下文:MessageContextMessageContext=AllocSetContextCreate(TopMemoryContext,"MessageContext",ALLOCSET_DEFAULT_SIZES);/**CreatememorycontextandbufferusedforRowDescriptionmessages.As*SendRowDescriptionMessage(),viaexec_describe_statement_message(),is*frequentlyexecutedforeversinglestatement,wedon'twantto*allocateaseparatebuffereverytime.*///TODO传输RowDescriptionmessages?row_description_context=AllocSetContextCreate(TopMemoryContext,"RowDescriptionContext",ALLOCSET_DEFAULT_SIZES);MemoryContextSwitchTo(row_description_context);initStringInfo(&row_description_buf);MemoryContextSwitchTo(TopMemoryContext);/**Rememberstand-alonebackendstartuptime*/if(!IsUnderPostmaster)PgStartTime=GetCurrentTimestamp();//记录启动时间/**POSTGRESmainprocessingloopbeginshere**Ifanexceptionisencountered,processingresumesheresoweabortthe*currenttransactionandstartanewone.**Youmightwonderwhythisisn'tcodedasaninfinitelooparounda*PG_TRYconstruct.Thereasonisthatthisisthebottomofthe*exceptionstack,andsowithPG_TRYtherewouldbenoexceptionhandler*inforceatallduringtheCATCHpart.Byleavingtheoutermostsetjmp*alwaysactive,wehaveatleastsomechanceofrecoveringfromanerror*duringerrorrecovery.(Ifwegetintoaninfiniteloopthereby,it*willsoonbestoppedbyoverflowofelog.c'sinternalstatestack.)**Notethatweusesigsetjmp(...,1),sothatthisfunction'ssignalmask*(towit,UnBlockSig)willberestoredwhenlongjmp'ingtohere.This*isessentialincasewelongjmp'doutofasignalhandleronaplatform*wherethatleavesthesignalblocked.It'snotredundantwiththe*unblockinAbortTransaction()becausethelatterisonlycalledifwe*wereinsideatransaction.*/if(sigsetjmp(local_sigjmp_buf,1)!=0)//{/**NOTE:ifyouaretemptedtoaddmorecodeinthisif-block,*considerthehighprobabilitythatitshouldbein*AbortTransaction()instead.Theonlystuffdonedirectlyhere*shouldbestuffthatisguaranteedtoapply*only*forouter-level*errorrecovery,suchasadjustingtheFE/BEprotocolstatus.*//*SincenotusingPG_TRY,mustreseterrorstackbyhand*/error_context_stack=NULL;/*Preventinterruptswhilecleaningup*/HOLD_INTERRUPTS();/**ForgetanypendingQueryCancelrequest,sincewe'rereturningto*theidleloopanyway,andcancelanyactivetimeoutrequests.(In*futurewemightwanttoallowsometimeoutrequeststosurvive,but*atminimumit'dbenecessarytodoreschedule_timeouts(),incase*wegotherebecauseofaquerycancelinterruptingtheSIGALRM*interrupthandler.)Noteinparticularthatwemustclearthe*statementandlocktimeoutindicators,topreventanyfutureplain*querycancelsfrombeingmisreportedastimeoutsincasewe're*forgettingatimeoutcancel.*/disable_all_timeouts(false);QueryCancelPending=false;/*secondtoavoidracecondition*/stmt_timeout_active=false;/*Notreadingfromtheclientanymore.*/DoingCommandRead=false;/*Makesurelibpqisinagoodstate*/pq_comm_reset();/*Reporttheerrortotheclientand/orserverlog*/EmitErrorReport();/**Makesuredebug_query_stringgetsresetbeforewepossiblyclobber*thestorageitpointsat.*/debug_query_string=NULL;/**Abortthecurrenttransactioninordertorecover.*/AbortCurrentTransaction();if(am_walsender)WalSndErrorCleanup();PortalErrorCleanup();SPICleanup();/**Wecan'treleasereplicationslotsinsideAbortTransaction()aswe*needtobeabletostartandaborttransactionswhilehavingaslot*acquired.Butweneverneedtoholdthemacrosstoplevelerrors,*soreleasinghereisfine.There'sanothercleanupinProcKill()*ensuringwe'llcorrectlycleanuponFATALerrorsaswell.*/if(MyReplicationSlot!=NULL)ReplicationSlotRelease();/*Wealsowanttocleanuptemporaryslotsonerror.*/ReplicationSlotCleanup();jit_reset_after_error();/**Nowreturntonormaltop-levelcontextandclearErrorContextfor*nexttime.*/MemoryContextSwitchTo(TopMemoryContext);FlushErrorState();/**Ifwewerehandlinganextended-query-protocolmessage,initiate*skiptillnextSync.Thisalsocausesusnottoissue*ReadyForQuery(untilwegetSync).*/if(doing_extended_query_message)ignore_till_sync=true;/*Wedon'thaveatransactioncommandopenanymore*/xact_started=false;/**Ifanerroroccurredwhilewewerereadingamessagefromthe*client,wehavepotentiallylosttrackofwheretheprevious*messageendsandthenextonebegins.Eventhoughwehave*otherwiserecoveredfromtheerror,wecannotsafelyreadanymore*messagesfromtheclient,sothereisn'tmuchwecandowiththe*connectionanymore.*/if(pq_is_reading_msg())ereport(FATAL,(errcode(ERRCODE_PROTOCOL_VIOLATION),errmsg("terminatingconnectionbecauseprotocolsynchronizationwaslost")));/*Nowwecanallowinterruptsagain*/RESUME_INTERRUPTS();}/*Wecannowhandleereport(ERROR)*/PG_exception_stack=&local_sigjmp_buf;if(!ignore_till_sync)send_ready_for_query=true;/*initially,oraftererror*//**Non-errorqueriesloophere.*/for(;;)//主循环{/**Attopofloop,resetextended-query-messageflag,sothatany*errorsencounteredin"idle"statedon'tprovokeskip.*/doing_extended_query_message=false;/**Releasestorageleftoverfrompriorquerycycle,andcreateanew*queryinputbufferintheclearedMessageContext.*/MemoryContextSwitchTo(MessageContext);//切换至MessageContextMemoryContextResetAndDeleteChildren(MessageContext);initStringInfo(&input_message);//初始化输入的信息/**Alsoconsiderreleasingourcatalogsnapshotifany,sothatit's*notpreventingadvanceofglobalxminwhilewewaitfortheclient.*/InvalidateCatalogSnapshotConditionally();/**(1)Ifwe'vereachedidlestate,tellthefrontendwe'rereadyfor*anewquery.**Note:thisincludesfflush()'ingthelastoftheprioroutput.**Thisisalsoagoodtimetosendcollectedstatisticstothe*collector,andtoupdatethePSstatsdisplay.Weavoiddoing*thoseeverytimethroughthemessageloopbecauseit'dslowdown*processingofbatchedmessages,andbecausewedon'twanttoreport*uncommittedupdates(thatconfusesautovacuum).Thenotification*processorwantsacalltoo,ifwearenotinatransactionblock.*/if(send_ready_for_query)//Iamready!{if(IsAbortedTransactionBlockState()){set_ps_display("idleintransaction(aborted)",false);pgstat_report_activity(STATE_IDLEINTRANSACTION_ABORTED,NULL);/*Starttheidle-in-transactiontimer*/if(IdleInTransactionSessionTimeout>0){disable_idle_in_transaction_timeout=true;enable_timeout_after(IDLE_IN_TRANSACTION_SESSION_TIMEOUT,IdleInTransactionSessionTimeout);}}elseif(IsTransactionOrTransactionBlock()){set_ps_display("idleintransaction",false);pgstat_report_activity(STATE_IDLEINTRANSACTION,NULL);/*Starttheidle-in-transactiontimer*/if(IdleInTransactionSessionTimeout>0){disable_idle_in_transaction_timeout=true;enable_timeout_after(IDLE_IN_TRANSACTION_SESSION_TIMEOUT,IdleInTransactionSessionTimeout);}}else{ProcessCompletedNotifies();pgstat_report_stat(false);set_ps_display("idle",false);pgstat_report_activity(STATE_IDLE,NULL);}ReadyForQuery(whereToSendOutput);send_ready_for_query=false;}/**(2)Allowasynchronoussignalstobeexecutedimmediatelyifthey*comeinwhilewearewaitingforclientinput.(Thismustbe*conditionalsincewedon'twant,say,readsonbehalfofCOPYFROM*STDINdoingthesamething.)*/DoingCommandRead=true;/**(3)readacommand(loopblockshere)*/firstchar=ReadCommand(&input_message);//读取命令/**(4)disableasyncsignalconditionsagain.**Querycancelissupposedtobeano-opwhenthereisnoqueryin*progress,soifaquerycancelarrivedwhilewewereidle,just*resetQueryCancelPending.ProcessInterrupts()hasthateffectwhen*it'scalledwhenDoingCommandReadisset,socheckforinterrupts*beforeresettingDoingCommandRead.*/CHECK_FOR_INTERRUPTS();DoingCommandRead=false;/**(5)turnofftheidle-in-transactiontimeout*/if(disable_idle_in_transaction_timeout){disable_timeout(IDLE_IN_TRANSACTION_SESSION_TIMEOUT,false);disable_idle_in_transaction_timeout=false;}/**(6)checkforanyotherinterestingeventsthathappenedwhilewe*slept.*/if(ConfigReloadPending){ConfigReloadPending=false;ProcessConfigFile(PGC_SIGHUP);}/**(7)processthecommand.Butignoreitifwe'reskippingtill*Sync.*/if(ignore_till_sync&&firstchar!=EOF)continue;switch(firstchar){case'Q':/*simplequery*/{constchar*query_string;/*Setstatement_timestamp()*/SetCurrentStatementStartTimestamp();query_string=pq_getmsgstring(&input_message);//SQL语句pq_getmsgend(&input_message);if(am_walsender){if(!exec_replication_command(query_string))exec_simple_query(query_string);}elseexec_simple_query(query_string);//执行SQL语句send_ready_for_query=true;}break;case'P':/*parse*/{constchar*stmt_name;constchar*query_string;intnumParams;Oid*paramTypes=NULL;forbidden_in_wal_sender(firstchar);/*Setstatement_timestamp()*/SetCurrentStatementStartTimestamp();stmt_name=pq_getmsgstring(&input_message);query_string=pq_getmsgstring(&input_message);numParams=pq_getmsgint(&input_message,2);if(numParams>0){inti;paramTypes=(Oid*)palloc(numParams*sizeof(Oid));for(i=0;i<numParams;i++)paramTypes[i]=pq_getmsgint(&input_message,4);}pq_getmsgend(&input_message);exec_parse_message(query_string,stmt_name,paramTypes,numParams);}break;case'B':/*bind*/forbidden_in_wal_sender(firstchar);/*Setstatement_timestamp()*/SetCurrentStatementStartTimestamp();/**thismessageiscomplexenoughthatitseemsbesttoput*thefieldextractionout-of-line*/exec_bind_message(&input_message);break;case'E':/*execute*/{constchar*portal_name;intmax_rows;forbidden_in_wal_sender(firstchar);/*Setstatement_timestamp()*/SetCurrentStatementStartTimestamp();portal_name=pq_getmsgstring(&input_message);max_rows=pq_getmsgint(&input_message,4);pq_getmsgend(&input_message);exec_execute_message(portal_name,max_rows);}break;case'F':/*fastpathfunctioncall*/forbidden_in_wal_sender(firstchar);/*Setstatement_timestamp()*/SetCurrentStatementStartTimestamp();/*Reportquerytovariousmonitoringfacilities.*/pgstat_report_activity(STATE_FASTPATH,NULL);set_ps_display("<FASTPATH>",false);/*startanxactforthisfunctioninvocation*/start_xact_command();/**Note:wemayatthispointbeinsideanaborted*transaction.Wecan'tthrowerrorforthatuntilwe've*finishedreadingthefunction-callmessage,so*HandleFunctionRequest()mustcheckforitafterdoingso.*Becarefulnottodoanythingthatassumeswe'reinsidea*validtransactionhere.*//*switchbacktomessagecontext*/MemoryContextSwitchTo(MessageContext);HandleFunctionRequest(&input_message);/*committhefunction-invocationtransaction*/finish_xact_command();send_ready_for_query=true;break;case'C':/*close*/{intclose_type;constchar*close_target;forbidden_in_wal_sender(firstchar);close_type=pq_getmsgbyte(&input_message);close_target=pq_getmsgstring(&input_message);pq_getmsgend(&input_message);switch(close_type){case'S':if(close_target[0]!='\0')DropPreparedStatement(close_target,false);else{/*special-casetheunnamedstatement*/drop_unnamed_stmt();}break;case'P':{Portalportal;portal=GetPortalByName(close_target);if(PortalIsValid(portal))PortalDrop(portal,false);}break;default:ereport(ERROR,(errcode(ERRCODE_PROTOCOL_VIOLATION),errmsg("invalidCLOSEmessagesubtype%d",close_type)));break;}if(whereToSendOutput==DestRemote)pq_putemptymessage('3');/*CloseComplete*/}break;case'D':/*describe*/{intdescribe_type;constchar*describe_target;forbidden_in_wal_sender(firstchar);/*Setstatement_timestamp()(neededforxact)*/SetCurrentStatementStartTimestamp();describe_type=pq_getmsgbyte(&input_message);describe_target=pq_getmsgstring(&input_message);pq_getmsgend(&input_message);switch(describe_type){case'S':exec_describe_statement_message(describe_target);break;case'P':exec_describe_portal_message(describe_target);break;default:ereport(ERROR,(errcode(ERRCODE_PROTOCOL_VIOLATION),errmsg("invalidDESCRIBEmessagesubtype%d",describe_type)));break;}}break;case'H':/*flush*/pq_getmsgend(&input_message);if(whereToSendOutput==DestRemote)pq_flush();break;case'S':/*sync*/pq_getmsgend(&input_message);finish_xact_command();send_ready_for_query=true;break;/**'X'meansthatthefrontendisclosingdownthesocket.EOF*meansunexpectedlossoffrontendconnection.Eitherway,*performnormalshutdown.*/case'X':caseEOF:/**ResetwhereToSendOutputtopreventereportfromattempting*tosendanymoremessagestoclient.*/if(whereToSendOutput==DestRemote)whereToSendOutput=DestNone;/**NOTE:ifyouaretemptedtoaddmorecodehere,DON'T!*Whateveryouhadinmindtodoshouldbesetupasan*on_proc_exitoron_shmem_exitcallback,instead.Otherwise*itwillfailtobecalledduringotherbackend-shutdown*scenarios.*/proc_exit(0);case'd':/*copydata*/case'c':/*copydone*/case'f':/*copyfail*//**Acceptbutignorethesemessages,perprotocolspec;we*probablygotherebecauseaCOPYfailed,andthefrontend*isstillsendingdata.*/break;default:ereport(FATAL,(errcode(ERRCODE_PROTOCOL_VIOLATION),errmsg("invalidfrontendmessagetype%d",firstchar)));}}/*endofinput-readingloop*/}二、基础信息

PostgresMain函数使用的数据结构、宏定义以及依赖的函数等。
数据结构/宏定义
1、StringInfoData

/*-------------------------*StringInfoDataholdsinformationaboutanextensiblestring.*dataisthecurrentbufferforthestring(allocatedwithpalloc).*lenisthecurrentstringlength.Thereisguaranteedtobe*aterminating'\0'atdata[len],althoughthisisnotvery*usefulwhenthestringholdsbinarydataratherthantext.*maxlenistheallocatedsizeinbytesof'data',i.e.themaximum*stringsize(includingtheterminating'\0'char)thatwecan*currentlystorein'data'withouthavingtoreallocate*morespace.Wemustalwayshavemaxlen>len.*cursorisinitializedtozerobymakeStringInfoorinitStringInfo,*butisnototherwisetouchedbythestringinfo.croutines.*SomeroutinesuseittoscanthroughaStringInfo.*-------------------------*/typedefstructStringInfoData{char*data;intlen;intmaxlen;intcursor;}StringInfoData;typedefStringInfoData*StringInfo;

2、宏定义

#ifndefWIN32#definePG_SETMASK(mask)sigprocmask(SIG_SETMASK,mask,NULL)#else/*EmulatePOSIXsigset_tAPIsonWindows*/typedefintsigset_t;externintpqsigsetmask(intmask);#definePG_SETMASK(mask)pqsigsetmask(*(mask))#definesigemptyset(set)(*(set)=0)#definesigfillset(set)(*(set)=~0)#definesigaddset(set,signum)(*(set)|=(sigmask(signum)))#definesigdelset(set,signum)(*(set)&=~(sigmask(signum)))#endif/*WIN32*/

3、全局变量

/**IsPostmasterEnvironmentistrueinapostmasterprocessandanypostmaster*childprocess;itisfalseinastandaloneprocess(bootstrapor*standalonebackend).IsUnderPostmasteristrueinpostmasterchild*processes.Notethat"childprocess"includesallchildren,notonly*regularbackends.Theseshouldbesetcorrectlyasearlyaspossible*intheexecutionofaprocess,sothaterrorhandlingwilldotheright*thingsifanerrorshouldoccurduringprocessinitialization.**Theseareinitializedforthebootstrap/standalonecase.*/boolIsPostmasterEnvironment=false;boolIsUnderPostmaster=false;boolIsBinaryUpgrade=false;boolIsBackgroundWorker=false;boolam_walsender=false;/*AmIawalsenderprocess?*/

依赖的函数
1、InitStandaloneProcess

/**Initializethebasicenvironmentforastandaloneprocess.**argv0hastobesuitabletofindtheprogram'sexecutable.*/voidInitStandaloneProcess(constchar*argv0){Assert(!IsPostmasterEnvironment);MyProcPid=getpid();/*resetMyProcPid*/MyStartTime=time(NULL);/*setourstarttimeincasewecallelog*//*Initializeprocess-locallatchsupport*/InitializeLatchSupport();MyLatch=&LocalLatchData;InitLatch(MyLatch);/*Computepaths,nopostmastertoinheritfrom*/if(my_exec_path[0]=='\0'){if(find_my_exec(argv0,my_exec_path)<0)elog(FATAL,"%s:couldnotlocatemyownexecutablepath",argv0);}if(pkglib_path[0]=='\0')get_pkglib_path(my_exec_path,pkglib_path);}

2、InitializeGUCOptions

/**InitializeGUCoptionsduringprogramstartup.**Notethatwecannotreadtheconfigfileyet,sincewehavenotyet*processedcommand-lineswitches.*/voidInitializeGUCOptions(void){inti;/**Beforelog_line_prefixcouldpossiblyreceiveanonemptysetting,make*surethattimezoneprocessingisminimallyalive(seeelog.c).*/pg_timezone_initialize();/**BuildsortedarrayofallGUCvariables.*/build_guc_variables();/**Loadallvariableswiththeircompiled-indefaults,andinitialize*statusfieldsasneeded.*/for(i=0;i<num_guc_variables;i++){InitializeOneGUCOption(guc_variables[i]);}guc_dirty=false;reporting_enabled=false;/**Preventanyattempttooverridethetransactionmodesfrom*non-interactivesources.*/SetConfigOption("transaction_isolation","default",PGC_POSTMASTER,PGC_S_OVERRIDE);SetConfigOption("transaction_read_only","no",PGC_POSTMASTER,PGC_S_OVERRIDE);SetConfigOption("transaction_deferrable","no",PGC_POSTMASTER,PGC_S_OVERRIDE);/**Forhistoricalreasons,someGUCparameterscanreceivedefaultsfrom*environmentvariables.Processthosesettings.*/InitializeGUCOptionsFromEnvironment();}

3、process_postgres_switches

/*----------------------------------------------------------------*process_postgres_switches*ParsecommandlineargumentsforPostgresMain**Thisiscalledtwice,onceforthe"secure"optionscomingfromthe*postmasterorcommandline,andonceforthe"insecure"optionscoming*fromtheclient'sstartuppacket.Thelatterhavethesamesyntaxbut*mayberestrictedinwhattheycando.**argv[0]isignoredineithercase(it'sassumedtobetheprogramname).**ctxisPGC_POSTMASTERforsecureoptions,PGC_BACKENDforinsecureoptions*comingfromtheclient,orPGC_SU_BACKENDforinsecureoptionscomingfrom*asuperuserclient.**Ifadatabasenameispresentinthecommandlinearguments,it's*returnedinto*dbname(thisisallowedonlyif*dbnameisinitiallyNULL).*----------------------------------------------------------------*/voidprocess_postgres_switches(intargc,char*argv[],GucContextctx,constchar**dbname){boolsecure=(ctx==PGC_POSTMASTER);interrs=0;GucSourcegucsource;intflag;if(secure){gucsource=PGC_S_ARGV;/*switchescamefromcommandline*//*Ignoretheinitial--singleargument,ifpresent*/if(argc>1&&strcmp(argv[1],"--single")==0){argv++;argc--;}}else{gucsource=PGC_S_CLIENT;/*switchescamefromclient*/}#ifdefHAVE_INT_OPTERR/**Turnthisoffbecauseit'seitherprintedtostderrandnotthelog*wherewe'dwantit,orargv[0]isnow"--single",whichwouldmakefor*aweirderrormessage.Weprintourownerrormessagebelow.*/opterr=0;#endif/**Parsecommand-lineoptions.CAUTION:keepthisinsyncwith*postmaster/postmaster.c(theoptionsetsshouldnotconflict)andwith*thecommonhelp()functioninmain/main.c.*/while((flag=getopt(argc,argv,"B:bc:C:D:d:EeFf:h:ijk:lN:nOo:Pp:r:S:sTt:v:W:-:"))!=-1){switch(flag){case'B':SetConfigOption("shared_buffers",optarg,ctx,gucsource);break;case'b':/*Undocumentedflagusedforbinaryupgrades*/if(secure)IsBinaryUpgrade=true;break;case'C':/*ignoredforconsistencywiththepostmaster*/break;case'D':if(secure)userDoption=strdup(optarg);break;case'd':set_debug_options(atoi(optarg),ctx,gucsource);break;case'E':if(secure)EchoQuery=true;break;case'e':SetConfigOption("datestyle","euro",ctx,gucsource);break;case'F':SetConfigOption("fsync","false",ctx,gucsource);break;case'f':if(!set_plan_disabling_options(optarg,ctx,gucsource))errs++;break;case'h':SetConfigOption("listen_addresses",optarg,ctx,gucsource);break;case'i':SetConfigOption("listen_addresses","*",ctx,gucsource);break;case'j':if(secure)UseSemiNewlineNewline=true;break;case'k':SetConfigOption("unix_socket_directories",optarg,ctx,gucsource);break;case'l':SetConfigOption("ssl","true",ctx,gucsource);break;case'N':SetConfigOption("max_connections",optarg,ctx,gucsource);break;case'n':/*ignoredforconsistencywithpostmaster*/break;case'O':SetConfigOption("allow_system_table_mods","true",ctx,gucsource);break;case'o':errs++;break;case'P':SetConfigOption("ignore_system_indexes","true",ctx,gucsource);break;case'p':SetConfigOption("port",optarg,ctx,gucsource);break;case'r':/*sendoutput(stdoutandstderr)tothegivenfile*/if(secure)strlcpy(OutputFileName,optarg,MAXPGPATH);break;case'S':SetConfigOption("work_mem",optarg,ctx,gucsource);break;case's':SetConfigOption("log_statement_stats","true",ctx,gucsource);break;case'T':/*ignoredforconsistencywiththepostmaster*/break;case't':{constchar*tmp=get_stats_option_name(optarg);if(tmp)SetConfigOption(tmp,"true",ctx,gucsource);elseerrs++;break;}case'v':/**-visnolongerusedinnormaloperation,since*FrontendProtocolisalreadysetbeforewegethere.Wekeep*theswitchonlyforpossibleuseinstandaloneoperation,*incaseweeversupportusingnormalFE/BEprotocolwitha*standalonebackend.*/if(secure)FrontendProtocol=(ProtocolVersion)atoi(optarg);break;case'W':SetConfigOption("post_auth_delay",optarg,ctx,gucsource);break;case'c':case'-':{char*name,*value;ParseLongOption(optarg,&name,&value);if(!value){if(flag=='-')ereport(ERROR,(errcode(ERRCODE_SYNTAX_ERROR),errmsg("--%srequiresavalue",optarg)));elseereport(ERROR,(errcode(ERRCODE_SYNTAX_ERROR),errmsg("-c%srequiresavalue",optarg)));}SetConfigOption(name,value,ctx,gucsource);free(name);if(value)free(value);break;}default:errs++;break;}if(errs)break;}/**Optionaldatabasenameshouldbethereonlyif*dbnameisNULL.*/if(!errs&&dbname&&*dbname==NULL&&argc-optind>=1)*dbname=strdup(argv[optind++]);if(errs||argc!=optind){if(errs)optind--;/*complainaboutthepreviousargument*//*spelltheerrormessageabitdifferentlydependingoncontext*/if(IsUnderPostmaster)ereport(FATAL,(errcode(ERRCODE_SYNTAX_ERROR),errmsg("invalidcommand-lineargumentforserverprocess:%s",argv[optind]),errhint("Try\"%s--help\"formoreinformation.",progname)));elseereport(FATAL,(errcode(ERRCODE_SYNTAX_ERROR),errmsg("%s:invalidcommand-lineargument:%s",progname,argv[optind]),errhint("Try\"%s--help\"formoreinformation.",progname)));}/**Resetgetopt(3)librarysothatitwillworkcorrectlyinsubprocesses*orwhenthisfunctioniscalledasecondtimewithanotherarray.*/optind=1;#ifdefHAVE_INT_OPTRESEToptreset=1;/*somesystemsneedthistoo*/#endif}

4、SelectConfigFiles

/**Selecttheconfigurationfilesanddatadirectorytobeused,and*dotheinitialreadofpostgresql.conf.**Thisiscalledafterprocessingcommand-lineswitches.*userDoptionisthe-Dswitchvalueifany(NULLifunspecified).*prognameisjustforuseinerrormessages.**Returnstrueonsuccess;onfailure,printsasuitableerrormessage*tostderrandreturnsfalse.*/boolSelectConfigFiles(constchar*userDoption,constchar*progname){char*configdir;char*fname;structstatstat_buf;/*configdiris-Doption,or$PGDATAifno-D*/if(userDoption)configdir=make_absolute_path(userDoption);elseconfigdir=make_absolute_path(getenv("PGDATA"));if(configdir&&stat(configdir,&stat_buf)!=0){write_stderr("%s:couldnotaccessdirectory\"%s\":%s\n",progname,configdir,strerror(errno));if(errno==ENOENT)write_stderr("Runinitdborpg_basebackuptoinitializeaPostgreSQLdatadirectory.\n");returnfalse;}/**Findtheconfigurationfile:ifconfig_filewasspecifiedonthe*commandline,useit,elseuseconfigdir/postgresql.conf.Inanycase*ensuretheresultisanabsolutepath,sothatitwillbeinterpreted*thesamewaybyfuturebackends.*/if(ConfigFileName)fname=make_absolute_path(ConfigFileName);elseif(configdir){fname=guc_malloc(FATAL,strlen(configdir)+strlen(CONFIG_FILENAME)+2);sprintf(fname,"%s/%s",configdir,CONFIG_FILENAME);}else{write_stderr("%sdoesnotknowwheretofindtheserverconfigurationfile.\n""Youmustspecifythe--config-fileor-Dinvocation""optionorsetthePGDATAenvironmentvariable.\n",progname);returnfalse;}/**SettheConfigFileNameGUCvariabletoitsfinalvalue,ensuringthat*itcan'tbeoverriddenlater.*/SetConfigOption("config_file",fname,PGC_POSTMASTER,PGC_S_OVERRIDE);free(fname);/**Nowreadtheconfigfileforthefirsttime.*/if(stat(ConfigFileName,&stat_buf)!=0){write_stderr("%s:couldnotaccesstheserverconfigurationfile\"%s\":%s\n",progname,ConfigFileName,strerror(errno));free(configdir);returnfalse;}/**Readtheconfigurationfileforthefirsttime.Thistimeonlythe*data_directoryparameterispickeduptodeterminethedatadirectory,*sothatwecanreadthePG_AUTOCONF_FILENAMEfilenexttime.*/ProcessConfigFile(PGC_POSTMASTER);/**Ifthedata_directoryGUCvariablehasbeenset,usethatasDataDir;*otherwiseuseconfigdirifset;elsepunt.**Note:SetDataDirwillcopyandabsolute-izeitsargument,sowedon't*haveto.*/if(data_directory)SetDataDir(data_directory);elseif(configdir)SetDataDir(configdir);else{write_stderr("%sdoesnotknowwheretofindthedatabasesystemdata.\n""Thiscanbespecifiedas\"data_directory\"in\"%s\",""orbythe-Dinvocationoption,orbythe""PGDATAenvironmentvariable.\n",progname,ConfigFileName);returnfalse;}/**ReflectthefinalDataDirvaluebackintothedata_directoryGUCvar.*(Ifyouarewonderingwhywedon'tjustmakethemasinglevariable,*it'sbecausetheEXEC_BACKENDcaseneedsDataDirtobetransmittedto*childbackendsspecially.XXXisthatstilltrue?Giventhatwenow*chdirtoDataDir,EXEC_BACKENDcanreadtheconfigfilewithoutknowing*DataDirinadvance.)*/SetConfigOption("data_directory",DataDir,PGC_POSTMASTER,PGC_S_OVERRIDE);/**Nowreadtheconfigfileasecondtime,allowinganysettingsinthe*PG_AUTOCONF_FILENAMEfiletotakeeffect.(Thisisprettyugly,but*sincewehavetodeterminetheDataDirbeforewecanfindtheautoconf*file,thealternativesseemworse.)*/ProcessConfigFile(PGC_POSTMASTER);/**Iftimezone_abbreviationswasn'tsetintheconfigurationfile,install*thedefaultvalue.Wedoitthiswaybecausewecan'tsafelyinstalla*"real"valueuntilmy_exec_pathisset,whichmaynothavehappened*whenInitializeGUCOptionsruns,sothebootstrapdefaultvaluecannot*betherealdesireddefault.*/pg_timezone_abbrev_initialize();/**Figureoutwherepg_hba.confis,andmakesurethepathisabsolute.*/if(HbaFileName)fname=make_absolute_path(HbaFileName);elseif(configdir){fname=guc_malloc(FATAL,strlen(configdir)+strlen(HBA_FILENAME)+2);sprintf(fname,"%s/%s",configdir,HBA_FILENAME);}else{write_stderr("%sdoesnotknowwheretofindthe\"hba\"configurationfile.\n""Thiscanbespecifiedas\"hba_file\"in\"%s\",""orbythe-Dinvocationoption,orbythe""PGDATAenvironmentvariable.\n",progname,ConfigFileName);returnfalse;}SetConfigOption("hba_file",fname,PGC_POSTMASTER,PGC_S_OVERRIDE);free(fname);/**Likewiseforpg_ident.conf.*/if(IdentFileName)fname=make_absolute_path(IdentFileName);elseif(configdir){fname=guc_malloc(FATAL,strlen(configdir)+strlen(IDENT_FILENAME)+2);sprintf(fname,"%s/%s",configdir,IDENT_FILENAME);}else{write_stderr("%sdoesnotknowwheretofindthe\"ident\"configurationfile.\n""Thiscanbespecifiedas\"ident_file\"in\"%s\",""orbythe-Dinvocationoption,orbythe""PGDATAenvironmentvariable.\n",progname,ConfigFileName);returnfalse;}SetConfigOption("ident_file",fname,PGC_POSTMASTER,PGC_S_OVERRIDE);free(fname);free(configdir);returntrue;}

5、pqinitmask

/**InitializeBlockSig,UnBlockSig,andStartupBlockSig.**BlockSigisthesetofsignalstoblockwhenwearetryingtoblock*signals.Thisincludesallsignalswenormallyexpecttoget,butNOT*signalsthatshouldneverbeturnedoff.**StartupBlockSigisthesetofsignalstoblockduringstartuppacket*collection;it'sessentiallyBlockSigminusSIGTERM,SIGQUIT,SIGALRM.**UnBlockSigisthesetofsignalstoblockwhenwedon'twanttoblock*signals(isthisevernonzero??)*/voidpqinitmask(void){sigemptyset(&UnBlockSig);/*Firstsetallsignals,thenclearsome.*/sigfillset(&BlockSig);sigfillset(&StartupBlockSig);/**Unmarkthosesignalsthatshouldneverbeblocked.Someofthesesignal*namesdon'texistonallplatforms.Mostdo,butmightaswellifdef*themallforconsistency...*/#ifdefSIGTRAPsigdelset(&BlockSig,SIGTRAP);sigdelset(&StartupBlockSig,SIGTRAP);#endif#ifdefSIGABRTsigdelset(&BlockSig,SIGABRT);sigdelset(&StartupBlockSig,SIGABRT);#endif#ifdefSIGILLsigdelset(&BlockSig,SIGILL);sigdelset(&StartupBlockSig,SIGILL);#endif#ifdefSIGFPEsigdelset(&BlockSig,SIGFPE);sigdelset(&StartupBlockSig,SIGFPE);#endif#ifdefSIGSEGVsigdelset(&BlockSig,SIGSEGV);sigdelset(&StartupBlockSig,SIGSEGV);#endif#ifdefSIGBUSsigdelset(&BlockSig,SIGBUS);sigdelset(&StartupBlockSig,SIGBUS);#endif#ifdefSIGSYSsigdelset(&BlockSig,SIGSYS);sigdelset(&StartupBlockSig,SIGSYS);#endif#ifdefSIGCONTsigdelset(&BlockSig,SIGCONT);sigdelset(&StartupBlockSig,SIGCONT);#endif/*Signalsuniquetostartup*/#ifdefSIGQUITsigdelset(&StartupBlockSig,SIGQUIT);#endif#ifdefSIGTERMsigdelset(&StartupBlockSig,SIGTERM);#endif#ifdefSIGALRMsigdelset(&StartupBlockSig,SIGALRM);#endif}

6、BaseInit

/**Earlyinitializationofabackend(eitherstandaloneorunderpostmaster).*ThishappensevenbeforeInitPostgres.**ThisisseparatefromInitPostgresbecauseitisalsocalledbyauxiliary*processes,suchasthebackgroundwriterprocess,whichmaynotcall*InitPostgresatall.*/voidBaseInit(void){/**Attachtosharedmemoryandsemaphores,andinitializeour*input/output/debuggingfiledescriptors.*/InitCommunication();DebugFileOpen();/*Dolocalinitializationoffile,storageandbuffermanagers*/InitFileAccess();smgrinit();InitBufferPoolAccess();}

7、InitProcess

/**InitProcess--initializeaper-processdatastructureforthisbackend*/voidInitProcess(void){PGPROC*volatile*procgloballist;/**ProcGlobalshouldbesetupalready(ifweareabackend,weinherit*thisbyfork()orEXEC_BACKENDmechanismfromthepostmaster).*/if(ProcGlobal==NULL)elog(PANIC,"procheaderuninitialized");if(MyProc!=NULL)elog(ERROR,"youalreadyexist");/*DecidewhichlistshouldsupplyourPGPROC.*/if(IsAnyAutoVacuumProcess())procgloballist=&ProcGlobal->autovacFreeProcs;elseif(IsBackgroundWorker)procgloballist=&ProcGlobal->bgworkerFreeProcs;elseprocgloballist=&ProcGlobal->freeProcs;/**Trytogetaprocstructfromtheappropriatefreelist.Ifthis*fails,wemustbeoutofPGPROCstructures(nottomentionsemaphores).**WhileweareholdingtheProcStructLock,alsocopythecurrentshared*estimateofspins_per_delaytolocalstorage.*/SpinLockAcquire(ProcStructLock);set_spins_per_delay(ProcGlobal->spins_per_delay);MyProc=*procgloballist;if(MyProc!=NULL){*procgloballist=(PGPROC*)MyProc->links.next;SpinLockRelease(ProcStructLock);}else{/**Ifwereachhere,allthePGPROCsareinuse.Thisisoneofthe*possibleplacestodetect"toomanybackends",sogivethestandard*errormessage.XXXdoweneedtogiveadifferentfailuremessage*intheautovacuumcase?*/SpinLockRelease(ProcStructLock);ereport(FATAL,(errcode(ERRCODE_TOO_MANY_CONNECTIONS),errmsg("sorry,toomanyclientsalready")));}MyPgXact=&ProcGlobal->allPgXact[MyProc->pgprocno];/**Cross-checkthatthePGPROCisofthetypeweexpect;ifthiswerenot*thecase,itwouldgetreturnedtothewronglist.*/Assert(MyProc->procgloballist==procgloballist);/**NowthatwehaveaPGPROC,markourselvesasanactivepostmaster*child;thisissothatthepostmastercandetectitifweexitwithout*cleaningup.(XXXautovaclaunchercurrentlydoesn'tparticipatein*this;itprobablyshould.)*/if(IsUnderPostmaster&&!IsAutoVacuumLauncherProcess())MarkPostmasterChildActive();/**InitializeallfieldsofMyProc,exceptforthosepreviously*initializedbyInitProcGlobal.*/SHMQueueElemInit(&(MyProc->links));MyProc->waitStatus=STATUS_OK;MyProc->lxid=InvalidLocalTransactionId;MyProc->fpVXIDLock=false;MyProc->fpLocalTransactionId=InvalidLocalTransactionId;MyPgXact->xid=InvalidTransactionId;MyPgXact->xmin=InvalidTransactionId;MyProc->pid=MyProcPid;/*backendId,databaseIdandroleIdwillbefilledinlater*/MyProc->backendId=InvalidBackendId;MyProc->databaseId=InvalidOid;MyProc->roleId=InvalidOid;MyProc->isBackgroundWorker=IsBackgroundWorker;MyPgXact->delayChkpt=false;MyPgXact->vacuumFlags=0;/*NB--autovaclauncherintentionallydoesnotsetIS_AUTOVACUUM*/if(IsAutoVacuumWorkerProcess())MyPgXact->vacuumFlags|=PROC_IS_AUTOVACUUM;MyProc->lwWaiting=false;MyProc->lwWaitMode=0;MyProc->waitLock=NULL;MyProc->waitProcLock=NULL;#ifdefUSE_ASSERT_CHECKING{inti;/*Lastprocessshouldhavereleasedalllocks.*/for(i=0;i<NUM_LOCK_PARTITIONS;i++)Assert(SHMQueueEmpty(&(MyProc->myProcLocks[i])));}#endifMyProc->recoveryConflictPending=false;/*Initializefieldsforsyncrep*/MyProc->waitLSN=0;MyProc->syncRepState=SYNC_REP_NOT_WAITING;SHMQueueElemInit(&(MyProc->syncRepLinks));/*InitializefieldsforgroupXIDclearing.*/MyProc->procArrayGroupMember=false;MyProc->procArrayGroupMemberXid=InvalidTransactionId;pg_atomic_init_u32(&MyProc->procArrayGroupNext,INVALID_PGPROCNO);/*Checkthatgrouplockingfieldsareinaproperinitialstate.*/Assert(MyProc->lockGroupLeader==NULL);Assert(dlist_is_empty(&MyProc->lockGroupMembers));/*Initializewaiteventinformation.*/MyProc->wait_event_info=0;/*Initializefieldsforgrouptransactionstatusupdate.*/MyProc->clogGroupMember=false;MyProc->clogGroupMemberXid=InvalidTransactionId;MyProc->clogGroupMemberXidStatus=TRANSACTION_STATUS_IN_PROGRESS;MyProc->clogGroupMemberPage=-1;MyProc->clogGroupMemberLsn=InvalidXLogRecPtr;pg_atomic_init_u32(&MyProc->clogGroupNext,INVALID_PGPROCNO);/**AcquireownershipofthePGPROC'slatch,sothatwecanuseWaitLatch*onit.Thatallowsustorepointtheprocesslatch,whichsofar*pointstoprocesslocalone,tothesharedone.*/OwnLatch(&MyProc->procLatch);SwitchToSharedLatch();/**Wemightbereusingasemaphorethatbelongedtoafailedprocess.So*becarefulandreinitializeitsvaluehere.(Thisisnotstrictly*necessaryanymore,butseemslikeagoodideaforcleanliness.)*/PGSemaphoreReset(MyProc->sem);/**Arrangetocleanupatbackendexit.*/on_shmem_exit(ProcKill,0);/**NowthatwehaveaPGPROC,wecouldtrytoacquirelocks,soinitialize*localstateneededforLWLocks,andthedeadlockchecker.*/InitLWLockAccess();InitDeadLockChecking();}

8、InitPostgres

/*--------------------------------*InitPostgres*InitializePOSTGRES.**Thedatabasecanbespecifiedbyname,usingthein_dbnameparameter,orby*OID,usingthedboidparameter.Inthelattercase,theactualdatabase*namecanbereturnedtothecallerinout_dbname.Ifout_dbnameisn't*NULL,itmustpointtoabufferofsizeNAMEDATALEN.**Similarly,theusernamecanbepassedbyname,usingtheusernameparameter,*orbyOIDusingtheuseroidparameter.**Inbootstrapmodenoparametersareused.Theautovacuumlauncherprocess*doesn'tuseanyparameterseither,becauseitonlygoesfarenoughtobe*abletoreadpg_database;itdoesn'tconnecttoanyparticulardatabase.*Inwalsendermodeonlyusernameisused.**AsofPostgreSQL8.2,weexpectInitProcess()wasalreadycalled,sowe*alreadyhaveaPGPROCstruct...butit'snotcompletelyfilledinyet.**Note:*BeverycarefulwiththeorderofcallsintheInitPostgresfunction.*--------------------------------*/voidInitPostgres(constchar*in_dbname,Oiddboid,constchar*username,Oiduseroid,char*out_dbname,booloverride_allow_connections){boolbootstrap=IsBootstrapProcessingMode();boolam_superuser;char*fullpath;chardbname[NAMEDATALEN];elog(DEBUG3,"InitPostgres");/**AddmyPGPROCstructtotheProcArray.**OnceIhavedonethis,Iamvisibletootherbackends!*/InitProcessPhase2();/**Initializemyentryintheshared-invalidationmanager'sarrayof*per-backenddata.**SetsupMyBackendId,auniquebackendidentifier.*/MyBackendId=InvalidBackendId;SharedInvalBackendInit(false);if(MyBackendId>MaxBackends||MyBackendId<=0)elog(FATAL,"badbackendID:%d",MyBackendId);/*NowthatwehaveaBackendId,wecanparticipateinProcSignal*/ProcSignalInit(MyBackendId);/**Alsosetuptimeouthandlersneededforbackendoperation.Weneed*theseineverycaseexceptbootstrap.*/if(!bootstrap){RegisterTimeout(DEADLOCK_TIMEOUT,CheckDeadLockAlert);RegisterTimeout(STATEMENT_TIMEOUT,StatementTimeoutHandler);RegisterTimeout(LOCK_TIMEOUT,LockTimeoutHandler);RegisterTimeout(IDLE_IN_TRANSACTION_SESSION_TIMEOUT,IdleInTransactionSessionTimeoutHandler);}/**bufmgrneedsanotherinitializationcalltoo*/InitBufferPoolBackend();/**Initializelocalprocess'saccesstoXLOG.*/if(IsUnderPostmaster){/**ThepostmasteralreadystartedtheXLOGmachinery,butweneedto*callInitXLOGAccess(),ifthesystemisn'tinhot-standbymode.*ThisishandledbycallingRecoveryInProgressandignoringthe*result.*/(void)RecoveryInProgress();}else{/**Weareeitherabootstrapprocessorastandalonebackend.Either*way,startuptheXLOGmachinery,andregistertohaveitclosed*downatexit.**Wedon'tyethaveanaux-processresourceowner,butStartupXLOG*andShutdownXLOGwillneedone.Hence,createsaidresourceowner*(andregisteracallbacktocleanitupafterShutdownXLOGruns).*/CreateAuxProcessResourceOwner();StartupXLOG();/*Release(andwarnabout)anybufferpinsleakedinStartupXLOG*/ReleaseAuxProcessResources(true);/*ResetCurrentResourceOwnertonothingforthemoment*/CurrentResourceOwner=NULL;on_shmem_exit(ShutdownXLOG,0);}/**Initializetherelationcacheandthesystemcatalogcaches.Notethat*nocatalogaccesshappenshere;weonlysetupthehashtablestructure.*Wemustdothisbeforestartingatransactionbecausetransactionabort*wouldtrytotouchthesehashtables.*/RelationCacheInitialize();InitCatalogCache();InitPlanCache();/*Initializeportalmanager*/EnablePortalManager();/*Initializestatscollection---musthappenbeforefirstxact*/if(!bootstrap)pgstat_initialize();/**Loadrelcacheentriesforthesharedsystemcatalogs.Thismustcreate*atleastentriesforpg_databaseandcatalogsusedforauthentication.*/RelationCacheInitializePhase2();/**Setupprocess-exitcallbacktodopre-shutdowncleanup.Thisisthe*firstbefore_shmem_exitcallbackweregister;thus,thiswillbethe*lastthingwedobeforelow-levelmoduleslikethebuffermanagerbegin*toclosedown.Weneedtohavethisinplacebeforewebeginourfirst*transaction---ifwefailduringtheinitializationtransaction,asis*entirelypossible,weneedtheAbortTransactioncalltocleanup.*/before_shmem_exit(ShutdownPostgres,0);/*Theautovacuumlauncherisdonehere*/if(IsAutoVacuumLauncherProcess()){/*reportthisbackendinthePgBackendStatusarray*/pgstat_bestart();return;}/**Startanewtransactionherebeforefirstaccesstodb,andgeta*snapshot.Wedon'thaveauseforthesnapshotitself,butwe're*interestedinthesecondaryeffectthatitsetsRecentGlobalXmin.(This*iscriticalforanythingthatreadsheappages,becauseHOTmaydecide*toprunethemeveniftheprocessdoesn'tattempttomodifyany*tuples.)*/if(!bootstrap){/*statement_timestampmustbesetfortimeoutstoworkcorrectly*/SetCurrentStatementStartTimestamp();StartTransactionCommand();/**transaction_isolationwillhavebeensettothedefaultbythe*above.Ifthedefaultis"serializable",andweareinhot*standby,wewillfailifwedon'tchangeittosomethinglower.*Fortunately,"readcommitted"isplentygoodenough.*/XactIsoLevel=XACT_READ_COMMITTED;(void)GetTransactionSnapshot();}/**Performclientauthenticationifnecessary,thenfigureoutour*postgresuserID,andseeifweareasuperuser.**Instandalonemodeandinautovacuumworkerprocesses,weuseafixed*ID,otherwisewefigureitoutfromtheauthenticatedusername.*/if(bootstrap||IsAutoVacuumWorkerProcess()){InitializeSessionUserIdStandalone();am_superuser=true;}elseif(!IsUnderPostmaster){InitializeSessionUserIdStandalone();am_superuser=true;if(!ThereIsAtLeastOneRole())ereport(WARNING,(errcode(ERRCODE_UNDEFINED_OBJECT),errmsg("norolesaredefinedinthisdatabasesystem"),errhint("YoushouldimmediatelyrunCREATEUSER\"%s\"SUPERUSER;.",username!=NULL?username:"postgres")));}elseif(IsBackgroundWorker){if(username==NULL&&!OidIsValid(useroid)){InitializeSessionUserIdStandalone();am_superuser=true;}else{InitializeSessionUserId(username,useroid);am_superuser=superuser();}}else{/*normalmultiusercase*/Assert(MyProcPort!=NULL);PerformAuthentication(MyProcPort);InitializeSessionUserId(username,useroid);am_superuser=superuser();}/**Ifwe'retryingtoshutdown,onlysuperuserscanconnect,andnew*replicationconnectionsarenotallowed.*/if((!am_superuser||am_walsender)&&MyProcPort!=NULL&&MyProcPort->canAcceptConnections==CAC_WAITBACKUP){if(am_walsender)ereport(FATAL,(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),errmsg("newreplicationconnectionsarenotallowedduringdatabaseshutdown")));elseereport(FATAL,(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),errmsg("mustbesuperusertoconnectduringdatabaseshutdown")));}/**Binaryupgradesonlyallowedsuper-userconnections*/if(IsBinaryUpgrade&&!am_superuser){ereport(FATAL,(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),errmsg("mustbesuperusertoconnectinbinaryupgrademode")));}/**Thelastfewconnectionslotsarereservedforsuperusers.Although*replicationconnectionscurrentlyrequiresuperuserprivileges,we*don'tallowthemtoconsumethereservedslots,whichareintendedfor*interactiveuse.*/if((!am_superuser||am_walsender)&&ReservedBackends>0&&!HaveNFreeProcs(ReservedBackends))ereport(FATAL,(errcode(ERRCODE_TOO_MANY_CONNECTIONS),errmsg("remainingconnectionslotsarereservedfornon-replicationsuperuserconnections")));/*Checkreplicationpermissionsneededforwalsenderprocesses.*/if(am_walsender){Assert(!bootstrap);if(!superuser()&&!has_rolreplication(GetUserId()))ereport(FATAL,(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),errmsg("mustbesuperuserorreplicationroletostartwalsender")));}/**Ifthisisaplainwalsenderonlysupportingphysicalreplication,we*don'twanttoconnecttoanyparticulardatabase.Justfinishthe*backendstartupbyprocessinganyoptionsfromthestartuppacket,and*we'redone.*/if(am_walsender&&!am_db_walsender){/*processanyoptionspassedinthestartuppacket*/if(MyProcPort!=NULL)process_startup_options(MyProcPort,am_superuser);/*ApplyPostAuthDelayassoonaswe'vereadalloptions*/if(PostAuthDelay>0)pg_usleep(PostAuthDelay*1000000L);/*initializeclientencoding*/InitializeClientEncoding();/*reportthisbackendinthePgBackendStatusarray*/pgstat_bestart();/*closethetransactionwestartedabove*/CommitTransactionCommand();return;}/**Setuptheglobalvariablesholdingdatabaseidanddefaulttablespace.*Butnotewewon'tactuallytrytotouchthedatabasejustyet.**Wetakeashortcutinthebootstrapcase,otherwisewehavetolookup*thedb'sentryinpg_database.*/if(bootstrap){MyDatabaseId=TemplateDbOid;MyDatabaseTableSpace=DEFAULTTABLESPACE_OID;}elseif(in_dbname!=NULL){HeapTupletuple;Form_pg_databasedbform;tuple=GetDatabaseTuple(in_dbname);if(!HeapTupleIsValid(tuple))ereport(FATAL,(errcode(ERRCODE_UNDEFINED_DATABASE),errmsg("database\"%s\"doesnotexist",in_dbname)));dbform=(Form_pg_database)GETSTRUCT(tuple);MyDatabaseId=HeapTupleGetOid(tuple);MyDatabaseTableSpace=dbform->dattablespace;/*takedatabasenamefromthecaller,justforparanoia*/strlcpy(dbname,in_dbname,sizeof(dbname));}elseif(OidIsValid(dboid)){/*callerspecifieddatabasebyOID*/HeapTupletuple;Form_pg_databasedbform;tuple=GetDatabaseTupleByOid(dboid);if(!HeapTupleIsValid(tuple))ereport(FATAL,(errcode(ERRCODE_UNDEFINED_DATABASE),errmsg("database%udoesnotexist",dboid)));dbform=(Form_pg_database)GETSTRUCT(tuple);MyDatabaseId=HeapTupleGetOid(tuple);MyDatabaseTableSpace=dbform->dattablespace;Assert(MyDatabaseId==dboid);strlcpy(dbname,NameStr(dbform->datname),sizeof(dbname));/*passthedatabasenamebacktothecaller*/if(out_dbname)strcpy(out_dbname,dbname);}else{/**Ifthisisabackgroundworkernotboundtoanyparticular*database,we'redonenow.Everythingthatfollowsonlymakessense*ifweareboundtoaspecificdatabase.Wedoneedtoclosethe*transactionwestartedbeforereturning.*/if(!bootstrap){pgstat_bestart();CommitTransactionCommand();}return;}/**Now,takeawriter'slockonthedatabasewearetryingtoconnectto.*IfthereisaconcurrentlyrunningDROPDATABASEonthatdatabase,this*willblockusuntilitfinishes(andhascommitteditsupdateof*pg_database).**Notethatthelockisnotheldlong,onlyuntiltheendofthisstartup*transaction.ThisisOKsincewewilladvertiseouruseofthe*databaseintheProcArraybeforedroppingthelock(infact,that'sthe*nextthingtodo).AnyonetryingaDROPDATABASEafterthispointwill*seeusinthearrayoncetheyhavethelock.Orderingisimportantfor*thisbecausewedon'twanttoadvertiseourselvesasbeinginthis*databaseuntilwehavethelock;otherwisewecreatewhatamountstoa*deadlockwithCountOtherDBBackends().**Note:useofRowExclusiveLockhereisreasonablebecauseweenvision*oursessionasbeingaconcurrentwriterofthedatabase.Ifwehada*wayofdeclaringasessionasbeingguaranteed-read-only,wecoulduse*AccessShareLockforsuchsessionsandtherebynotconflictagainst*CREATEDATABASE.*/if(!bootstrap)LockSharedObject(DatabaseRelationId,MyDatabaseId,0,RowExclusiveLock);/**NowwecanmarkourPGPROCentrywiththedatabaseID.**Weassumethisisanatomicstoresonolockisneeded;thoughactually*thingswouldworkfineevenifitweren'tatomic.Anyonesearchingthe*ProcArrayforthisdatabase'sIDshouldholdthedatabaselock,sothey*wouldnotbeexecutingconcurrentlywiththisstore.Aprocesslooking*foranotherdatabase'sIDcouldintheoryseeachancematchifitread*apartially-updateddatabaseIdvalue;butaslongasallsuchsearches*waitandretry,asinCountOtherDBBackends(),theywillcertainlysee*thecorrectvalueontheirnexttry.*/MyProc->databaseId=MyDatabaseId;/**Weestablishedacatalogsnapshotwhilereadingpg_authidand/or*pg_database;butuntilwehavesetupMyDatabaseId,wewon'treactto*incomingsinvalmessagesforunsharedcatalogs,sowewon'trealizeit*ifthesnapshothasbeeninvalidated.Assumeit'snogoodanymore.*/InvalidateCatalogSnapshot();/**Recheckpg_databasetomakesurethetargetdatabasehasn'tgoneaway.*IftherewasaconcurrentDROPDATABASE,thisensureswewilldie*cleanlywithoutcreatingamess.*/if(!bootstrap){HeapTupletuple;tuple=GetDatabaseTuple(dbname);if(!HeapTupleIsValid(tuple)||MyDatabaseId!=HeapTupleGetOid(tuple)||MyDatabaseTableSpace!=((Form_pg_database)GETSTRUCT(tuple))->dattablespace)ereport(FATAL,(errcode(ERRCODE_UNDEFINED_DATABASE),errmsg("database\"%s\"doesnotexist",dbname),errdetail("Itseemstohavejustbeendroppedorrenamed.")));}/**Nowweshouldbeabletoaccessthedatabasedirectorysafely.Verify*it'sthereandlooksreasonable.*/fullpath=GetDatabasePath(MyDatabaseId,MyDatabaseTableSpace);if(!bootstrap){if(access(fullpath,F_OK)==-1){if(errno==ENOENT)ereport(FATAL,(errcode(ERRCODE_UNDEFINED_DATABASE),errmsg("database\"%s\"doesnotexist",dbname),errdetail("Thedatabasesubdirectory\"%s\"ismissing.",fullpath)));elseereport(FATAL,(errcode_for_file_access(),errmsg("couldnotaccessdirectory\"%s\":%m",fullpath)));}ValidatePgVersion(fullpath);}SetDatabasePath(fullpath);/**It'snowpossibletodorealaccesstothesystemcatalogs.**Loadrelcacheentriesforthesystemcatalogs.Thismustcreateat*leasttheminimumsetof"nailed-in"cacheentries.*/RelationCacheInitializePhase3();/*setupACLframework(soCheckMyDatabasecancheckpermissions)*/initialize_acl();/**Re-readthepg_databaserowforourdatabase,checkpermissionsandset*updatabase-specificGUCsettings.Wecan'tdothisuntilallthe*database-accessinfrastructureisup.(Also,itwantstoknowifthe*userisasuperuser,sotheabovestuffhastohappenfirst.)*/if(!bootstrap)CheckMyDatabase(dbname,am_superuser,override_allow_connections);/**Nowprocessanycommand-lineswitchesandanyadditionalGUCvariable*settingspassedinthestartuppacket.Wecouldn'tdothisbefore*becausewedidn'tknowifclientisasuperuser.*/if(MyProcPort!=NULL)process_startup_options(MyProcPort,am_superuser);/*Processpg_db_role_settingoptions*/process_settings(MyDatabaseId,GetSessionUserId());/*ApplyPostAuthDelayassoonaswe'vereadalloptions*/if(PostAuthDelay>0)pg_usleep(PostAuthDelay*1000000L);/**Initializevariousdefaultstatesthatcan'tbesetupuntilwe've*selectedtheactiveuserandgottentherightGUCsettings.*//*setdefaultnamespacesearchpath*/InitializeSearchPath();/*initializeclientencoding*/InitializeClientEncoding();/*Initializethisbackend'ssessionstate.*/InitializeSession();/*reportthisbackendinthePgBackendStatusarray*/if(!bootstrap)pgstat_bestart();/*closethetransactionwestartedabove*/if(!bootstrap)CommitTransactionCommand();}三、跟踪分析

插入测试数据:

testdb=#--获取pidtestdb=#selectpg_backend_pid();pg_backend_pid----------------1893(1row)testdb=#--插入1行testdb=#insertintot_insertvalues(23,'IamPostgresMain','IamPostgresMain','IamPostgresMain');testdb=#--插入1行insertintot_insertvalues(23,'IamPostgresMain','IamPostgresMain','IamPostgresMain');(挂起)

启动gdb,跟踪调试:

[root@localhost~]#gdb-p1893GNUgdb(GDB)RedHatEnterpriseLinux7.6.1-100.el7Copyright(C)2013FreeSoftwareFoundation,Inc....#断点设置在循环中(gdb)bpostgres.c:4013Breakpoint1at0x850d26:filepostgres.c,line4013....(gdb)pinput_message$7={data=0x1508ef0"insertintot_insertvalues(23,'IamPostgresMain','IamPostgresMain','IamPostgresMain');",len=93,maxlen=1024,cursor=0}(gdb)n...4135switch(firstchar)(gdb)4142SetCurrentStatementStartTimestamp();(gdb)pfirstchar$8=81...(gdb)finishRuntillexitfrom#0PostgresMain(argc=1,argv=0x1532aa8,dbname=0x1532990"testdb",username=0x1532978"xdb")atpostgres.c:4020#DONE!

使用gdb跟踪postgres进程启动过程:

[xdb@localhost~]$gdbpostgres...(gdb)setfollow-fork-modechild(gdb)startTemporarybreakpoint1at0x6f1735:filemain.c,line62.Startingprogram:/appdb/xdb/bin/postgres[Threaddebuggingusinglibthread_dbenabled]Usinghostlibthread_dblibrary"/lib64/libthread_db.so.1".Temporarybreakpoint1,main(argc=1,argv=0x7fffffffe538)atmain.c:6262booldo_check_root=true;(gdb)bPostgresMainBreakpoint2at0x8507bb:filepostgres.c,line3631.(gdb)del1Nobreakpointnumber1....(gdb)attach3028Attachingtoprogram:/appdb/xdb/bin/postgres,process3028...#连接DB[xdb@localhost~]$psql-dtestdb#回到gdb#finish直至进入postmaster.c中的PostgresMain(gdb)finishRuntillexitfrom#0ServerLoop()atpostmaster.c:1704[Newprocess3042][Threaddebuggingusinglibthread_dbenabled]Usinghostlibthread_dblibrary"/lib64/libthread_db.so.1".[SwitchingtoThread0x7ffff7feb740(LWP3042)]Breakpoint2,PostgresMain(argc=1,argv=0xf28ac8,dbname=0xf289b0"testdb",username=0xf28998"xdb")atpostgres.c:36313631volatileboolsend_ready_for_query=true;(gdb)next3632booldisable_idle_in_transaction_timeout=false;(gdb)3635if(!IsUnderPostmaster)(gdb)pIsUnderPostmaster$3=true(gdb)pdbname$4=0xf289b0"testdb"(gdb)pusername$5=0xf28998"xdb"...3845MessageContext=AllocSetContextCreate(TopMemoryContext,(gdb)3855row_description_context=AllocSetContextCreate(TopMemoryContext,(gdb)3858MemoryContextSwitchTo(row_description_context);(gdb)3859initStringInfo(&row_description_buf);(gdb)3860MemoryContextSwitchTo(TopMemoryContext);(gdb)3865if(!IsUnderPostmaster)(gdb)3890if(sigsetjmp(local_sigjmp_buf,1)!=0)(gdb)p*MessageContext$6={type=T_AllocSetContext,isReset=true,allowInCritSection=false,methods=0xb8c720<AllocSetMethods>,parent=0xef9b90,firstchild=0x0,prevchild=0xf74c80,nextchild=0xfabb50,name=0xb4e87c"MessageContext",ident=0x0,reset_cbs=0x0}...(gdb)n4090DoingCommandRead=true;(gdb)4095firstchar=ReadCommand(&input_message);(gdb)4106CHECK_FOR_INTERRUPTS();(gdb)4107DoingCommandRead=false;(gdb)pfirstchar$8=81(gdb)pinput_message$9={data=0xeff010"insertintot_insertvalues(24,'IamPostgresMain','IamPostgresMain','IamPostgresMain');",len=93,maxlen=1024,cursor=0}(gdb)n...#DONE!

到此,相信大家对“PostgreSQL中PostgresMain函数的实现逻辑是什么”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!