>백엔드 개발 >Golang >Go 다중 스레드 환경에서 EINVAL과 함께 \'setns\'가 실패하는 이유는 무엇입니까?

Go 다중 스레드 환경에서 EINVAL과 함께 \'setns\'가 실패하는 이유는 무엇입니까?

Linda Hamilton
Linda Hamilton원래의
2024-11-01 09:23:30737검색

Why Does 'setns' Fail with EINVAL in a Go Multithreaded Environment?

Go에서 'setns' 호출이 MNT 네임스페이스에 대한 EINVAL과 함께 실패함

문제

MNT에 진입하기 위해 Go에서 'setns' 호출을 시도할 때 네임스페이스가 있는 경우 호출은 지속적으로 EINVAL을 반환합니다. 이 문제는 동일한 기능이 올바르게 작동하는 C 구현에도 불구하고 관찰됩니다.

원인

이 문제는 Go가 다중 스레드 언어인 반면 'setns'는 다중 스레드 언어라는 사실에서 발생합니다. 단일 스레드 컨텍스트에서 호출됩니다. 다중 스레드 환경에서 호출할 때 'setns'는 현재 스레드를 대상 네임스페이스와 제대로 연결하지 못합니다.

해결책 - CGO 생성자 트릭

이 문제에 대한 해결책은 다음을 활용하는 것입니다. "CGO 생성자 트릭." 이 기술을 사용하면 Go 런타임이 초기화되기 전에 실행될 C 함수를 지정할 수 있습니다. 이 접근 방식을 사용하면 C 함수는 Go 스레드가 생성되기 전에 'setns'를 호출할 수 있으므로 호출이 단일 스레드 컨텍스트에서 이루어지도록 할 수 있습니다.

  1. 'setns'를 호출하는 C 함수를 구성하세요. ' 원하는 매개변수를 사용하세요. __attribute__((constructor)) 매크로로 함수를 장식하면 됩니다.
  2. import "C"를 사용하여 C 함수를 가져와 Go 코드에 포함시킵니다.

작업 예

<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"

... rest of file is unchanged ...
</code>

자리 표시자 대상 프로세스의 실제 PID를 사용합니다.

제한 사항

이 접근 방식에는 몇 가지 제한 사항이 있습니다.

  • PID는 Go 함수와 같이 C 함수 내에 하드코딩되어야 합니다. C 함수 실행 시에는 코드를 사용하지 못할 수 있습니다.
  • Go 런타임 초기화 전에 C 코드가 실행되므로 Go 코드 내에서 'setns'를 여러 번 호출하는 것은 불가능합니다.

추가 참고 사항

'setns(2)' 패치는 다중 스레드 환경에서 단일 스레드 실행에 대한 요구 사항을 확인합니다. 기능이 있는 프로세스는 자체 사용자 네임스페이스에 CAP_SYS_CHROOT 및 CAP_SYS_ADMIN을 보유하고 대상 마운트 네임스페이스에 CAP_SYS_ADMIN도 보유해야 합니다.

위 내용은 Go 다중 스레드 환경에서 EINVAL과 함께 \'setns\'가 실패하는 이유는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.