#linux #go #system-calls
#linux #Вперед #системные вызовы
Вопрос:
У меня есть некоторый код go, который создает корневую систему скелета, а затем в каждом пространстве имен Linux подключается к нему, настраивает cgroups, а затем запускает процесс внутри этой cgroup / chroot.
Я заставил большую часть этого работать, но у меня возникли проблемы с получением контрольных групп для работы.
Я следил за этим на протяжении большей части своей работы с cgroups, и я все еще новичок в них как в концепции.
Если я вручную создам эту среду и выполню следующие команды, кажется, что все работает нормально. (Я добавил к ним номера для справки позже)
1) mount -t proc proc /proc
2) mount -t sysfs sysfs /sys
3) mount -t tmpfs cgroup_root /sys/fs/cgroup
4) mkdir /sys/fs/cgroup/pids
5) mount -t cgroup pids -o pids /sys/fs/cgroup/pids
Как вы можете видеть из выходных данных cat / proc / mounts
proc /proc proc rw,relatime 0 0
sysfs /sys sysfs rw,relatime 0 0
cgroup_root /sys/fs/cgroup tmpfs rw,relatime 0 0
pids /sys/fs/cgroup/pids cgroup rw,relatime,pids 0 0
У меня есть смонтированная /proc, /sys, /sys/fs/cgroup
и pids /sys/fs/cgroup/pids
-группа. Теперь я могу настроить эту cgroup pids с любыми настройками, которые я хочу, и все работает нормально.
Моя проблема в том, что я пытаюсь сделать то же самое в Go, и у меня возникают проблемы.
В моем коде я могу успешно выполнить до шага 4) mkdir /sys/fs/cgroup/pids
, и я даже проверил, что этот файл создается, но у меня возникают проблемы с получением системного вызова.Mount(), чтобы сделать то, что я хочу для 5-й команды.
Вот что у меня есть прямо сейчас.
func mountPid(pidsLoc string) {
fstype := "cgroup"
source := "pids"
flags := uintptr(0)
data := "pids"
err := syscall.Mount(source, pidsLoc, fstype, flags, data)
if err != nil {
serverFatal(err)
}
}
Где pidsLoc = /sys/fs/cgroup/pids
, но когда я пытаюсь запустить это, я получаю сообщение об ошибке «операция не разрешена».
Я действительно не думаю, что это ошибка разрешений, потому что я смог смонтировать свой /sys
, /proc
и /sys/fs/cgroups
все в порядке. Вот код, который я использовал для этих трех:
func mountProc() {
source := "proc"
fstype := "proc"
target := "/proc"
flags := uintptr(0)
data := ""
err := syscall.Mount(source, target, fstype, flags, data)
if err != nil {
serverFatal(err)
}
}
func mountSys() {
source := "sysfs"
fstype := "sysfs"
target := "/sys"
flags := uintptr(0)
data := ""
err := syscall.Mount(source, target, fstype, flags, data)
if err != nil {
serverFatal(err)
}
}
//This can not be called before mountSys()
func mountCGroupFS() {
fstype := "tmpfs"
source := "cgroup_root"
target := "/sys/fs/cgroup"
flags := uintptr(0)
data := ""
err := syscall.Mount(source, target, fstype, flags, data)
if err != nil {
serverFatal(err)
}
}
И я запустил все из них с теми же разрешениями, что и раньше. Может быть, я просто использую системный вызов.Mount() неправильно, но я не уверен. Документация для пакета системного вызова в Go не очень хороша, и я обнаружил, что в основном мне приходится читать документацию на C / C для методов, которые использует системный вызов, а затем пытаться установить связи между ними.
Заранее спасибо!
PS Вот ссылка на репозиторий, если вам интересно. Я пытаюсь создать программу, которая позволяет «безопасно» выполнять внешний код.
Комментарии:
1. Почему бы не использовать это: github.com/containerd/cgroups ?
2. Я не знал об этом, и похоже, что это будет отличный ресурс, но я пытаюсь создать свой собственный с нуля, чтобы учиться, поэтому я не хочу использовать другую библиотеку.