英文:
Change linux namespace in go
问题
我想在Go语言中更改命名空间。当我在C中编译和运行代码时,一切都正常,但在Go中,netns系统调用返回了错误号22。有任何想法为什么会发生这种情况吗?
以下是要翻译的内容:
我想在Go语言中更改命名空间。当我在C中编译和运行代码时,一切都正常,但在Go中,netns系统调用返回了错误号22。有任何想法为什么会发生这种情况吗?
go)
$ go build main.go ; ./main
setns mnt: Invalid argument
panic: -1
goroutine 1 [running]:
runtime.panic(0x423b80, 0xffffffffffffffff)
/usr/local/go/src/pkg/runtime/panic.c:266 +0xb6
main.main()
main.go:81 +0x86
$
c)
$ grep ^// main.go | sed 's/\/\///' | sed 's/__main/main/' > main.c; gcc main.c -o main; ./main
$
以下是代码:
package main
//
// #define _GNU_SOURCE
// #include <fcntl.h>
// #include <sched.h>
// #include <sys/syscall.h>
// #include <sys/param.h>
// #include <sys/mount.h>
// #include <stdio.h>
// #include <unistd.h>
//
// #define NETNS_RUN_DIR "/run/netns"
// #define MNTNS_RUN_DIR "/run/mntns"
//
// #ifndef HAVE_SETNS
//
// int
// setns(int fd, int nstype) {
// #ifdef __NR_setns
// return syscall(__NR_setns, fd, nstype);
// #else
// errno = ENOSYS;
// return -1;
// #endif
// }
//
// #endif /* HAVE_SETNS */
//
//
// int
// ChangeNamespace(char *name)
// {
// char net_path[MAXPATHLEN];
// char mnt_path[MAXPATHLEN];
// int fd;
//
// snprintf(net_path, sizeof(net_path), "%s/%s", NETNS_RUN_DIR, name);
// snprintf(mnt_path, sizeof(mnt_path), "%s/%s", MNTNS_RUN_DIR, name);
//
// fd = open(net_path, O_RDONLY);
// if (fd < 0) {
// perror("open net");
// return -1;
// }
//
// if (setns(fd, 0) < 0) {
// perror("setns net");
// return -1;
// }
//
// fd = open(mnt_path, O_RDONLY);
// if (fd < 0) {
// perror("open mnt");
// return -1;
// }
//
// if (setns(fd, 0) < 0) {
// perror("setns mnt");
// return -1;
// }
//
// return 0;
// }
//
// int
// __main(int argc, char *argv[]) {
// ChangeNamespace("ns");
// return 0;
// }
//
import "C"
import "unsafe"
func main() {
name := C.CString("ns")
defer C.free(unsafe.Pointer(name))
i := int(C.ChangeNamespace(name))
if i < 0 {
panic(i)
}
}
英文:
I want to change namespace in go. When I'm compiling and running code in C it works fine, but in go I got errno 22 on netns syscall. Any Idea why this could occur?
go)
$ go build main.go ; ./main
setns mnt: Invalid argument
panic: -1
goroutine 1 [running]:
runtime.panic(0x423b80, 0xffffffffffffffff)
/usr/local/go/src/pkg/runtime/panic.c:266 +0xb6
main.main()
main.go:81 +0x86
$
c)
$ grep ^// main.go | sed 's/\/\///' | sed 's/__main/main/' > main.c; gcc main.c -o main; ./main
$
The code below:
package main
//
// #define _GNU_SOURCE
// #include <fcntl.h>
// #include <sched.h>
// #include <sys/syscall.h>
// #include <sys/param.h>
// #include <sys/mount.h>
// #include <stdio.h>
// #include <unistd.h>
//
// #define NETNS_RUN_DIR "/run/netns"
// #define MNTNS_RUN_DIR "/run/mntns"
//
// #ifndef HAVE_SETNS
//
// int
// setns(int fd, int nstype) {
// #ifdef __NR_setns
// return syscall(__NR_setns, fd, nstype);
// #else
// errno = ENOSYS;
// return -1;
// #endif
// }
//
// #endif /* HAVE_SETNS */
//
//
// int
// ChangeNamespace(char *name)
// {
// char net_path[MAXPATHLEN];
// char mnt_path[MAXPATHLEN];
// int fd;
//
// snprintf(net_path, sizeof(net_path), "%s/%s", NETNS_RUN_DIR, name);
// snprintf(mnt_path, sizeof(mnt_path), "%s/%s", MNTNS_RUN_DIR, name);
//
// fd = open(net_path, O_RDONLY);
// if (fd < 0) {
// perror("open net");
// return -1;
// }
//
// if (setns(fd, 0) < 0) {
// perror("setns net");
// return -1;
// }
//
// fd = open(mnt_path, O_RDONLY);
// if (fd < 0) {
// perror("open mnt");
// return -1;
// }
//
// if (setns(fd, 0) < 0) {
// perror("setns mnt");
// return -1;
// }
//
// return 0;
// }
//
// int
// __main(int argc, char *argv[]) {
// ChangeNamespace("ns");
// return 0;
// }
//
import "C"
import "unsafe"
func main() {
name := C.CString("ns")
defer C.free(unsafe.Pointer(name))
i := int(C.ChangeNamespace(name))
if i < 0 {
panic(i)
}
}
答案1
得分: 5
你可以使用类似这样的代码来完全跳过cgo,我现在无法测试它:
const (
netNS = "/run/netns/"
mntNS = "/run/mntns/"
)
func ChangeNamespace(name string) error {
fd, err := syscall.Open(netNS+name, syscall.O_RDONLY, 0666)
if err != nil {
return err
}
defer syscall.Close(fd)
if _, _, err := syscall.RawSyscall(syscall.SYS_SETNS, uintptr(fd), 0, 0); err != nil {
return err
}
fd1, err := syscall.Open(mntNS+name, syscall.O_RDONLY, 0666)
if err != nil {
return err
}
defer syscall.Close(fd1)
if _, _, err := syscall.RawSyscall(syscall.SYS_SETNS, uintptr(fd1), 0, 0); err != nil {
return err
}
return nil
}
希望对你有帮助!
英文:
You could use something like this skipping the cgo all together, I can't test it right now:
const (
netNS = "/run/netns/"
mntNS = "/run/mntns/"
)
func ChangeNamespace(name string) error {
fd, err := syscall.Open(netNS+name, syscall.O_RDONLY, 0666)
if err != nil {
return err
}
defer syscall.Close(fd)
if _, _, err := syscall.RawSyscall(syscall.SYS_SETNS, uintptr(fd), 0, 0); err != nil {
return err
}
fd1, err := syscall.Open(mntNS+name, syscall.O_RDONLY, 0666)
if err != nil {
return err
}
defer syscall.Close(fd1)
if _, _, err := syscall.RawSyscall(syscall.SYS_SETNS, uintptr(fd1), 0, 0); err != nil {
return err
}
return nil
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论