Что такое процесс в Unix-подобных операционных системах?

Ответ

Процесс — это изолированный экземпляр запущенной программы, которому операционная система выделяет ресурсы для выполнения.

Каждый процесс обладает:

  • Изолированным адресным пространством: Память одного процесса недоступна для другого. Включает в себя:
    • Сегмент кода (Text): Исполняемый код программы.
    • Сегмент данных (Data): Глобальные и статические переменные.
    • Куча (Heap): Динамически выделяемая память.
    • Стек (Stack): Локальные переменные, параметры функций и адреса возврата.
  • Системными ресурсами: Набор открытых файлов, сетевых соединений (сокетов).
  • Контекстом выполнения: Состояние регистров процессора, счетчик команд и другая информация, необходимая для выполнения.
  • Уникальным идентификатором (PID) и идентификатором родительского процесса (PPID).

Процессы создаются системным вызовом fork(), который создает точную копию родительского процесса, и exec(), который заменяет образ процесса на новую программу. В Go это абстрагировано в пакете os/exec.

package main

import (
    "fmt"
    "os/exec"
    "time"
)

func main() {
    // Создаем новый процесс, который выполнит команду 'ls -l'
    cmd := exec.Command("ls", "-l")

    // Запускаем процесс и ждем его завершения
    output, err := cmd.Output()
    if err != nil {
        fmt.Println("Error:", err)
        return
    }

    fmt.Printf("Process with PID %d finished.nOutput:n%s", cmd.Process.Pid, string(output))
}

Ключевое отличие от потока (thread): Потоки выполняются в рамках одного процесса и разделяют его адресное пространство, что делает коммуникацию между ними быстрее, но менее безопасной. Процессы полностью изолированы.

Ответ 18+ 🔞

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

Представь себе, что процесс — это как будто тебе, одинокому чуваку, операционка выдает целую отдельную квартиру-студию. Полная изоляция, блядь! Свои стены, свой санузел, своя кухня. И в этой квартире у тебя:

  • Своя библиотека (Text): Там лежит инструкция, что ты вообще должен делать, твой код.
  • Шкаф с барахлом (Data): Твои глобальные переменные, всякая статичная фигня, которую ты не трогаешь.
  • Свалка в углу (Heap): Туда ты кидаешь всё, что создаёшь на лету, динамически, как бог на душу положит.
  • Стол с бумажками (Stack): Тут ты пишешь, что тебе передали, какие локальные переменные, куда возвращаться. Съел — выкинул.

И самое главное — ты в своей квартире нихуя не видишь, что творится у соседа-процесса. Он может там ебучую бомбу собирать, а ты и не в курсе. Полная приватность, ёпта! Плюс тебе выдают личный пропуск (PID), пропуск твоего папаши (PPID), набор ключей от открытых файлов и сокетов, и полный слепок твоего текущего состояния — что ты делал, на чём остановился.

А рождаются эти процессы, конечно, через ебаную магию fork() — это когда процесс-родитель клонирует себя, как амёба, создавая свою точную копию-ребёнка. А потом этот ребёнок может через exec() выкинуть из головы всё родительское и загрузить себе в черепушку совершенно новую программу. В Go, слава богу, от этой низкоуровневой жести спрятались за пакетом os/exec.

package main

import (
    "fmt"
    "os/exec"
    "time"
)

func main() {
    // Создаем новый процесс, который выполнит команду 'ls -l'
    cmd := exec.Command("ls", "-l")

    // Запускаем процесс и ждем его завершения
    output, err := cmd.Output()
    if err != nil {
        fmt.Println("Error:", err)
        return
    }

    fmt.Printf("Process with PID %d finished.nOutput:n%s", cmd.Process.Pid, string(output))
}

И вот теперь главный пиздец, про отличие от потока. Поток — это не отдельная квартира! Это твой сожитель в этой же самой квартире. Вы жрёте из одного холодильника (памяти), срете в один унитаз (переменные), и если один поток начнёт дико бухать и ломать мебель, то второй получит по ебалу сразу же. Быстро, да, но охуенно опасно. А процесс — он отгорожен, как в бункере. Пусть себе там взрывается, другим-то что?