msantos / embedexe

Run an executable embedded in a Go binary
ISC License
5 stars 0 forks source link

support mac system with following solution #1

Open fastfading opened 4 months ago

fastfading commented 4 months ago

memfd_create 是 Linux 特有的系统调用,用于创建一个匿名文件,该文件驻留在内存中。由于它是 Linux 特有的,在 macOS 上没有直接等效的功能。不过,可以使用其他方法来实现类似的功能,例如使用 mmapshm_open。以下是一些在 macOS 上的替代方案:

使用 mmap

mmap 可以在内存中创建一个匿名映射,可以用于创建临时的内存文件。

package main

import (
    "fmt"
    "os"
    "syscall"
    "unsafe"
)

func createMemfd(size int) ([]byte, error) {
    fd, err := syscall.MemfdCreate("memfd", syscall.MFD_CLOEXEC)
    if err != nil {
        return nil, err
    }

    // Resize the memory file
    if err := syscall.Ftruncate(fd, int64(size)); err != nil {
        syscall.Close(fd)
        return nil, err
    }

    // Create a memory mapping
    data, err := syscall.Mmap(fd, 0, size, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED)
    if err != nil {
        syscall.Close(fd)
        return nil, err
    }

    return data, nil
}

func main() {
    size := 4096 // 4KB
    data, err := createMemfd(size)
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(1)
    }

    defer syscall.Munmap(data)

    // Use the memory
    copy(data, "Hello, memfd!")
    fmt.Println("Memory content:", string(data[:13]))
}

使用 shm_open

shm_openshm_unlink 可以用于在共享内存对象上创建和删除文件描述符。

package main

import (
    "fmt"
    "os"
    "syscall"
    "unsafe"
)

func createShm(size int) ([]byte, error) {
    shmName := "/myshm"

    // Create shared memory object
    fd, err := syscall.ShmOpen(shmName, syscall.O_CREAT|syscall.O_RDWR, 0600)
    if err != nil {
        return nil, err
    }

    // Resize the memory object
    if err := syscall.Ftruncate(fd, int64(size)); err != nil {
        syscall.Close(fd)
        syscall.ShmUnlink(shmName)
        return nil, err
    }

    // Create a memory mapping
    data, err := syscall.Mmap(fd, 0, size, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED)
    if err != nil {
        syscall.Close(fd)
        syscall.ShmUnlink(shmName)
        return nil, err
    }

    return data, nil
}

func main() {
    size := 4096 // 4KB
    data, err := createShm(size)
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(1)
    }

    defer syscall.Munmap(data)

    // Use the memory
    copy(data, "Hello, shm_open!")
    fmt.Println("Memory content:", string(data[:15]))
}

总结

虽然 macOS 不支持 memfd_create,但可以使用 mmapshm_open 来创建匿名内存文件或共享内存对象,以实现类似的功能。上述示例代码展示了如何在 macOS 上使用这两种方法。

fastfading commented 4 months ago

memfd_create is a Linux-specific system call used to create an anonymous file that resides in memory. Since it is specific to Linux, there is no direct equivalent in macOS. However, similar functionality can be achieved using other methods, such as mmap or shm_open. Here are some alternatives on macOS:

Using mmap

mmap can create an anonymous mapping in memory, which can be used to create a temporary in-memory file.

package main

import (
    "fmt"
    "os"
    "syscall"
)

func createMemfd(size int) ([]byte, error) {
    // Create an anonymous memory mapping
    data, err := syscall.Mmap(-1, 0, size, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_ANON|syscall.MAP_PRIVATE)
    if err != nil {
        return nil, err
    }
    return data, nil
}

func main() {
    size := 4096 // 4KB
    data, err := createMemfd(size)
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(1)
    }

    defer syscall.Munmap(data)

    // Use the memory
    copy(data, "Hello, mmap!")
    fmt.Println("Memory content:", string(data[:11]))
}

Using shm_open

shm_open and shm_unlink can be used to create and delete file descriptors on shared memory objects.

package main

import (
    "fmt"
    "os"
    "syscall"
    "unsafe"
)

func createShm(size int) ([]byte, error) {
    shmName := "/myshm"

    // Create shared memory object
    fd, err := syscall.ShmOpen(shmName, syscall.O_CREAT|syscall.O_RDWR, 0600)
    if err != nil {
        return nil, err
    }

    // Resize the memory object
    if err := syscall.Ftruncate(fd, int64(size)); err != nil {
        syscall.Close(fd)
        syscall.ShmUnlink(shmName)
        return nil, err
    }

    // Create a memory mapping
    data, err := syscall.Mmap(fd, 0, size, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED)
    if err != nil {
        syscall.Close(fd)
        syscall.ShmUnlink(shmName)
        return nil, err
    }

    return data, nil
}

func main() {
    size := 4096 // 4KB
    data, err := createShm(size)
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(1)
    }

    defer syscall.Munmap(data)

    // Use the memory
    copy(data, "Hello, shm_open!")
    fmt.Println("Memory content:", string(data[:15]))
}

Summary

Although macOS does not support memfd_create, you can use mmap or shm_open to create anonymous memory files or shared memory objects to achieve similar functionality. The example code above demonstrates how to use these two methods on macOS.

msantos commented 4 months ago

@fastfading thank you for the proposal and for the detailed code examples!

For example, if the caller embedded /bin/cat in the binary, cat could not be executed directly from the mmap'ed memory. To exec cat, would involve reimplementing the linker and exec() for each supported platform.

A fallback option for platforms without memfd support might be: