2015-10-07 1 views
3

J'ai implémenté la macro syscall pour appeler les appels d'interruption logiciels. Cela fonctionnait bien pour beaucoup de syscalls. Cependant, ce n'était pas pour fork(). Le pid de retour est le même pour le processus parent et enfant. L'extrait est comme ci-dessous:fork() implémentation à l'aide de l'appel svc

#define SYSCALL0(N) ({           \ 
    register int ip asm("ip") = N;        \ 
    register int r0 asm("r0");         \ 
    asm volatile("swi 0x80" : "=r"(r0) : "r"(ip) : "memory"); \ 
    r0;               \ 
}) 

int main(int argc, char * argv[]) { 
    NSLog(@"--beginning of program\n"); 
    int counter = 0; 
    pid_t pid = SYSCALL0(2); 
    if (pid == 0) { 
     NSLog(@"pid = %d", getpid()); 
     // child process 
     for (int i = 0; i < 3; ++i) 
      NSLog(@"child process: counter=%d\n", ++counter); 
    } 
    else if (pid > 0) { 
     NSLog(@"pid = %d", getpid()); 
     // parent process 
     for (int i = 0; i < 3; ++i) 
      NSLog(@"parent process: counter=%d\n", ++counter); 
    } 
    else { 
     // fork failed 
     NSLog(@"fork() failed!\n"); 
     return 1; 
    } 
    NSLog(@"--end of program--\n"); 
} 

Sortie:

2015-10-11 21:29:43.666 Training[2564:907] --beginning of program 
2015-10-11 21:29:43.669 Training[2564:907] pid = 2650 
2015-10-11 21:29:43.670 Training[2564:907] parent process: counter=1 
2015-10-11 21:29:43.670 Training[2564:907] parent process: counter=2 
2015-10-11 21:29:43.669 Training[2564:907] pid = 2650 
2015-10-11 21:29:43.671 Training[2564:907] parent process: counter=3 
2015-10-11 21:29:43.671 Training[2564:907] --end of program-- 
2015-10-11 21:29:43.671 Training[2564:907] parent process: counter=1 
2015-10-11 21:29:43.672 Training[2564:907] parent process: counter=2 
2015-10-11 21:29:43.673 Training[2564:907] parent process: counter=3 
2015-10-11 21:29:43.674 Training[2564:907] --end of program-- 

L'environnement testé est une prison iOS cassé (il ne fonctionnera pas sur la non-jailbreaké) en cours d'exécution sur ARMv7. Je pense que je n'ai peut-être pas fait assez avec le retour de l'appel swi, donc il ne pouvait pas retourner 0 pour indiquer le processus de l'enfant. Qu'est-ce que j'ai raté? Comment puis-je le faire fonctionner correctement?

+0

Quelle est votre question? – Lorenzo

+2

Désolé si ce n'est pas clair, je modifiais la question. La question est "Comment puis-je le faire fonctionner correctement" – Krypton

Répondre

1

Je le découvre. Il s'avère qu'après l'appel svc, r1 est défini comme indicateur si le code suivant est enfant ou parent. L'extrait est changé comme ci-dessous:

#include <dlfcn.h> 
int svc_fork() { 
    register int r3 asm("r3") = (int)dlsym(RTLD_DEFAULT, "_current_pid"); 
    register int r12 asm("r12") = 2; 
    register int r1 asm("r1") = 1; 
    register int r0 asm("r0"); 
    asm volatile("swi 0x80      \n" 
       "cmp r1, #0      \n" 
       "beq Lparent      \n" 
       "mov r0, #0      \n" 
       "str r0, [r3]      \n" 
       "Lparent:       \n" 
       : "=r"(r0) 
       : "r"(r1), "r"(r12), "r"(r3) 
       : "memory"); 
    return r0; 
} 
2

Vous ne faites pas les appels système de cette façon. Les wrappers d'utilisateur pour les syscalls font beaucoup plus de travail que cela, comme vous venez de le remarquer. Donc soit trouver le code source de votre système d'exploitation, comprendre comment les appels système sont enveloppés et faire la même chose, ou simplement utiliser les wrappers qui ont été commodément fournis pour vous. Je suis à peu près sûr que iOS fait toujours des syscalls BSD façon. Je sais que fork utilise les deux valeurs de retour de l'interface syscall, un registre contient si le processus est un processus fils, l'autre contient la valeur de retour.

En outre, votre wrapper ne gère probablement pas correctement les erreurs (cela est généralement signalé par un drapeau que vous devez gérer spécialement). Et au moins certains systèmes d'exploitation (je ne sais pas si iOS est l'un d'entre eux) savent exactement quels registres sont sauvegardés dans les wrappers syscall et ne les dérangent pas, donc des appels système comme cela peuvent détruire vos registres.

+0

Le problème est que je ne peux pas trouver de code source, alors je l'ai mis en place en regardant cette page https://www.theiphonewiki.com/wiki/ Kernel_Syscalls – Krypton

+0

Si vous creusez sur le web, vous trouverez peut-être une ancienne source pour Darwin qui devrait être assez proche. Mais oui, l'idée est que vous ne devriez pas le faire vous-même. Quel est le problème avec l'utilisation des appels système correctement enveloppés que votre système d'exploitation vous fournit? – Art

+0

J'ai trouvé le code darwin pour cela. J'espère que ça marchera, voyons. – Krypton