2013-05-05 2 views
1

Je suis actuellement en train de développer un noyau et de rencontrer un problème mystérieux lors de l'implémentation de l'appel système. Je vous écris le gestionnaire d'interruption 0x80th comme ceci:comportement étrange dans le gestionnaire d'interruptions

sys_call_s: 
    pushad 
    call sys_call 
    popad 
    iret 

« sys_call » est le nom de la fonction C qui font le vrai travail. Le problème est: J'ai une triple erreur lors de l'exécution de l'instruction suivante de "int 0x80". Par exemple, j'ai une erreur lors de l'exécution de la troisième ligne du programme ci-dessous et finalement les bochs vont se réinitialiser.

abc: mov eax,0    ; 0 means system call get_pid() 
    int 0x80 
    mov [pid_father],eax ; this is the instruction caused bochs to triple fault 
    mov eax,1    ; 1: fork() 
    int 0x80 
    jmp $ 

pid_father: dd 0 

Encore plus strangly, quand je remplace l'instruction "IRET" avec "ret", le programme fonctionne très bien et se tourner à "jmp $".

Est-ce que quelqu'un a une idée de pourquoi j'ai eu ce problème?

[edit] Maintenant, je pense que ce problème est causé par la mauvaise adresse du pointeur de la pile. J'ai mappé une page pour ce processus, l'adresse physique de cette page est 0x401000, l'adresse linéaire est 0x800000 (8M). J'ai placé le pointeur de pile de ce processus à 0x800ff0, mais chaque fois que j'utilise la commande "d'impression-pile" dans des bochs la sortie est: "l'adresse physique n'est pas disponible pour linéaire 0x00801000". Comment puis-je le réparer?

[edit] Maintenant j'ai trouvé que je ne peux pas accéder aux données dans ce processus. par exemple quand je place "mov [pid_father], eax" avant "int 0x80", bochs se réinitialise. pourquoi c'est arrivé?

Répondre

1

Je pense que vous devez afficher le contenu de vos registres GDT et DS et de vos tables de pagination. Si vous voyez la triple erreur sur cette ligne sans le reste du code, cela impliquera que l'accès à [pid_father] est le problème. Le segment de données n'est pas valide ou la page est invalide ou marquée en lecture seule, ce qui provoque une exception GPF ou défaut de page. L'exception de GPF ou d'erreur de page échoue (peut-être pour la même raison, ou une autre), ce qui provoque une exception de double faute, qui à son tour fait échouer la CPU à tripler et à réinitialiser.

Bochs est généralement assez bon (de la mémoire) à l'impression pourquoi il a failli. Vous voudrez peut-être faire défiler un peu l'historique et chercher la première exception qui a été soulevée.

+0

Merci pour vos conseils, Stewart. –

+1

Le problème se localise dans la table de pages. Je n'ai pas défini l'indicateur inscriptible dans l'entrée de la table de pages correspondante. Donc, chaque fois que j'écris sur cette page, j'ai une erreur de protection. Lors de l'utilisation de l'instruction "ret" pour revenir du gestionnaire d'interruption, le sélecteur du segment de code est 0x10 qui est le sélecteur de code du noyau et le code de ce segment a droit à l'accès en lecture/écriture à n'importe quelle page. Ceci explique pourquoi le premier processus survient juste après avoir remplacé l'instruction "iret" par "ret". –

+0

Vraiment? Je pensais que la protection de page outrepassait la protection du sélecteur, de sorte que si les tables de pages sont marquées en lecture seule, la page est en lecture seule quel que soit le segment de code en cours. BTW - vous n'avez pas mentionné que vous avez activé la pagination. Cela aurait été utile à mentionner. – Stewart