📄 mpiexec.c
字号:
know what to do with new environment variables), but this will allow us to start. */ { ProcessApp *app = pState->app; const char **newargs = 0; char *pmiDebugStr = 0; int j; char rankStr[12]; /* Insert into app->args */ newargs = (const char **) malloc( (app->nArgs + 14 + 1) * sizeof(char *) ); if (!pState->hostname) { MPIU_Error_printf( "No hostname avaliable for %s\n", app->exename ); exit(1); } snprintf( rankStr, sizeof(rankStr)-1, "%d", pState->id ); rankStr[12-1] = 0; curarg = 0; newargs[curarg++] = pState->hostname; curarg += AddEnvSetToCmdLine( "PMI_PORT", s->pmiinfo.portName, newargs + curarg ); curarg += AddEnvSetToCmdLine( "PMI_ID", rankStr, newargs + curarg ); pmiDebugStr = getenv( "PMI_DEBUG" ); if (pmiDebugStr) { /* Use this to help debug the connection process */ curarg += AddEnvSetToCmdLine( "PMI_DEBUG", pmiDebugStr, newargs + curarg ); } newargs[curarg++] = app->exename; for (j=0; j<app->nArgs; j++) { newargs[j+curarg] = app->args[j]; } newargs[j+curarg] = 0; app->exename = strdup( "/usr/bin/ssh" ); app->args = newargs; app->nArgs += curarg; if (MPIE_Debug) { printf( "cmd = %s\n", app->exename ); fflush(stdout); printf( "Number of args = %d\n", app->nArgs ); for (j=0; j<app->nArgs; j++) { printf( "argv[%d] = %s\n", j, app->args[j] ); fflush(stdout); } } } return 0;}/* Close one side of the pipe pair and register a handler for the I/O */int mypostamble( void *predata, void *data, ProcessState *pState ){ SetupInfo *s = (SetupInfo *)predata; IOLabelSetupFinishInServer( &s->labelinfo, pState ); PMISetupFinishInServer( 1, &s->pmiinfo, pState ); return 0;}int myspawn( ProcessWorld *pWorld, void *data ){ SetupInfo *s = (SetupInfo *)data; ProcessWorld *p, **pPtr; p = pUniv.worlds; pPtr = &(pUniv.worlds); while (p) { pPtr = &p->nextWorld; p = *pPtr; } *pPtr = pWorld; /* Fork Processes may call a routine that is passed s but not pWorld; this makes sure that all routines can access the current world */ s->pmiinfo.pWorld = pWorld; /* FIXME: This should be part of the PMI initialization in the clients */ MPIE_Putenv( pWorld, "PMI_SPAWNED=1" ); MPIE_ForkProcesses( pWorld, 0, mypreamble, s, mypostfork, 0, mypostamble, 0 ); return 0;}/* Temp test for the replacement for the simple "spawn == fork" *//* * Approach: * Processes are created using a remote shell program. This requires * changing the command line from * * a.out args ... * * to * * remshell-program remshell-args /bin/sh -c PMI_PORT=string && * export PMI_PORT && PMI_ID=rank-in-world && export PMI_ID && * a.out args * * (the export PMI_PORT=string syntax is not valid in all versions of sh) * * Using PMI_ID ensures that we correctly identify each process (this was * a major problem in the setup used by the p4 device in MPICH1). * Using environment variables instead of command line arguments keeps * the commaand line clean. * * Two alternatives should be considered * 1) Use an intermediate manager. This would allow us to set up the * environment as well: * remshell-program remshell-args manager -port string * One possibilty for the manager is the mpd manager * 2) Use the secure server (even the same one as in MPICH1); then * there is no remote shell command. * * We can handle the transformation of the command line by adding a * to the postfork routine; this is called after the fork but before the * exec, and it can change the command line by making a copy of the app * structure, changing the command line, and setting the pState structure * to point to this new app (after the fork, these changes are visable only * to the forked process). * * Enhancements: * Allow the code to avoid the remote shell if the process is being created * on the local host. * * Handle the user of -l username and -n options to remshell * (-n makes stdin /dev/null, necessary for backgrounding). * (-l username allows login to hosts where the user's username is * different) * * Provide an option to add a backslash before any - to deal with the * serious bug in the GNU inetutils remote shell programs that process * *all* arguments on the remote shell command line, even those for the * *program*! * * To best support the errcodes return from MPI_Comm_spawn, * we need a way to communicate the array of error codes back to the * spawn and spawn multiple commands. Query: how is that done in * PMI? * */#if 0/* ----------------------------------------------------------------------- *//* Convert the remote shell command into argv format *//* The command may be specified as a string with blanks separating the *//* arguments, either from the default, an environment variable, or *//* eventually the machines file (allowing different options for each host *//* or the command line. *//* Returns the number of arguments *//* For example, this allows "ssh -2" as a command *//* Allow the environment variable MPIEXEC_REMSHELL to set the remote shell *//* program to use *//* ----------------------------------------------------------------------- */const char defaultRemoteshell[] = DEFAULT_REMOTE_SHELL;#define MAX_REMSHELL_ARGS 10int MPIE_GetRemshellArgv( char *argv[], int nargv ){ static char *(remshell[MAX_REMSHELL_ARGS]); static int remargs = 0; int i; /* Convert the string for the remote shell command into an argv list */ if (!remargs) { const char *rem = getenv( "MPIEXEC_REMSHELL" ); char *next_parm; if (!rem) rem = defaultRemoteshell; /* Unpack the string into remshell. Allow 10 tokens */ while (rem) { int len; next_parm = strchr( rem, ' ' ); if (next_parm) len = next_parm - rem; else len = strlen(rem); remshell[remargs] = (char *)MPIU_Malloc( len + 1 ); MPIU_Strncpy( remshell[remargs], rem, len ); remshell[remargs][len] = 0; remargs++; if (next_parm) { rem = next_parm + 1; while (*rem == ' ') rem++; if (remargs >= MAX_REMSHELL_ARGS) { /* FIXME */ MPIU_Error_printf( "Remote shell command is too complex\n" ); exit(1); } } else { rem = 0; } } } /* remshell contains the command. Copy into argv and return the number of args. We just copy *pointers* because any variable fields will be replaced by the other commands */ for (i=0; i<remargs; i++) argv[i] = remshell[i]; return remargs;}#endif/* */static int AddEnvSetToCmdLine( const char *envName, const char *envValue, const char **args ){ int nArgs = 0; static int useCSHFormat = -1; /* Determine the Shell type the first time*/ if (useCSHFormat == -1) { char *shell = getenv( "SHELL" ), *sname; if (shell) { printf( "Shell is %s\n", shell ); sname = strrchr( shell, '/' ); if (!sname) sname = shell; else sname++; printf( "Sname is %s\n", sname ); if (strcmp( sname, "bash" ) == 0 || strcmp( sname, "sh" ) || strcmp( sname, "ash" ) == 0) useCSHFormat = 0; else useCSHFormat = 1; } else { /* Default is to assume csh (setenv) format */ useCSHFormat = 1; } } if (useCSHFormat) { args[nArgs++] = strdup( "setenv" ); args[nArgs++] = strdup( envName ); args[nArgs++] = strdup( envValue ); args[nArgs++] = strdup( ";" ); } else { char tmpBuf[1024]; args[nArgs++] = strdup( "export" ); MPIU_Strncpy( tmpBuf, envName, sizeof(tmpBuf) ); MPIU_Strnapp( tmpBuf, "=", sizeof(tmpBuf) ); MPIU_Strnapp( tmpBuf, envValue, sizeof(tmpBuf) ); args[nArgs++] = strdup( tmpBuf ); args[nArgs++] = strdup( ";" ); } return nArgs;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -