text: Kernel-Thread und normale Threads
  Thema: Kernel-Thread und normale Threads
  Autor Thema: Kernel-Thread und normale Threads (Gelesen 3140 mal)
  « am: 20. January 2011, 22:15 »
  ich habe mal eine Frage zu den Unterschieden zwischen den beiden Threadarten.
  Zum einen muss ich die Register (cs,ss) unterschiedlich setzen.
  Der Kernel-Thread braucht auch seinen eigenen Stack, oder?
  Kann ich den genau so laden, wie einen normalen Stack, also über esp = stack in meinem CPU dump?
  « Antwort #1 am: 20. January 2011, 22:24 »
  Re:Kernel-Thread und normale Threads
  ja klar ob der Task/Thread/Prozess im Ring0 oder eins läuft ist egal. nur die segmentregister müssen, wie du schon richtig sagtest auf die richtiges Diskriptoren zeigen.
  « Antwort #2 am: 20. January 2011, 22:40 »
  Ohne Ringwechsel ändert iret den Stack nicht. Wenn du das also haben willst, musst du das für diesen Fall von Hand machen. In der Regel kannst du aber auch einfach den normalen Kernelstack des Threads benutzen.
  « Antwort #3 am: 20. January 2011, 23:40 »
  Kann ich so ohne weiteres alle auf einem Stack arbeiten lassen?
  Kommt es dann nicht vor, dass die Threads ihre Stacks zerstören?
  « Antwort #4 am: 21. January 2011, 09:36 »
  Jeder Thread muss dann natürlich trotzdem seinen eigenen Kernelstack haben.
  Ich bin davon ausgegangen, dass du das bei Ring-3-Tasks auch schon machst. Unbedingt notwendig ist wohl nur ein Kernelstack pro CPU, wenn man den Zustand woanders hin sichert, insofern ist diese Annahme möglicherweise falsch.
  « Antwort #5 am: 21. January 2011, 11:16 »
  Gut, dann habe ich dich richtig verstanden.
  Da ich den Zustand immer auf dem Stack sichern möchte, muss also auch jeder Kernel-Thread seinen eigenen Stack bekommen.
  Den muss ich dann händich kurz vor dem Rücksprung manuell setzen, oder?
  « Antwort #6 am: 21. January 2011, 11:22 »
  Wenn du den Zustand auf den Stack sicherst, hast du doch sowieso schon einen Stack pro Thread vorgesehen. Dann brauchst du den Stack nicht zu wechseln. Der Interrupt legt die Rücksprunginformationen auf den Stack, iret nimmt sie wieder runter. Das ist einfach nur ein besserer Funktionsaufruf.
  « Antwort #7 am: 21. January 2011, 11:30 »
  Aber du meintest doch, dass das nicht bei Kernel-Threads gilt, oder?
  So wie ich dich verstanden habe, macht die CPU das nur, wenn in einen anderen Ring gewechselt wird. stimmt das so?
  « Antwort #8 am: 21. January 2011, 11:44 »
  Die CPU macht nur bei einem Ringwechsel auch einen Stackwechsel, ja. (cs, eip und eflags werden natürlich trotzdem auf den Stack gesichert, nur ss und esp nicht) Der springende Punkt ist, dass du den Stackwechsel sowieso nur aus Sicherheitsgründen brauchst (Ring-3-Code auf den Kernelstack schreiben lassen, oder das vom Kernel benutzte esp ändern lassen? Lieber nicht.) und das bei Ring-0-Code nicht der Fall ist, weil der sowieso alle Rechte hat.
  Du kannst also einfach denselben Stack für den Kernel (im Sinn von Interrupthandlern usw.) und Ring-0-Thread benutzen und musst gar nichts wechseln.
  « Antwort #9 am: 21. January 2011, 11:55 »
  Aber die Kernel-Threads legen doch lokale Variablen auf den Stack, oder?
  Muss ich dann nicht noch mehr beachten oder mache ich mir umsonst sorgen?
  Was ich vllt vergessen habe zu sagen ist, dass meine Kernel-Threads präemptiv werden.
  Der ganze Kernel soll präemptiv sein.
  « Antwort #10 am: 21. January 2011, 12:18 »
  Zitat von: rizor am 21. January 2011, 11:55
  Ja, natürlich. Aber das stört doch nicht.
  Nehmen wir an, wir sind in einem Ring-0-Task und es kommt ein IRQ rein. Im Moment sind irgendwelche Variablen auf dem Stack. Die CPU legt cs, eip und eflags auf den Stack und springt zum ISR. Der ISR speichert den Prozessorzustand auf den Stack und macht irgendwelches Zeug, das den Task wechselt. An dieser Stelle führst du manuell einen Stackwechsel von einem Kernelstack auf den anderen durch (das gleiche machst du bei den Usertasks auch). Irgendwann später kommt unser Task wieder zum Zug und esp wird wieder auf den unseren Kernelstack gesetzt. Der Zustand wird vom Stack wiederhergestellt, das iret nimmt eflags, eip und cs vom Stack und wir haben wundersamerweise wieder unsere lokale Variable oben auf dem Stack.
  Was du nicht gemacht hast, ist beim Interrupt auf einen gesonderten Kernelstack und beim iret auf einen Userstack zu wechseln.