Как выполнить системный вызов (syscall) в Go?

Ответ

Системный вызов (syscall) — это обращение программы к ядру операционной системы для выполнения низкоуровневой операции (например, работа с файлами, сетью, процессами).

Современный подход (рекомендуемый):

Начиная с Go 1.4, рекомендуется использовать пакет golang.org/x/sys/unix (для Unix-подобных систем) или golang.org/x/sys/windows. Пакет syscall в стандартной библиотеке считается замороженным и может быть удален в будущем.

Исторический подход (пакет syscall):

Пакет syscall предоставляет несколько функций для выполнения системных вызовов:

  1. Обертки высокого уровня: Для многих популярных системных вызовов есть готовые функции-обертки. Это самый простой и безопасный способ.

    // Получаем ID текущего процесса
    pid := syscall.Getpid()
    fmt.Printf("Process ID: %dn", pid)
    
    // Меняем права на файл
    err := syscall.Chmod("myfile.txt", 0644)
  2. syscall.Syscall() / syscall.Syscall6(): Для вызовов, которые могут блокировать поток на длительное время. Эти функции интегрированы с планировщиком Go, который может запустить другую горутину на этом потоке.

    // Пример открытия файла (упрощенно)
    // syscall.Syscall(номер_вызова, arg1, arg2, arg3)
    fd, _, errno := syscall.Syscall(syscall.SYS_OPEN, uintptr(unsafe.Pointer(syscall.StringBytePtr("file.txt"))), uintptr(syscall.O_RDONLY), 0)
    if errno != 0 {
        // обработка ошибки
    }
  3. syscall.RawSyscall(): Для очень быстрых вызовов, которые гарантированно не блокируются. Эта функция не взаимодействует с планировщиком Go, что делает ее более производительной, но и более опасной при неправильном использовании.

Ключевые моменты:

  • Платформозависимость: Номера системных вызовов (например, syscall.SYS_OPEN) и их аргументы сильно зависят от ОС (Linux, macOS, Windows).
  • unsafe: Для передачи указателей (например, на строки) в ядро часто требуется использовать пакет unsafe.
  • Ошибки: Системные вызовы обычно возвращают результат и ошибку типа syscall.Errno. Значение 0 означает успех.

Вывод: Для нового кода всегда используйте пакет golang.org/x/sys. Прямые системные вызовы через syscall.Syscall — это мощный, но сложный и небезопасный инструмент, который следует применять с осторожностью.