Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Bagaimana untuk menyelesaikan ralat \"EINVAL\" apabila memasuki ruang nama pelekap dalam Go?

Bagaimana untuk menyelesaikan ralat \"EINVAL\" apabila memasuki ruang nama pelekap dalam Go?

Susan Sarandon
Susan Sarandonasal
2024-11-02 08:54:02587semak imbas

How to resolve the

Memasuki Ruang Nama Gunung dalam Go

Isu:

Dalam Go, panggilan setns mengembalikan EINVAL (argumen tidak sah) apabila cuba memasuki ruang nama pelekap untuk bekas.

Penjelasan:

Untuk memasukkan ruang nama menggunakan setns, panggilan mesti dibuat daripada konteks satu utas sebelum urutan masa jalan Go bermula.

Penyelesaian:

Terdapat dua pendekatan untuk 解决isu ini:

1. Menggunakan Trik Pembina:

  • Tambahkan makro __attribute__((pembina)) pada fungsi C yang memanggil setns sebelum Go bermula.
  • Kod Go yang diubah suai:
<code class="go">/*
#include <sched.h>
#include <stdio.h>
#include <fcntl.h>

__attribute__((constructor)) void enter_namespace(void) {
   setns(open("/proc/<PID>/ns/mnt", O_RDONLY, 0644), 0);
}
*/
import "C"</code>

2. Menggunakan syscall.RawSyscall:

  • Pastikan panggilan setns dibuat dalam utas utama sebelum memulakan urutan masa jalan Go.
  • Gunakan runtime.LockOSThread untuk mengunci utas utama jika perlu.
<code class="go">package main

import (
    "fmt"
    "os"
    "path/filepath"
    "syscall"
    "runtime"
)

func main() {
    if syscall.Geteuid() != 0 {
        fmt.Println("abort: you want to run this as root")
        os.Exit(1)
    }

    if len(os.Args) != 2 {
        fmt.Println("abort: you must provide a PID as the sole argument")
        os.Exit(2)
    }

    // Lock the main thread to the OS thread
    runtime.LockOSThread()

    namespaces := []string{"ipc", "uts", "net", "pid", "mnt"}

    for i := range namespaces {
        fd, _ := syscall.Open(filepath.Join("/proc", os.Args[1], "ns", namespaces[i]), syscall.O_RDONLY, 0644)
        err, _, msg := syscall.RawSyscall(308, uintptr(fd), 0, 0) // 308 == setns

        if err != 0 {
            fmt.Println("setns on", namespaces[i], "namespace failed:", msg)
        } else {
            fmt.Println("setns on", namespaces[i], "namespace succeeded")
        }

    }
}</code>

Nota:

  • Pastikan kernel anda menyokong berbilang ruang nama dengan menyemak /proc/sys/kernel/namespaces_allowed.
  • Tampalan kernel yang dipetik dalam dokumentasi menyatakan bahawa proses mesti mempunyai CAP_SYS_ADMIN dalam ruang nama pelekap sasaran. Pastikan syarat ini dipenuhi sebelum cuba memanggil setns.

Atas ialah kandungan terperinci Bagaimana untuk menyelesaikan ralat \"EINVAL\" apabila memasuki ruang nama pelekap dalam Go?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn