2011-03-29 29 views
5

DÜZENLEME (YAPILANDIRMA İLERLEME):Çok iş parçacıklı bir uygulama nasıl yapılır?

Bir vsftpd arka planına ptrace yapmaya çalışıyorum. Daemon'a bağlanan şu kodum var. Ardından, ilk ortaya çıkan işlemin PID'sini başarıyla görüntüler. Bununla birlikte, bu yumurtlama sürecinin çocukları için PID'leri 2,3 olarak döndürür. Program, ortaya çıkan süreçlerin çıkmasını yakalar, bu da bana yakın olduğumu düşünür.

Herhangi bir fikrin var mı?

void * trace_process(void * pid){ 
    pid_t child = atoi((char *) pid); 
    long orig_eax, eax; 
    int status; 
    int callmade = FALSE; 
    long opt = PTRACE_O_TRACEFORK; 
    long newpid; 

    long trace = ptrace(PTRACE_ATTACH,child,NULL,NULL); 
    ptrace(PTRACE_SETOPTIONS,child,NULL,opt); 
    if(trace == FALSE) 
     printf("Attached to %d\n",child); 

    while(TRUE) { 
     child = waitpid(-1, &status, __WALL); 

     if (status >> 16 == PTRACE_EVENT_FORK) { 
      ptrace(PTRACE_GETEVENTMSG, child, NULL, (long) &newpid); 
      ptrace(PTRACE_SYSCALL, newpid, NULL, NULL);  

      printf("Attached to offspring %ld\n", newpid); 
     } 
     else{ 
      if(WIFEXITED(status)) 
       printf("Child %d exited\n", child); 
     } 

     ptrace(PTRACE_SYSCALL,child, NULL, NULL); 
    } 
} 

Örnek çıktı:

Attached to 2015 // daemon 
Attached to offspring 5302 // new connection handler 
Attached to offspring 2 // should be authenticator 
Child 5303 exited  // authenticator exiting on successful login 
Attached to offspring 3 // should be process serving files 
Child 5304 exited  // logout: process serving files 
Child 5302 exited  // connection closed 
Attached to offspring 5305 // new connection handler 
Attached to offspring 2 // ... repeat 
Child 5306 exited 
Attached to offspring 3 
Child 5307 exited 
Child 5305 exited 
+0

Eğer strace (1) 'baktınız mı' hiç? –

+0

@Nikolai N Fetissov Şimdi strace kaynağına bakıyorum. Geçmesi tam olarak kolay değil. Daha ilginç olan şey, ben vsftpd pidine strace ekledim ve ncftp kullanarak giriş yaptığımda "bağlanıyor ..." diyaloğunda asılı kalmam. Strace'den ctrl-c olduğunda düzgün şekilde devam eder. Yani strace de çalışmıyor. – ofosho

+0

'-f' seçeneğini kullandınız mı? –

cevap

1

Ben Ebeveynlerinden ve çocuklarından gelen tüm sistem çağrılarını yakalamak için gerçekten çalıştığını fark edin. Tek sorun, PID'lerin gerçek PI'lerden ziyade göreceli olarak döndürülmesidir. Bu, bekletilen PID'nin aslında ebeveyn tarafından oluşturulduğundan emin olmamasına neden olur. Her iki durumda da, kod tüm sistem çağrılarını alacaktır. PID'in neden göreli olduğunu bilmek istiyorum, kendi bilgim için, ancak kod gayet iyi çalışıyor.

+0

Göreli PID'ler değiller, yeni PID ad alanında pids'ler (1'den başlayarak). Aslında şu anda vsftpd'ye saldırmaya çalışıyor ve strace kaynağının derinlerine diriliyor. –

0

Playing with ptrace makale okurken, ben de bu mücadele bir kullanıcıdan this comment bulundu: benim koduyla ileri gittikten sonra

/* After struggled a long time, I got a true way to make my ptrace worked 
* correct with multi-thread application. Here're my sample codes, hope it 
* can help others whom have the same confusion. */  

char trapCode[] = {0, 0, 0, 0}; 
int status; 

ptrace(PTRACE_ATTACH, childProcess, NULL, NULL); //childProcess is the main thread 
wait(NULL); 

printf("\nchild %d created\n", childProcess); 
fflush(stdout); 

long ptraceOption = PTRACE_O_TRACECLONE; 
ptrace(PTRACE_SETOPTIONS, childProcess, NULL, ptraceOption); 

struct user_regs_struct regs; 

for(unsigned int i = 0; i < m_breakPoints.size(); i++) 
{ 
    BreakPoint_Info breakPointInfo = m_breakPoints[i]; 
    if(!breakPointInfo.m_enabled) 
     continue; 

    unsigned int index = breakPointInfo.m_checkPointIndex; 
    if(m_bytesBackup.find(m_checkPoints[index].m_offset) != m_bytesBackup.end()) 
     continue; 

    unsigned long readAddr = m_checkPoints[index].m_offset; 
    One_Byte_With_Result *oneByte = new One_Byte_With_Result; 
    getData(childProcess, readAddr, trapCode, 4); 
    oneByte->m_char = trapCode[0]; 
    trapCode[0] = 0xcc; 
    putData(childProcess, readAddr, trapCode, 4); 

    m_bytesBackup.insert(std::make_pair(m_checkPoints[index].m_offset, oneByte)); 
} 

std::set allThreads; 
std::set::iterator allThreadsIter; 
allThreads.insert(childProcess); 

int rec = ptrace(PTRACE_CONT, childProcess, NULL, NULL); 

while(true) 
{ 
    pid_t child_waited = waitpid(-1, &status, __WALL); 

    if(child_waited == -1) 
     break; 

    if(allThreads.find(child_waited) == allThreads.end()) 
    { 
     printf("\nreceived unknown child %d\t", child_waited); 
     break; 
    } 

    if(WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) 
    { 
     pid_t new_child; 
     if(((status >> 16) & 0xffff) == PTRACE_EVENT_CLONE) 
     { 
      if(ptrace(PTRACE_GETEVENTMSG, child_waited, 0, &new_child) != -1) 
      {   
       allThreads.insert(new_child); 
       ptrace(PTRACE_CONT, new_child, 0, 0); 

       printf("\nchild %d created\t", new_child); 
      } 

      ptrace(PTRACE_CONT, child_waited, 0, 0); 
      continue; 
     } 
    } 

    if(WIFEXITED(status)) 
    { 
     allThreads.erase(child_waited); 
     printf("\nchild %d exited with status %d\t", child_waited, WEXITSTATUS(status)); 

     if(allThreads.size() == 0) 
      break; 
    } 
    else if(WIFSIGNALED(status)) 
    { 
     allThreads.erase(child_waited); 
     printf("\nchild %d killed by signal %d\t", child_waited, WTERMSIG(status)); 

     if(allThreads.size() == 0) 
      break; 
    } 
    else if(WIFSTOPPED(status)) 
    { 
     int stopCode = WSTOPSIG(status); 
     if(stopCode == SIGTRAP) 
     { 
      ptrace(PTRACE_GETREGS, child_waited, NULL, &regs); 
      unsigned long currentEip = regs.eip; 
      //printf("%d\t%08x\n", child_waited, currentEip); 

      Address_Bytes_Map::iterator iter = m_bytesBackup.find(currentEip - 1); 
      if(iter != m_bytesBackup.end()) 
      { 
       iter->second->m_result = true; 

       regs.eip = regs.eip - 1; 
       getData(child_waited, regs.eip, trapCode, 4); 
       trapCode[0] = iter->second->m_char; 
       putData(child_waited, regs.eip, trapCode, 4); 
       rec = ptrace(PTRACE_SETREGS, child_waited, NULL, &regs); 
      } 
     } 
    } 

    rec = ptrace(PTRACE_CONT, child_waited, 1, NULL); 

    continue; 
} 
+0

Evet, benim üzerinde çalıştığım kod bu. Temelde aynı şeylere sahibim, ancak yayınlama amaçları için basitleştirildi. Onun versiyonunu doğrudan kullandığımda "bilinmeyen bir çocuk" alıyorum ve çıkar. Bu mantıklıdır çünkü saklandığı (2,3, ..) ve çıkarken gerçek pideyi almıştır. Yazılışı takdir ediyorum. – ofosho

+0

@ofosho Tamam, daha sonra buna bir göz atacağım. – karlphillip

1

İş parçacığının sonraki wait()'dan önce çalışmasına izin verin.

Dene:

ptrace(PTRACE_SYSCALL,child, NULL, NULL); 

önce:

while(TURE) 
İlgili konular