Der Prozess ist eine Abstraktion der Logik. Wir haben viel Verständnis für den Prozess aus Betriebssystembüchern, aber wir wissen möglicherweise nicht viel über die Implementierung In diesem Artikel wird versucht, die allgemeinen Prinzipien der Prozessimplementierung zu erläutern.
Die Implementierung des Prozesses ist tatsächlich die gleiche wie beim normalen Schreiben von Code. Wenn wir beispielsweise etwas darstellen möchten, definieren wir eine Datenstruktur. Prozesse sind keine Ausnahme. Das Wesen eines Prozesses ist also eine Datenstruktur, die eine Reihe von Daten speichert. Das Betriebssystem verwaltet alle Prozesse in Form von Arrays oder verknüpften Listen. Man kann sagen, dass Prozesse in zwei Typen unterteilt werden können:
1 Der erste Prozess, wenn das System initialisiert wird,
2 Mit Ausnahme des ersten Prozesses werden andere Prozesse durch Fork- oder Fork+Execute-Systemaufrufe erstellt.
Schauen wir uns zunächst an, welche Informationen die Prozessstruktur enthält.
Wenn das System einen Prozess erstellt, wird der Wert des cs:ip-Registers festgelegt fork, then ip Dies ist die IP-Adresse der Anweisung nach der Fork-Funktion. Bei der Ausführung wird die IP-Adresse vom Compiler angegeben. Egal was passiert, wenn der Prozess mit der Ausführung beginnt, analysiert die CPU cs:ip und erhält eine Anweisung zur Ausführung. Wie wird cs:ip analysiert?
Wenn der Prozess ausgeführt wird, wird der TSS-Selektor (GDT-Index) in das TSS-Register geladen, und dann wird der Kontext in TSS auch in das entsprechende Register geladen, z. B. CR3, LDT-Selektor. Suchen Sie anhand des LDT-Index in den TSS-Informationen zunächst die erste Adresse der Prozess-LDT-Strukturdaten von GDT und rufen Sie dann den Selektor von cs gemäß den Attributen des aktuellen Segments ab, z. B. dem Codesegment erste Adresse des linearen Prozessraums aus der LDT-Tabelle Adresse, Längenbeschränkung, Berechtigungen und andere Informationen. Verwenden Sie die erste Adresse der linearen Adresse plus den Offset in der IP, um die lineare Adresse zu erhalten, und ermitteln Sie dann die physische Adresse über das Seitenverzeichnis und die Seitentabelle. Wenn die physische Adresse nicht zugewiesen wurde, werden Seitenfehlerausnahmen und andere Verarbeitungen ausgeführt durchgeführt werden.
Prozessunterbrechung, -blockierung und mehrere Prozesse. Normalerweise hören wir diese Konzepte ziemlich oft. Sehen wir uns nun an, wie sie umgesetzt werden. Es gibt zwei Arten der Prozessunterbrechung oder -blockierung.
1 Aktiv pausieren. Lassen Sie den Prozess zeitweise während des Schlafs hängen. Das Prinzip des Schlafs wurde bereits analysiert, daher werde ich es nicht noch einmal analysieren. Das allgemeine Prinzip besteht darin, einen Timer einzustellen und den Prozess nach Ablauf aufzuwecken.
Ändern Sie den Prozess in einen angehaltenen Zustand und warten Sie auf das Aufwecken.
2 Passive Federung.
Es gibt viele Szenarien für eine passive Unterbrechung. Der Hauptgrund ist, dass der Prozess eine Ressource anwendet, die Ressource jedoch die Bedingungen nicht erfüllt und der Prozess vom Betriebssystem angehalten wird. Zum Beispiel, wenn wir eine Pfeife lesen. Wenn keine Daten aus der Pipe gelesen werden können, wird der Prozess angehalten. In die Warteschlange der Pipe einfügen.
<code>// 当前进程挂载到睡眠队列p中,p指向队列头指针的地址<br>void sleep_on(struct task_struct **p)<br>{<br> struct task_struct *tmp;<br><br> if (!p)<br> return;<br> if (current == &(init_task.task))<br> panic("task[0] trying to sleep");<br> /*<br> *p为第一个睡眠节点的地址,即tmp指向第一个睡眠节点<br> 头指针指向当前进程,这个版本的实现没有采用真正链表的形式,<br> 他通过每个进程在栈中的临时变量形成一个链表,每个睡眠的进程,<br> 在栈里有一个变量指向后面一个睡眠节点,然后把链表的头指针指向当前进程,<br> 然后切换到其他进程执行,当被wake_up唤醒的时候,wake_up会唤醒链表的第一个<br> 睡眠节点,因为第一个节点里保存了后面一个节点的地址,所以他唤醒后面一个节点,<br> 后面一个节点以此类推,从而把整个链表的节点唤醒,这里的实现类似nginx的filter,<br> 即每个模块保存后面一个节点的地址,然后把全局指针指向自己。<br> */<br> tmp = *p;<br> *p = current;<br> // 不可中断睡眠只能通过wake_up唤醒,即使有信号也无法唤醒<br> current->state = TASK_UNINTERRUPTIBLE;<br> // 进程调度<br> schedule();<br> // 唤醒后面一个节点<br> if (tmp)<br> tmp->state=0;<br>}<br><br>// 唤醒队列中的第一个节点,并清空链表,因为第一个节点会向后唤醒其他节点<br>void wake_up(struct task_struct **p)<br>{<br> if (p && *p) {<br> (**p).state=0;<br> *p=NULL;<br> }<br>}</code>
Das obige ist der detaillierte Inhalt vonbedeuten? Bitte geben Sie mehr Kontext an.. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!