2014-09-04 5 views
0

이동 중에 네임 스페이스를 변경하고 싶습니다. C에서 코드를 컴파일하고 실행할 때 제대로 작동하지만 netn 시스템 콜에서 errno 22를 얻습니다. 이것이 일어날 수있는 아이디어가 있습니까?리눅스 네임 스페이스를 변경하십시오.

이동)

$ 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) 
    } 
} 
+0

'perror()'줄을 변경하여 문자열이 어느 호출에 실패했는지 말할 수 있습니까? "잘못된 인수"만으로는 무슨 일이 일어나고 있는지 설명하기에 충분하지 않습니다. (나는 이것이 움직이는 스택 문제라고 생각한다.) – andlabs

+0

setns가 예상 된 스레드에서 호출되고 있는지 확인하기 위해'runtime.LockOSThread'를 호출해야한다. – JimB

+0

docker가 [libcontainer/namespaces] (https://github.com/libcontainer/namespaces)에서이를 어떻게 처리하는지 확인할 수 있습니다. 다가오는'go.sys' 패키지에 대한 지원을 추가하는 것에 관한 최소한 하나의 공개 문제가 있습니다 : [# 8447] (https://code.google.com/p/go/issues/detail?id=8447) – JimB

답변

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 
} 
+0

테스트 할 때 어제 피곤할 것입니다.하지만이 문제로 문제가 해결됩니다. 여전히 같은 오류. – KrHubert

+0

@ixos 오류가 무엇을 말합니까? – OneOfOne

+0

같은 오류 : setns mnt – KrHubert

관련 문제