Maison  >  Article  >  Tutoriel système  >  En savoir plus sur les processus : afficher les processus enfants, les informations sur les threads et les statuts courants

En savoir plus sur les processus : afficher les processus enfants, les informations sur les threads et les statuts courants

PHPz
PHPzoriginal
2024-07-25 08:00:14363parcourir

En savoir plus sur les processus : afficher les processus enfants, les informations sur les threads et les statuts courants

Questions et réponses

ps Afficher tous les processus enfants ? pstree-ppid

ps-eLf Quelle est la signification de chaque tableau ?

PID:process id 进程id
PPID: parent process id 父进程id
LWP:表示这是个线程;要么是主线程(进程),要么是线程
NLWP: num of light weight process 轻量级进程数量,即线程数量
TIME: 占用的CPU总时间
C CPU利用率,以整数表示。

Afficher le taux d'utilisation du processeur/la mémoire vidéo/la priorité et d'autres informations sur tous les threads en cours de processus ? top-H-p25120

Voyez sur quel processeur le thread s'exécute ? ps-eoruser,pid,ppid,lwp,psr,args-L|grepl3-agent

Statut du processus commun ?

-D:不可被唤醒的睡眠状态,通常用于 I/O 情况。
-R:该进程正在运行。
-S:该进程处于睡眠状态,可被唤醒。
-T:停止状态,可能是在后台暂停或进程处于除错状态。
-W:内存交互状态(从 2.6 内核开始无效)。
-X:死掉的进程(应该不会出现)。
-Z:僵尸进程。进程已经中止,但是部分程序还在内存当中。
-<:高优先级(以下状态在 BSD 格式中出现)。
-N:低优先级。
-L:被锁入内存。
-s:包含子进程。
-l:多线程(小写 L)。
-+:位于后台。

Six états du processus et son processus de conversion (cycle de vie) : état prêt, état d'exécution, état de sommeil profond, état de sommeil léger, état arrêté et état zombie.

Quels sont les processus mère-enfant partagés ? la différence est ? ——Après le fork, les processus mère et enfant partagent le descripteur de fichier et la zone de mappage construite par mmap. Les autres sont copiés, mais l'espace de processus et même l'adresse de processus du processus sont complètement les mêmes que ceux du processus parent, et ils le sont. espace complètement indépendant)

La différence entre fork et vfork - vfork est utilisé pour créer un nouveau processus, et le but du nouveau processus est d'exécuter un nouveau programme. Différence 1 : l'espace d'adressage du processus parent n'est pas copié dans le processus enfant. Différence 2 : vfork garantit que le processus enfant s'exécute en premier. Après avoir appelé exec ou (exit), l'exécution du processus parent peut être planifiée.

**La valeur de l'adresse de la mémoire vidéo partagée est-elle comprise dans la plage de l'espace de processus utilisateur ? **Après le fork, le processus enfant utilisera-t-il la même adresse que le processus parent ? S'il s'agit de processus différents, les adresses affichées dans l'espace de processus de la mémoire vidéo partagée sont-elles les mêmes ?

Le cycle de vie du processus, l'état prêt et l'état en cours d'exécution sont numériquement égaux et sont définis par la macro TASK_RUNNING.

Comment Task_struct est-il géré sous Linux ?

Comprenez le processus zombie : il abandonne presque tout l'espace mémoire vidéo, n'a pas de code exécutable et ne peut pas être planifié. Il conserve uniquement une position dans la liste des processus (les ressources ont été libérées depuis longtemps et la structure Task_struct est toujours là). . Si son processus parent n'installe pas la fonction de traitement du signal SIGCHLD et appelle wait()/waitpid() pour attendre la fin du processus enfant et n'ignore pas explicitement le signal, alors il restera toujours dans l'état zombie. Le processus parent se termine, le processus d'initialisation prendra manuellement en charge ce processus enfant et le nettoiera dans la communauté LINUX. Il peut toujours être éliminé. Si le processus parent ne se termine pas, le processus enfant restera dans l'état zombie, c'est pourquoi il existe parfois de nombreux processus zombies dans le système. Les numéros de processus pouvant être utilisés par le système sont limités (cat/proc/sys/kernel/pid_max) Si un grand nombre de processus zombies sont formés, le système ne pourra pas former de nouveaux processus car il n'y a pas de processus disponible. Nombres.

Recyclage sous-processus :

Le processus parent attend la fin du processus enfant via wait/waitpid et d'autres fonctions, ce qui entraînera le blocage du processus parent. Si le processus parent est très occupé, vous pouvez utiliser la fonction signal pour installer un gestionnaire pour SIGCHLD car une fois le processus enfant terminé, le processus parent recevra le signal et pourra appeler wait dans le gestionnaire pour recycler. Si le processus parent ne se soucie pas de la fin du processus enfant, il peut utiliser le signal (SIGCHLD, SIG_IGN) pour informer le noyau qu'il n'est pas intéressé par la fin du processus enfant, une fois le processus enfant terminé, le noyau le recyclera. et n'envoie plus de messages au processus parent. Il existe également des moyens de signaler, c'est-à-dire que le processus parent bifurque un processus enfant, puis continue de fonctionner. De cette façon, le processus enfant est repris par init Une fois le processus enfant terminé, init le recyclera. Cependant, vous devez effectuer vous-même le recyclage des enfants.

Pourquoi le processus enfant entre-t-il dans l'état zombie après sa fin ? - Parce que le processus parent peut avoir besoin d'obtenir l'état de sortie et d'autres informations du processus enfant.

L'état zombie est-il un état par lequel chaque processus enfant doit passer ? - Tout processus enfant (sauf init) ne disparaît pas immédiatement après la sortie(), mais laisse une structure de données appelée processus zombie (Zombie) (il occupe de la mémoire vidéo ressources, c'est-à-dire qu'il y a toujours un enregistrement dans la table de processus), en attente du processus parent. Si le processus parent n'a pas le temps de traiter le processus enfant après exit(), vous pouvez alors utiliser la commande ps pour voir que l'état du processus enfant est "Z". Si le processus parent se termine avant la fin du processus enfant, le processus enfant sera repris par init. init traitera le processus enfant à l'état zombie en tant que processus parent.

Comment éliminer les processus zombies :

Réécrivez le processus parent et récupérez le corps du processus enfant après sa mort. La méthode spécifique consiste à accepter le signal SIGCHLD. Après la mort du processus enfant, le signal SIGCHLD est envoyé au processus parent. Une fois que le processus parent a reçu ce signal, il exécute la fonction waitpid() pour récupérer le cadavre du processus enfant. Ceci est basé sur le principe que même si le processus parent n'appelle pas wait, le noyau lui enverra un message SIGCHLD. Bien que le traitement par défaut soit de l'ignorer, si vous souhaitez répondre à ce message, vous pouvez définir une fonction de traitement. . Signal SIGCHLD : lorsque le processus enfant se termine, le processus parent recevra ce signal. Si le processus parent ne gère pas ce signal et n'attend pas le processus enfant, le processus enfant se termine et occupera une entrée dans la table des processus du noyau. À ce stade, le processus enfant est appelé processus zombie. Nous devrions éviter ce genre de situation (le processus parent soit ignore le signal SIGCHILD, soit l'attrape, soit attend le processus enfant qu'il génère, soit le processus parent se termine en premier, puis la fin du processus enfant est prise en charge manuellement par le processus d'initialisation).

La fonction exit() lorsque le processus se termine, alors quelles sont les terminaisons du thread ? ——Trois situations d'abandon de thread :

Le thread revient simplement de la fonction de démarrage et la valeur de retour est le code de sortie du thread. Les threads peuvent être annulés par d’autres threads du même processus. Le fil appelle pthread_exit.

Si vous n'attendez pas de thread et n'êtes pas intéressé par la valeur de retour du thread, vous pouvez définir le thread à l'état détaché et laisser le système récupérer manuellement les ressources qu'il occupe lorsque le thread se termine. Un thread ne peut pas appeler pthread_detach lui-même pour passer à l'état détaché. Il ne peut appeler pthread_detach que par d'autres threads.

pthread_cancel() permet à un thread d'annuler un autre thread spécifié par th.

Processus - la plus petite unité d'allocation de ressources, thread - la plus petite unité d'exécution de programme. Un processus a un espace d'adressage indépendant et un thread n'a pas d'espace d'adressage indépendant (les threads du même processus partagent l'espace d'adressage du processus après un crash d'un processus, cela n'affectera pas les autres processus en mode protégé, et un). le thread n’est qu’une partie d’un processus. Différents chemins d’exécution. Les threads ont leurs propres piles et variables locales, mais les threads n'ont pas d'espace d'adressage séparé. Si un thread raccroche, cela signifie que l'ensemble du processus s'est enfui. Par conséquent, les programmes multi-processus sont plus puissants que les programmes multi-thread, mais ils. consommer plus de ressources lors du changement de processus. Plus grand, moins efficace. Cependant, pour certaines opérations simultanées qui nécessitent une opération et un partage simultanés de variables individuelles, seuls les threads, et non les processus, peuvent être utilisés.

Raison d'utiliser le multi-threading ?

Processus

Le processus est l'unité de base de l'allocation des ressources et le thread est l'unité de base de la planification

Informations sur le processus

Le planificateur Linux identifie en fait task_struct pour la planification. Quel que soit le thread de processus, la couche inférieure correspond à une task_struct. La différence entre un processus et un thread est le nombre de ressources partagées entre les deux processus et toutes les ressources sont partagées entre les deux threads.

Bloc de contrôle de processus PCB (ProcessControlBlock)

task_struct est la description d'un processus par le noyau Linux, qui peut aussi être appelée « descripteur de processus ». Une description de la structure qui stocke toutes les ressources requises par le processus. /proc/${pid} informations relatives au processus. Pour le système d’exploitation, un processus est une structure de données.

struct task_struct {
longstate; // 进程状态-1为不可运行, 0为可运行, >0为已中断

struct mm_struct*mm; // 指向的是进程的虚拟内存,也就是载入资源和可执行文件的地方
	pid_t pid; // 进程标识符,用来代表一个进程
 
struct task_struct __rcu*parent; // 指向父进程的指针
struct list_headchildren; // 子进程列表
 	struct list_head sibling; // 兄弟进程
struct fs_struct*fs;// 存放文件系统信息的指针
 
struct files_struct *files; // 一个数组,包含该进程打开的文件指针
unsigned int policy; // 调度策略:一般有FIFO,RR,CFS
...
};

从2.6版本之后,Linux改用了slab分配器动态生成task_struct,只须要在栈底(向上下降的栈)或栈顶(向下下降的栈)创建一个新的结构structthread_info(这儿是栈对象的尾端),你可以把slab分配器觉得是一种分配和释放数据结构的优化策略。通过预先分配和重复使用task_struct,可以防止动态分配和释放带来的资源消耗。

进程的地址空间ref

所谓进程地址空间(processaddressspace),就是从进程的视角听到的地址空间,是进程运行时所用到的虚拟地址的集合。

进程的显存

程序段(Text):程序代码在显存中的映射,储存函数体的二补码代码。

初始化过的数据(Data):在程序运行初早已对变量进行初始化的数据。

未初始化过的数据(BSS):在程序运行初未对变量进行初始化的数据。

栈(Stack):储存局部、临时变量,函数调用时,储存函数的返回表针,用于控制函数的调用和返回。在程序块开始时手动分配显存,结束时手动释放显存,其操作方法类似于数据结构中的栈。

堆(Heap):储存动态显存分配,须要程序员手工分配,手工释放.注意它与数据结构中的堆是两码事,分配方法类似于数组。

注:1.Text,BSS,Data段在编译时早已决定了进程将占用多少VM

可以通过size,晓得这种信息:

正常情况下,Linux进程不能对拿来储存程序代码的显存区域执行写操作,即程序代码是以只读的形式加载到显存中,但它可以被多个进程安全的共享。

创建进程后都创建了什么资源

进程创建

system()通过调用shell启动一个新进程

exec()以替换当前进程映像的方法启动一个新进程

fork()以复制当前进程映像的方法启动一个新进程

fork(2)

执行fork后,父进程的task_struck对拷给子进程,母子进程最初资源完全一样,而且是两份不同的拷贝,因而任何改动都导致两者的分裂。

兄妹进程对显存资源(mm)的管理使用了COW(Copy-On-Write,写时拷贝)技术:

在fork之前,一片显存区对应一份数学地址和一份虚拟地址,显存区的权限为RW;在fork以后,母子进程听到的显存区虚拟地址相同,化学地址也相同,母女进程使用的虽然是同一片化学显存,未发生显存拷贝,操作系统会将此显存区权限改为RO;父或子进程对显存区执行写操作将触发PageFault,操作系统此时会将显存区拷贝一份,母女进程见到的虚拟地址仍旧一样,而且化学地址早已不同。各进程虚拟地址到化学地址的映射由MMU(MemoryManagementUnit,显存管理单元)管理。fork运行在有MMU的CPU上。

Bei CPUs ohne MMU ist es schwierig, COW und Support Fork anzuwenden. CPUs ohne MMU verwenden vfork zum Erstellen von Prozessen, und der übergeordnete Prozess blockiert immer, bis der untergeordnete Prozess beendet wird oder ausgeführt wird. Der wesentliche Unterschied zwischen vfork und fork besteht darin, dass die Mutter- und Kindprozesse in vfork denselben Videospeicherbereich gemeinsam nutzen.

Der Systemaufruf

fork(2) wird verwendet, um einen neuen Prozess zu erstellen, einen sogenannten untergeordneten Prozess, der gleichzeitig mit dem übergeordneten Prozess ausgeführt wird (gleichzeitig) und dessen Ausführungsreihenfolge ungewiss ist (asynchron). pid_t ist eine Makrodefinition, ihr Wesen ist int. Bei Erfolg gibt sie zwei Werte zurück, der untergeordnete Prozess gibt 0 zurück und der übergeordnete Prozess gibt die untergeordnete Prozess-ID zurück, andernfalls wird ein Fehler zurückgegeben

Der gesamte virtuelle Adressraum des übergeordneten Prozesses wird in den untergeordneten Prozess kopiert, einschließlich des Status der Mutex-Sperre,

Der untergeordnete Prozess ist bis auf die folgenden Punkte genau derselbe wie der übergeordnete Prozess:

Prozessrecycling von wait() und waitpid()

Recyceln Sie die task_struct-Struktur des untergeordneten Prozesses über waitpid()/wait().

Unterschied:

Waisenprozesse und Zombieprozesse Zombieprozesse

Zombie-Prozess: Ein Prozess verwendet fork, um einen untergeordneten Prozess zu erstellen, und der übergeordnete Prozess ruft nicht wait oder waitpid auf, um die Statusinformationen des untergeordneten Prozesses abzurufen das System. Diese Prozesse werden Zombie-Prozesse genannt. (Der untergeordnete Prozess kann über /proc/$pid gesehen werden, der Thread jedoch nicht)

Wenn ein Prozess den Exit-Befehl aufruft, um sein Leben zu beenden, obwohl er nicht wirklich zerstört wird, hinterlässt er eine Datenstruktur namens Zombie-Prozess (Zombie) (das System ruft Exit auf, seine Funktion besteht darin, den Prozess zum Beenden zu bringen, aber es beschränkt sich nur darauf, einen normalen Prozess in einen Zombie-Prozess umzuwandeln, und kann ihn nicht vollständig zerstören.

Im Status von Linux-Prozessen ist der Zombie-Prozess eine ganz besondere Art. Er hat bereits fast den gesamten Videospeicherplatz aufgegeben, verfügt über keinen ausführbaren Code und kann nicht geplant werden. Er behält nur eine Position in der Prozessliste um den Status des Prozesses aufzuzeichnen und andere Informationen können von anderen Prozessen erfasst werden. Darüber hinaus belegt der Zombie-Prozess keinen Videospeicherplatz mehr. Es benötigt seinen übergeordneten Prozess, um die Leiche für ihn einzusammeln.

Wenn der übergeordnete Prozess die SIGCHLD-Signalverarbeitungsfunktion nicht installiert und wait oder waitpid() aufruft, um auf das Ende des untergeordneten Prozesses zu warten, und das Signal nicht explizit ignoriert, bleibt er weiterhin im Zombie-Status Wenn der Prozess zu diesem Zeitpunkt endet, übernimmt der Init-Prozess manuell diesen Unterprozess und sammelt seine Leiche ein, und er kann trotzdem entfernt werden.

Und wenn der übergeordnete Prozess eine Schleife ist und nicht beendet wird, bleibt der untergeordnete Prozess weiterhin im Zombie-Zustand. Aus diesem Grund gibt es manchmal viele Zombie-Prozesse im System. Die Prozessnummern, die vom System verwendet werden können, sind begrenzt. Wenn eine große Anzahl von Zombie-Prozessen gebildet wird, kann das System keine neuen Prozesse bilden, da keine Prozessnummern verfügbar sind.

Ursache des Zombie-Prozesses: Nachdem der untergeordnete Prozess beendet wurde, sendet er das SIGCHLD-Signal an den übergeordneten Prozess, und der übergeordnete Prozess ignoriert es standardmäßig. Der übergeordnete Prozess ruft nicht die Funktion wait() oder waitpid() auf, um auf das zu warten Ende des Kindprozesses. Möglichkeiten, Zombie-Prozesse zu verhindern: Der übergeordnete Prozess ruft wait()/waitpid() auf, um auf das Ende des untergeordneten Prozesses zu warten. Auf diese Weise wird der übergeordnete Prozess normalerweise im Wartezustand blockiert und kann keine anderen Dinge verarbeiten. Erfassen Sie das SIGCHLD-Signal und rufen Sie die Wartefunktion für die Signalverarbeitungsfunktion auf. Diese Verarbeitung kann das in 1 beschriebene Problem verhindern. Zweimal verzweigen, der Elternprozess erstellt einen Vaterprozess und der Vaterprozess erstellt einen Sohnprozess. Danach begeht der Mutterprozess Selbstmord und der Sohnprozess wird zu einem Waisenprozess und wird vom Init-Prozess übernommen. Waisenprozess

Verwaister Prozess: Der übergeordnete Prozess wird beendet, aber einer oder mehrere seiner untergeordneten Prozesse werden noch ausgeführt, sodass diese untergeordneten Prozesse zu verwaisten Prozessen werden. Verwaiste Prozesse werden vom Init-Prozess (pid=1) aufgenommen und der Init-Prozess führt die Statuserfassung für sie durch. (Wenn ein verwaister Prozess im System erscheint, bedeutet das, dass der Hauptprozess die untergeordneten Prozesse vor dem Beenden nicht gelöscht hat)

Thread (LightweightProcess, LWP)

同一进程的多个线程获取进程ID时得到的是惟一ID值。Linux同一进程的多线程,在内核视角实际上每位线程都有一个PID,但在用户空间须要getpid()返回惟一值,Linux使用了一个小方法,引入了TGID的概念linux进程与线程 内核,getpid()返回的的TGID值。

pthread_create()

Linux线程本质上就是进程,只是与进程间资源共享方法不同,线程间共享所有资源。每位线程都有自己的task_struct,因而每位线程都可被CPU调度。多线程间又共享同一进程资源。

在一个线程中创建了另外一个线程,主线程要等到创建的线程返回了,获取该线程的返回值后主线程才退出。这个时侯就须要用到线程挂起。pthread_join函数用于挂起当前线程,直到指定的线程中止为止。

说线程的PID,是指用户空间的进程ID,值就是TGID(threadgroupIDforthethreadgroupleader);当非常强调,线程在内核空间的PID,则指线程在内核中task_struct里特有的PID。top–H命令从线程视角显示CPU占用率。不带参数的top命令,进程ID是主线程的PID(也就是TGID)。

Linux的进程和线程

进程是处于运行期的程序和相关资源的统称,具备一些要素:

拥有一段可执行程序代码。如同一场戏须要一个剧本。代码段可以多个进程共用,如同许多场表演都可以用一份剧本一样。拥有一段进程专用的系统堆栈空间。可以觉得是这个进程的“私有财产”,相应的,也肯定有系统空间堆栈在系统中有进程控制块(或称进程描述符,本文两种说法通用)描述这个进程的相关信息。可以觉得是进程的“户口”。系统通过这个控制块来控制进程的相关行为有独立的储存空间,也就是专有的用户空间,相应的又会有用户空间堆栈。理解各类ID

# ps -eo ppid,pid,tid,lwp,tgid,pgrp,sid,tpgid,args -L | awk &#039;{if(NR==1) print $0; if($9~/a.out/) print $0}&#039;
 PPID PID TID LWPTGIDPGRP SID TPGID COMMAND
 579046 2436128 2436128 2436128 2436128 2436128579046 2436128 ./a.out
 579046 2436128 2436129 2436129 2436128 2436128579046 2436128 ./a.out
 579046 2436128 2436130 2436130 2436128 2436128579046 2436128 ./a.out

pidstat-t[-ppid号]可以复印出线程之间的关系。

各类ID最后都归结到pid和lwp(tid)上。所以理解各类ID,最终归结为理解pid和lwp(tid)的联系和区别。

PID:进程ID。

LWP:线程ID。在用户态的命令(例如ps)中常用的显示方法。

TID:线程ID,等于LWP。TID在系统提供的插口函数中更常用,例如syscall(SYS_gettid)和syscall(__NR_gettid)。

TGID:线程组ID,也就是线程组leader的进程ID,等于PID。

pgid(processgroupID):进程组ID,也就是进程组leader的进程ID。

pthreadid:pthread库提供的ID,生效范围不在系统级别,可以忽视。

sid:sessionIDforthesessionleader。

TPGID:ttyprocessgroupIDfortheprocessgroupleader。

上图挺好地描述了用户视角(userview)和内核视角(kernelview)看见线程的差异:

轮询

Polling (Thread auf Benutzerebene), der für den Kernel transparent ist, d. h. das System weiß nicht, ob Polling vorhanden ist. Es wird vollständig vom Benutzerprogramm selbst geplant Es ist schwierig, die Belegungsplanung zu mögen, wodurch die CPU-Steuerung gezwungen wird, auf andere Prozesse/Threads umzuschalten. Im Allgemeinen kann nur eine kooperative Planung durchgeführt werden. Nachdem die Abfrage selbst die Steuerung aktiv verkauft hat, können andere Abfragen ausgeführt werden.

Der Unterschied zwischen Goroutine und Interpreter

Im Wesentlichen ist Goroutine eine Umfrage. Der Unterschied besteht darin, dass Golang die Goroutine-Planung in vielen Aspekten wie Laufzeit und Systemaufrufen kapselt und verarbeitet. Wenn es auf langfristige Ausführung oder Systemaufrufe stößt, wird die CPU (P) der aktuellen Goroutine aktiv verkauft Geplante und ausgeführte Linux-Betriebs- und Wartungsrekrutierung, dh Golang unterstützt den Dolmetscher auf Sprachebene.

Unterschiedliche Prozessplanung in anderen Aspekten

Drei Hauptplanungsstrategien des Linux-Kernels:

1, SCHED_OTHER Time-Sharing-Planungsstrategie,

2, SCHED_FIFO Echtzeit-PlanungsstrategieLinux-Prozess und Thread-Kernel, wer zuerst kommt, mahlt zuerst

3, SCHED_RR Echtzeit-Planungsstrategie, Zeitscheibenrotation

Prozessplanung in Echtzeit

SCHED_FIFO: Verschiedene Prioritäten werden entsprechend der höheren Priorität in den Ruhezustand versetzt und dann gemäß der niedrigeren Priorität ausgeführt.

SCHED_RR: Verschiedene Prioritäten werden entsprechend der höheren Priorität in den Ruhezustand versetzt und dann entsprechend der niedrigeren Prioritätsrotation ausgeführt.

Kernel RT-Patch:

Die folgenden zwei Parameter

/proc/sys/kernel/sched_rt_period_us

/proc/sys/kernel/sched_rt_runtime_us

Zeigt an, dass RT während des Zeitraums nur bis zur Laufzeit laufen kann

Normale Prozessplanung

SCHED_OTHER:

CFS: Completely Fair Scheduling (neuer Kernel)

Schwarze Mangrove, der Wert des rechten Knotens ist größer als der Wert des linken Knotens

Führen Sie den bisher kleinsten Prozess von vruntime aus

Unter Berücksichtigung von CPU/IO und nett

Finden Sie immer den Thread-Zeitplan mit der kleinsten Laufzeit.

vruntime=Pruntime/Gewicht×1024;

Vruntime ist die virtuelle Laufzeit, Pruntime ist die chemische Laufzeit und das Gewicht wird durch den Nice-Wert bestimmt (je niedriger der Nice-Wert, desto höher das Gewicht. Threads mit kürzerer Laufzeit und niedrigeren Nice-Werten werden kleiner). vruntime und wird für die Planung priorisiert. Dabei handelt es sich um einen Prozess, der sich im Betrieb dynamisch verändert.

Kernelraum und Benutzerraum Kernelraum und Benutzerraum

Der virtuelle Adressraum von Linux reicht von 0 bis 4G. Der Linux-Kernel teilt diesen 4G-Byteraum in zwei Teile, und das höchste 1G-Byte (von der virtuellen Adresse 0xCxC0000000 bis 0xFFFFFFFF) wird vom Kernel verwendet, der als „Kernelraum“ bezeichnet wird " ". Die unteren 3G-Bytes (von der virtuellen Adresse 0x00000000 bis 0xBFFFFFFF) werden von jedem Prozess verwendet und als „Benutzerraum“ bezeichnet. Da jeder Prozess über Systemaufrufe in den Kernel eintreten kann, wird der Linux-Kernel von allen Prozessen im System gemeinsam genutzt. . Also, Aus einer bestimmten Prozessperspektive kann jeder Prozess über 4 GByte virtuellen Speicherplatz verfügen

.

Linux verwendet einen zweistufigen Schutzmechanismus: Stufe 0 wird vom Kernel verwendet, und Stufe 3 wird von Benutzerprogrammen verwendet. Jeder Prozess verfügt über seinen eigenen privaten Benutzerbereich (0 ~ 3G). Dieser Bereich ist für andere Prozesse im Das höchste 1 GB virtueller Kernel-Speicherplatz wird von allen Prozessen und dem Kernel gemeinsam genutzt.

Der Kernel-Space speichert Kernel-Code und -Daten, während der User-Space des Prozesses den Code und die Daten des Benutzerprogramms speichert. Ob Kernel-Space oder User-Space, sie befinden sich alle im virtuellen Raum. Tatsächlich belegt der Kernelraum das höchste 1-GB-Byte jedes virtuellen Raums, wird jedoch immer ab der niedrigsten Adresse (0x00000000) dem chemischen Speicher zugeordnet. Darüber hinaus kann die Verwendung virtueller Adressen den Kernelraum wirksam vor Zerstörung schützen nach Benutzerraum Der chemische Adresskonvertierungsprozess wird vom Betriebssystem und der CPU gemeinsam durchgeführt (das Betriebssystem legt die Seitentabelle für die CPU fest und die CPU führt die Adresskonvertierung über die MMU-Einheit durch).

Hinweis: Jeder Prozess im Multitasking-Betriebssystem läuft in seiner eigenen Videospeicher-Sandbox. Im 32-Bit-Modus handelt es sich immer um eine 4-GB-Videospeicheradresse. Diese virtuelle Adresse wird dem chemischen Speicher über eine Seitentabelle (Pagetable) zugeordnet, die vom Betriebssystem verwaltet und vom Prozessor referenziert wird. Jeder Prozess verfügt über einen eigenen Satz Seitentabellen.

Die Verteilung des Prozessspeicherplatzes wird rechts angezeigt:

Videospeicher

Der Haufen geht runter und der Stapel steigt (warum ist meiner umgekehrt???)

Die absteigende Richtung und Big- und Small-Endianness von Stapel und Speicher

Low->|----------------|

|Globale Mengen (alle initialisierten Mengendaten, |

|Uninitialisierte Menge.bss)|

Start des Heaps->|----------------|

|Der Heap sinkt in Richtung der hohen Adresse|

||

||

|Freier Speicherplatz|

||

||

|Der Stapel bewegt sich nach unten zur unteren Adresse|

Beginn des High Stack->|----------------|

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn