Ich habe es gelesen, um ein Gefühl für den Unterschied zwischen Multi-Prozess / Thread zu bekommen, also habe ich es zusammengefasst. Lesen Sie 5.4 für die Version zu sehen torvalds/linux
Von virtuellen Maschinen geplante Threads, nicht vom Betriebssystem. Emulieren Sie eine Multithread-Umgebung unabhängig von der Betriebssystemfunktionalität.
Der OS-Scheduler plant die Thread-Ausführung (Kann mit -L im Befehl ps angezeigt werden)
M: N-Thread ist ein asymmetrisches Thread-Modell, bei dem der Kernel-Thread M und der Benutzer-Thread N ist. Funktioniert durch Zuordnen mehrerer Kernel-Threads zu mehreren Benutzer-Threads Es scheint, dass Golang dies nutzt und die Switch-Kosten sehr niedrig sind.
Grundsätzlich rufen sowohl fork (2) als auch pthred_create () intern do_fork () auf. Der Klon ruft do_fork auf, nachdem er aufgerufen wurde. Es scheint, dass der Unterschied zwischen Prozess- und Thread-Erstellung durch den Unterschied im Flag beim Aufrufen von do_fork () unterschieden wird.
long sys_clone(unsigned long clone_flags, unsigned long newsp,
void __user *parent_tid, void __user *child_tid)
{
long ret;
if (!newsp)
newsp = UPT_SP(¤t->thread.regs.regs);
current->thread.forking = 1;
ret = do_fork(clone_flags, newsp, ¤t->thread.regs, 0, parent_tid,
child_tid);
current->thread.forking = 0;
return ret;
}
Überblick über den Verarbeitungsablauf
① do_fork() ② _do_fork() ③ copy_process() ④ copy_mm() ⑤ dup_mmap () (Wenn es sich nicht um LWP handelt, verarbeiten Sie die Kuh unten) ⑥ copy_page_range() ⑦ copy_one_pte () Kopieren Sie den VM-Bereich von einer Aufgabe in eine andere
static int copy_mm(unsigned long clone_flags, struct task_struct *tsk)
{
struct mm_struct *mm, *oldmm;
int retval;
tsk->min_flt = tsk->maj_flt = 0;
tsk->nvcsw = tsk->nivcsw = 0;
#ifdef CONFIG_DETECT_HUNG_TASK
tsk->last_switch_count = tsk->nvcsw + tsk->nivcsw;
tsk->last_switch_time = 0;
#endif
tsk->mm = NULL;
tsk->active_mm = NULL;
oldmm = current->mm;
if (!oldmm)
return 0;
//Initialisierung des vmacache-Eintrags
vmacache_flush(tsk);
// CLONE_Wenn eine VM konfiguriert ist, werden der aufrufende Prozess und die untergeordneten Prozesse ausgeführt
//Es läuft im selben Speicherplatz.
if (clone_flags & CLONE_VM) {
mmget(oldmm);
//Stellen Sie mm des übergeordneten Prozesses auf untergeordnet und gut ein_Zu mm
mm = oldmm;
goto good_mm;
}
retval = -ENOMEM;
// CLONE_Duplizieren Sie die vorhandene mm-Struktur, wenn die VM nicht festgelegt ist
mm = dup_mm(tsk, current->mm);
if (!mm)
goto fail_nomem;
good_mm:
tsk->mm = mm;
tsk->active_mm = mm;
return 0;
fail_nomem:
return retval;
}
Der Prozess von copy_mm wird nach Klon (2) aufgerufen. Es stellt sich heraus, dass CLONE_VM, wenn es gesetzt ist (Flag beim Erstellen des Threads), eine Adresse mit dem übergeordneten Prozess teilt. https://linuxjm.osdn.jp/html/LDP_man-pages/man2/clone.2.html
static struct mm_struct *dup_mm(struct task_struct *tsk,
struct mm_struct *oldmm)
{
struct mm_struct *mm;
int err;
mm = allocate_mm();
if (!mm)
goto fail_nomem;
//Kopieren Sie den Speicher des übergeordneten Prozesses in den generierten Prozess
memcpy(mm, oldmm, sizeof(*mm));
if (!mm_init(mm, tsk, mm->user_ns))
goto fail_nomem;
err = dup_mmap(mm, oldmm);
if (err)
goto free_pt;
mm->hiwater_rss = get_mm_rss(mm);
mm->hiwater_vm = mm->total_vm;
if (mm->binfmt && !try_module_get(mm->binfmt->module))
goto free_pt;
return mm;
free_pt:
/* don't put binfmt in mmput, we haven't got module yet */
mm->binfmt = NULL;
mm_init_owner(mm, NULL);
mmput(mm);
fail_nomem:
return NULL;
}
Die Hauptverarbeitung von copy_mm. Wenn CLONE_VM (Thread) zum Zeitpunkt des vorherigen Prozesses festgelegt wurde, wird dieser Prozess nicht ausgeführt. Threads können auf die Daten zugreifen, aus denen sie erstellt wurden. Im Fall eines Prozesses wird der Prozess des Kopierens des Speichers des übergeordneten Prozesses ausgeführt. (Wird später beschrieben.)
mm_struct - Struktur, die Adressrauminformationen verwaltet
Artikel | Überblick |
---|---|
mmap | vm_area_Halten Sie den Anfang der Struktur |
mm_rb | Rot für die schnelle Suche im Speicherbereich-Halte einen schwarzen Baum |
mmap_cache | Lokale Rohspeicherreferenz(locality)Beschleunigen durch Ausnutzen |
mm_count | Referenzzähler für diese Struktur. Bei 0 wird kein Objekt angezeigt |
mm_list | mm_struct Feld zum Erstellen einer Liste von Strukturen |
start_code, end_code | Start- und Endadressen des Textsegments |
start_brk, brk | Heap-Start- und Endadressen |
start_stack | Startadresse des Stapels |