Linux - Schauen Sie sich copy_mm () an

Tux_Enhanced.svg.png

Überblick

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

Threads und Prozesse unter Linux

Grüner Faden / nativer Faden

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)

(Nebenbei) Die Geschichte des Thread-Modells

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.

Ich habe mir die Kernelquelle angesehen

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(&current->thread.regs.regs);
	current->thread.forking = 1;
	ret = do_fork(clone_flags, newsp, &current->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.)

Ergänzung

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

Referenz

Recommended Posts

Linux - Schauen Sie sich copy_mm () an
Spielen Sie mit Linux-Partitionen herum ~ Fortsetzung ~