⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 subprocess.cpp

📁 基于ecos的redboot
💻 CPP
📖 第 1 页 / 共 2 页
字号:
          break;  
        case 0:
          goto Done;
          continue;
        default:
          buf[rc]=_TCHAR('\0');
          Output(String::CStrToUnicodeStr(buf));
          continue;
      }
    } while(!m_bKillThread && m_pfnContinue(m_pContinuationFuncParam));
Done:
    TRACE(_T("Closing fd %d\n"),m_tty);
    close (m_tty);
  
    switch(waitpid(m_idProcess,&m_nExitCode,WNOHANG));
  }
  
  if(m_bAutoDelete){
    delete this;
  }
}
#endif

void CSubprocess::Output (LPCTSTR psz)
{
  m_pfnLogfunc(m_pLogparam,psz);
}

void CSubprocess::Send(LPCTSTR str)
{
  char *psz=String(str).GetCString();
  int nToWrite=strlen(psz);
  const char *c=psz;
  do {
#ifdef _WIN32
    DWORD dwWritten;
    if(!::WriteFile(m_hwPipe,psz,nToWrite,&dwWritten,0)){
      break;
    }
#else
    int dwWritten = write(m_tty, c, nToWrite);
    if(-1==dwWritten){
      break;
    } 
#endif
    nToWrite-=(int)dwWritten;
    c+=(int)dwWritten;
  } while (nToWrite>0);
  //::FlushFileBuffers(m_hwPipe);
  delete [] psz;
}

bool CSubprocess::Kill(bool bRecurse)
{
TRACE(_T("CSubprocess::Kill pid %d recurse=%d\n"),m_idProcess,bRecurse);
  PInfoArray arPinfo;
  bool rc=false;
  if(m_idProcess && -1!=m_idProcess){
    // Start of with the easy one:
    if(bRecurse) {
      // Need to gather this information before we orphan our grandchildren:
      PSExtract(arPinfo);
    }
    
#ifdef _WIN32

    if(m_hProcess){
      TRACE(_T("Terminate process %s\n"),(LPCTSTR)Name(m_idProcess));
      rc=(TRUE==::TerminateProcess(m_hProcess,PROCESS_KILL_EXIT_CODE));
      // dtor's (or subsequent Run's) responsibility to close the handle
    }

#else
    rc=(0==kill(m_idProcess,SIGTERM));
    int status;
    waitpid(m_idProcess,&status,WNOHANG);
#endif
    
    if(bRecurse) {
      // kill process *and* its children
      // FIXME: needs to be top-down
      for(int i=0;i<(signed)arPinfo.size();i++){
        if(arPinfo[i].IsChildOf(m_idProcess)){
      
#ifdef _WIN32
          // begin hack
          const String strName(Name(arPinfo[i].PID));
          if(_tcsstr(strName,_T("eCosTest")) || _tcsstr(strName,_T("cmd.EXE")) || _tcsstr(strName,_T("CMD.EXE")) || arPinfo[i].PID==(signed)GetCurrentProcessId()){
            continue;
          }
          // end hack
          HANDLE hProcess=::OpenProcess(PROCESS_TERMINATE,false,arPinfo[i].PID);
          if(hProcess){
            TRACE(_T("Terminate process %s\n"),(LPCTSTR)Name(arPinfo[i].PID));
            rc&=(TRUE==::TerminateProcess(hProcess,PROCESS_KILL_EXIT_CODE));
            CloseHandle(hProcess);
          } else {
            rc=false;
          }
#else
          rc&=(0==kill(arPinfo[i].PID,SIGTERM));
          int status;
          waitpid(arPinfo[i].PID,&status,WNOHANG);
#endif
        }
      }
    }
  }
  return rc;
}

Time CSubprocess::CpuTime(bool bRecurse) const
{
  Time t=0;
  // kill process *and* its children
  // FIXME: needs to be top-down
  
#ifdef _WIN32
  __int64 ftCreation,ftExit,ftKernel,ftUser;
  if(m_hProcess && ::GetProcessTimes (m_hProcess,(FILETIME *)&ftCreation,(FILETIME *)&ftExit,(FILETIME *)&ftKernel,(FILETIME *)&ftUser)){
    t+=Time((ftKernel+ftUser)/10000);
  }

  if(bRecurse){
    PInfoArray arPinfo;
    PSExtract(arPinfo);
    if(m_idProcess && -1!=m_idProcess){
      for(int i=0;i<(signed)arPinfo.size();i++){
        if(arPinfo[i].IsChildOf(m_idProcess)){
          t+=arPinfo[i].tCpu;
        }
      }
    }
  }
#else
  PInfoArray arPinfo;
  PSExtract(arPinfo);
  for(int i=0;i<(signed)arPinfo.size();i++){
    if(arPinfo[i].PID==m_idProcess || arPinfo[i].IsChildOf(m_idProcess)){
      t+=arPinfo[i].tCpu;
    }
  }
#endif
  return t;
}

#ifdef _WIN32
bool CSubprocess::PSExtract(CSubprocess::PInfoArray &arPinfo)
{
  bool rc=false;
  arPinfo.clear();
  // If Windows NT:
  switch(GetPlatform()) {
  case VER_PLATFORM_WIN32_NT:
    if(hInstLib1) {
      
      // Get procedure addresses.
      static BOOL (WINAPI *lpfEnumProcesses)( DWORD *, DWORD cb, DWORD * ) = (BOOL(WINAPI *)(DWORD *,DWORD,DWORD*))GetProcAddress( hInstLib1, "EnumProcesses" ) ;
      if( lpfEnumProcesses) {
        
        if(hInstLib2) {
          
          static DWORD (WINAPI *lpfNtQueryInformationProcess)( HANDLE, int, void *, DWORD, LPDWORD ) =
            (DWORD(WINAPI *)(HANDLE, int, void *, DWORD, LPDWORD)) GetProcAddress( hInstLib2,"NtQueryInformationProcess" ) ;
          
          if(lpfNtQueryInformationProcess){
            DWORD dwMaxPids=256;
            DWORD dwPidSize;
            DWORD *arPids = NULL ;
            do {
              delete [] arPids;
              arPids=new DWORD[dwMaxPids];
            } while(lpfEnumProcesses(arPids, dwMaxPids, &dwPidSize) && dwPidSize/sizeof(DWORD)==dwMaxPids) ;
            
            if(dwPidSize/sizeof(DWORD)<dwMaxPids){
              rc=true;
              for( DWORD dwIndex = 0 ; (signed)dwIndex < dwPidSize/sizeof(DWORD); dwIndex++ ) {
                // Regardless of OpenProcess success or failure, we
                // still call the enum func with the ProcID.
                DWORD pid=arPids[dwIndex];
                HANDLE hProcess=::OpenProcess( PROCESS_QUERY_INFORMATION, FALSE, pid ); 
                if (hProcess ) {
                  struct {
                    DWORD ExitStatus; // receives process termination status
                    DWORD PebBaseAddress; // receives process environment block address
                    DWORD AffinityMask; // receives process affinity mask
                    DWORD BasePriority; // receives process priority class
                    ULONG UniqueProcessId; // receives process identifier
                    ULONG InheritedFromUniqueProcessId; // receives parent process identifier
                  } pbi;
                  memset( &pbi, 0, sizeof(pbi)); 
                  DWORD retLen; 
                  __int64 ftCreation,ftExit,ftKernel,ftUser;
                  if(lpfNtQueryInformationProcess(hProcess, 0 /*ProcessBasicInformation*/, &pbi, sizeof(pbi), &retLen)>=0 &&
                    TRUE==::GetProcessTimes (hProcess,(FILETIME *)&ftCreation,(FILETIME *)&ftExit,(FILETIME *)&ftKernel,(FILETIME *)&ftUser)){
                    // The second test is important.  It excludes orphaned processes who appear to have been adopted by virtue of a new
                    // process having been created with the same ID as their original parent.
                    PInfo p;
                    p.PID=pid;
                    p.PPID=pbi.InheritedFromUniqueProcessId;
                    p.tCreation=ftCreation;
                    p.tCpu=Time((ftKernel+ftUser)/10000);
                    arPinfo.push_back(p);
                  }
                  
                  CloseHandle(hProcess); 

                }
              }
            }
            delete [] arPids;
          }          
        }
      }      
    }
    break;
  case VER_PLATFORM_WIN32_WINDOWS:
    
    if( hInstLib1) {
      
      static HANDLE (WINAPI *lpfCreateToolhelp32Snapshot)(DWORD,DWORD)=
        (HANDLE(WINAPI *)(DWORD,DWORD))GetProcAddress( hInstLib1,"CreateToolhelp32Snapshot" ) ;
      static BOOL (WINAPI *lpfProcess32First)(HANDLE,LPPROCESSENTRY32)=
        (BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32))GetProcAddress( hInstLib1, "Process32First" ) ;
      static BOOL (WINAPI *lpfProcess32Next)(HANDLE,LPPROCESSENTRY32)=
        (BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32))GetProcAddress( hInstLib1, "Process32Next" ) ;
      if( lpfProcess32Next && lpfProcess32First && lpfCreateToolhelp32Snapshot) {
        
        // Get a handle to a Toolhelp snapshot of the systems
        // processes.
        HANDLE hSnapShot = lpfCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) ;
        if(INVALID_HANDLE_VALUE != hSnapShot) {
          // Get the first process' information.
          PROCESSENTRY32 procentry;
          procentry.dwSize = sizeof(PROCESSENTRY32) ;
          if(lpfProcess32First( hSnapShot, &procentry )){
            rc=true;
            do {
              PInfo p;
              p.PID=procentry.th32ProcessID;
              p.PPID=procentry.th32ParentProcessID;
              arPinfo.push_back(p);
            } while(lpfProcess32Next( hSnapShot, &procentry ));
          }
          CloseHandle(hSnapShot);
        }
      }
    }
    break;
  default:
    break;
  }    

  SetParents(arPinfo);

  if(!rc){
    ERROR(_T("Couldn't get process information!\n"));
  }
  return rc;
}

#else // UNIX

bool CSubprocess::PSExtract(CSubprocess::PInfoArray &arPinfo)
{
  arPinfo.clear();
  int i;
  FILE *f=popen("ps -l",_T("r") MODE_TEXT);
  if(f){
    char buf[100];
    while(fgets(buf,sizeof(buf)-1,f)){
      TCHAR discard[100];
      PInfo p;
      // Output is in the form
      //  F S   UID   PID  PPID  C PRI  NI ADDR    SZ WCHAN  TTY          TIME CMD
      //100 S   490   877   876  0  70   0    -   368 wait4  pts/0    00:00:00 bash
      int F,UID,C,PRI,NI,SZ,HH,MM,SS; 
      bool rc=(15==_stscanf(buf,_T("%d %s %d %d %d %d %d %d %s %d %s %s %d:%d:%d"),&F,discard,&UID,&p.PID,&p.PPID,&C,&PRI,&NI,discard,&SZ,discard,discard,&HH,&MM,&SS));
      if(rc){
        p.tCpu=1000*(SS+60*(60*HH+MM));
        arPinfo.push_back(p);
      }
    }
    pclose(f);
    for(i=0;i<(signed)arPinfo.size();i++){
      int pid=arPinfo[i].PPID;
      arPinfo[i].pParent=0;
      for(int j=0;j<(signed)arPinfo.size();j++){
        if(i!=j && arPinfo[j].PID==pid){
          arPinfo[i].pParent=&arPinfo[j];
          break;
        }
      }
    }
  } else {
    ERROR(_T("Failed to run ps -l\n"));
  }
  return true; //FIXME
}

#endif

void CSubprocess::SetParents(CSubprocess::PInfoArray &arPinfo)
{
  int i;
  for(i=0;i<(signed)arPinfo.size();i++){
    PInfo &p=arPinfo[i];
    p.pParent=0;
    for(int j=0;j<(signed)arPinfo.size();j++){
      if(arPinfo[j].PID==p.PPID 
#ifdef _WIN32
        && arPinfo[j].tCreation<p.tCreation
#endif
        )
      {
        arPinfo[i].pParent=&arPinfo[j];
        break;
      }
    }
  }

  // Check for circularity
  bool bCircularity=false;
  for(i=0;i<(signed)arPinfo.size();i++){
    PInfo *p=&arPinfo[i];
    for(int j=0;j<(signed)arPinfo.size() && p;j++){
      p=p->pParent;
    }
    // If all is well, p should be NULL here.  Otherwise we have a loop.
    if(p){
      // Make sure it can't foul things up:
      arPinfo[i].pParent=0;
      bCircularity=true;
    }
  }
  
  if(bCircularity){
    ERROR(_T("!!! Circularly linked process list at index %d\n"),i);
    for(int k=0;k<(signed)arPinfo.size();k++){
      const PInfo &p=arPinfo[k];
      ERROR(_T("%d: %s ppid=%4d\n"),k,(LPCTSTR)Name(p.PID),p.PPID);
    }
  }
}

bool CSubprocess::PInfo::IsChildOf(int pid) const
{
  for(PInfo *p=pParent;p && p!=this;p=p->pParent) { // guard against circular linkage
    if(p->PID==pid){
      return true;
    }
  }
  return false;
}

const String CSubprocess::Name(int pid)
{
  String str(String::SFormat(_T("id=%d"),pid));
#ifdef _DEBUG
#ifdef _WIN32
  if(VER_PLATFORM_WIN32_NT==GetPlatform() && hInstLib1){
    static BOOL (WINAPI *lpfEnumProcessModules)( HANDLE, HMODULE *, DWORD, LPDWORD ) =
      (BOOL(WINAPI *)(HANDLE, HMODULE *, DWORD, LPDWORD)) GetProcAddress( hInstLib1,"EnumProcessModules" ) ;
    static DWORD (WINAPI *lpfGetModuleFileNameEx)( HANDLE, HMODULE, LPTSTR, DWORD )=
      (DWORD (WINAPI *)(HANDLE, HMODULE,LPTSTR, DWORD )) GetProcAddress( hInstLib1,"GetModuleFileNameExA" ) ;
    if( lpfEnumProcessModules &&  lpfGetModuleFileNameEx ) {
      HANDLE hProcess=::OpenProcess(PROCESS_ALL_ACCESS,false,pid);
      if(hProcess) {
        HMODULE hMod;
        DWORD dwSize;
        if(lpfEnumProcessModules( hProcess, &hMod, sizeof(HMODULE), &dwSize ) ){
          // Get Full pathname:
          TCHAR buf[1+MAX_PATH];
          lpfGetModuleFileNameEx( hProcess, hMod, buf, MAX_PATH);
          str+=_TCHAR(' ');
          str+=buf;
        }
        CloseHandle(hProcess);
      }
    }
  }
#endif
#endif
  return str;
}

#ifdef _WIN32
DWORD CSubprocess::GetPlatform()
{
  OSVERSIONINFO  osver;
  osver.dwOSVersionInfoSize = sizeof( osver ) ;
  return GetVersionEx( &osver ) ? osver.dwPlatformId : (DWORD)-1;
}
#endif

bool CSubprocess::ProcessAlive()
{
  return !m_bThreadTerminated;
}

void CSubprocess::CloseInput()
{
#ifdef _WIN32
  CloseHandle(m_hwPipe);m_hwPipe=INVALID_HANDLE_VALUE;
#else
  close(m_tty);
#endif
}

bool CSubprocess::Wait(Duration dTimeout)
{
  return CeCosThreadUtils::WaitFor(m_bThreadTerminated,dTimeout);
}

const String CSubprocess::ErrorString() const
{
#ifdef _WIN32
  TCHAR *pszMsg;
  FormatMessage(  
    FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
    NULL,
    m_nErr,
    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
    (LPTSTR)&pszMsg,
    0,
    NULL 
    );
  return pszMsg;
#else 
  return strerror(errno);
#endif
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -