Pull to refresh

Пакет syscall в языке Golang

Level of difficultyEasy

Как все начиналось

В рамках лабораторной работы в университете надо было написать небольшую программу для работы с системными вызовами. Язык программирования можно было выбрать любой, а поскольку я учу Golang, мой выбор пал на него.

Погуглив, я нашел специальный пакет syscall, но понятность документации оставляет желать лучшего. Я стал копать дальше, но материала по данной теме оказалось очень мало, а на русском языке почти нет, поэтому я и решил написать данную статью.

Быстро про системные вызовы

Системный вызов - это обращение к ядру операционной системы. С помощью них наши программы могут планировать процессы, создавать каналы взаимодействия друг с другом и много чего ещё интересного.

В данной статье я рассмотрю следующие системные вызовы:

  • fork() - создание нового процесса с тем же исполняемым кодом, что и родительском процессе. Причем продолжение обоих процессов продолжится с того места, где был вызван syscall

  • exec() - меняет исполняемый код процесса на другой

Обёртки над системными вызовами

В пакете syscall есть разные реализации приведенных выше системных вызовов.

ForkExec() объединила в себе fork и exec, что немного упростило написание кода. Посмотрим на сигнатуру этого метода:

ForkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)

  • argv0 - файл с программой, которую мы хотим запустить в новом процессе.

  • argv - остальные аргументы командной строки, включая argv0.

  • attr - специальная структура ProcAttr, в которой описаны параметры для запуска нового процесса.

    Возвращает функция pid нового процесса или 0, если не получилось его создать, и ошибку, если таковая имеется.

Давайте рассмотрим ProcAttrподробнее:

type ProcAttr struct {
	Dir   string    // Current working directory.
	Env   []string  // Environment.
	Files []uintptr // File descriptors.
	Sys   *SysProcAttr
}
  • dir - путь до рабочей директории.

  • env - переменные окружающей среды.

  • files - файловые дескрипторы. Можно удобно их задать для текущего процесса без использования дополнительных системных вызовов.

  • sys - остальные параметры процесса типа SysProcAttr.

Я не использовал всех полей, пример кода выглядит так

args := &syscall.ProcAttr{
		Files: []uintptr{os.Stdin.Fd(), os.Stdout.Fd(), os.Stderr.Fd()},
	}

Если вам нужно перенаправить stdin, stdout или stderr в другие файлы, то файловые дескрипторы следует поменять.

Классическое представление

Если у вас возникла потребность вызвать эти системные вызовы отдельно, то можно использовать следующие функции:

syscall.Syscall(syscall.SYS_FORK, 0)

Первым аргументом идёт системный вызов, далее аргументы. Возвращается pid дочернего процесса в родительском, а в дочернем 0.

Exec(argv0 string, argv []string, envv []string) (err error)

  • argv0 - файл с программным кодом, который будет исполняться в новом процессе.

  • argv - аргументы командной строки

  • envv - переменные окружения

Не вижу особого смысла использовать такой вариант для создания новых процессов, потому что приходится писать больше кода и для изменения параметров нового процесса придется использовать дополнительные системные вызовы.

Вывод

Golang предоставляет удобный интерфейс для взаимодействия с системными вызовами, что может быть очень удобно для написания низкоуровневых приложений приложений. Надеюсь статья помогла вам разобраться с пакетом syscall.

Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.