Pid 0 что значит
Перейти к содержимому

Pid 0 что значит

  • автор:

The Windows Process Journey — PID 0 (System Idle Process)

The goal of this process is to give the CPU something to execute in case there is nothing else to do (thus it is called idle ;-). Let’s think about the next situation, we have a process using 30% of CPU, in that case PID 0 (System Idle) will consume the remaining 70%. Also, Idle is the first process that the kernel starts.

Moreover, there is a kernel thread of System Idle for each vCPU the OS has identified (check out the screenshot below which shows that. The VM which I have used had 3 vCPUs — also see the first field in the table showing the “Processor”).

The reason for having an “Idle Process” is to avoid an edge case in which the scheduler (Windows schedule based on threads) does not have any thread in a “Ready” state to execute next. By the way, there are also other schedulers IO and Memory, which we will talk about in one of the next posts/writeups.

When the kernel threads are executed they can also perform different power saving tricks regarding the CPU. One of them could be halting different components which are not in use until the next interrupt arrives. The kernel threads can also call functions in the HAL (hardware abstraction layer, more on that in the future) in order to perform tasks such as reducing the CPU clock speed. Which optimization is performed is based on the version of Windows, hardware and the firmware installed.

Windows PID = 0 допустимо?

в Windows 0 действительный PID для процесса или зарезервирован ОС? Было бы неплохо, если бы вы могли предоставить ссылку на документ, который говорит, что он зарезервирован или что. Спасибо!

3 ответов

открыть Диспетчер задач-перейдите на вкладку процессы (возможно, нажмите «Просмотр», «показать столбцы» и включите столбец PID).

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

нет документации, доступной для меня, но я уверен, что это всегда будет так.

это нигде не указано, но это сводится к тому, как работает таблица обработки ядра. Этот же объект используется как для дескрипторов процессов, так и для идентификаторов процессов/потоков. Случается, что значения дескриптора начинаются с 0x4, и PsInitialSystemProcess является первым процессом, который будет создан, поэтому он получает PID 4. Процесс простоя на самом деле не является процессом, и вы не можете его открыть. Вероятно, у него нет PID для большинства намерений и целей, но большинство инструментов считают его равным 0.

PID 0 зарезервирован для простаивающего «psuedo-процесса», так же, как PID 4 зарезервирован для системы (ядра Windows).

Я не могу найти документацию о том, где это указано, но запрос процессов через любой API (perf Counters, WMI) всегда даст вам простой процесс для PID 0.

windows PID = 0 valid?

In Windows, is 0 valid PID for a process or is it reserved by OS? It would be nice if you can provide a link to a doc that says it is reserved or what. Thank!

3 Answers 3

Open task manager — switch to the processes tab (maybe click «View», «Show columns» and enable the PID column).

PID 0 is the System Idle Process. Since that process isn’t really a process and never exits, I suspect that it is always the case.

No documentation available to me, but I’m pretty certain this is always going to be the case.

It’s not stated anywhere but it comes down to how the kernel handle table works. This same object is used for both process handles and process/thread IDs. It happens that handle values all start at 0x4, and PsInitialSystemProcess is the first process to be created, so it gets a PID of 4. Idle process isn’t actually a process and you can’t open it. It probably doesn’t have a PID for most intents and purposes but most tools consider it to be 0.

The PID of 0 is reserved for the Idle «psuedo-process», just like PID of 4 is reserved for the System (Windows Kernel).

I can’t find any documentation on where that is specified, but querying the processes via any API (Perf Counters, WMI) will always give you the idle process for PID 0.

    The Overflow Blog
Related
Hot Network Questions

Subscribe to RSS

To subscribe to this RSS feed, copy and paste this URL into your RSS reader.

Site design / logo © 2023 Stack Exchange Inc; user contributions licensed under CC BY-SA . rev 2023.3.3.43277

By clicking “Accept all cookies”, you agree Stack Exchange can store cookies on your device and disclose information in accordance with our Cookie Policy.

Механизмы контейнеризации: namespaces

namespaces

Последние несколько лет отмечены ростом популярности «контейнерных» решений для ОС Linux. О том, как и для каких целей можно использовать контейнеры, сегодня много говорят и пишут. А вот механизмам, лежащим в основе контейнеризации, уделяется гораздо меньше внимания.

Все инструменты контейнеризации — будь то Docker, LXC или systemd-nspawn,— основываются на двух подсистемах ядра Linux: namespaces и cgroups. Механизм namespaces (пространств имён) мы хотели бы подробно рассмотреть в этой статье.

Начнём несколько издалека. Идеи, лежащие в основе механизма пространств имён, не новы. Ещё в 1979 году в UNIX был добавлен системный вызов chroot() — как раз с целью обеспечить изоляцию и предоставить разработчикам отдельную от основной системы площадку для тестирования. Нелишним будет вспомнить, как он работает. Затем мы рассмотрим особенности функционирования механизма пространств имён в современных Linux-системах.

Chroot(): первая попытка изоляции

Название chroot представляет собой сокращение от change root, что дословно переводится как «изменить корень». С помощью системного вызова chroot() и соответствующей команды можно изменить корневой каталог. Программе, запущенной с изменённым корневым каталогом, будут доступны только файлы, находящиеся в этом каталоге.

Файловая система UNIX представляет собой древовидную иерархию:

chroot

Вершиной этой иерархии является каталог /, он же root. Все остальные каталоги — usr, local, bin и другие, — связаны с ним.

С помощью chroot в систему можно добавить второй корневой каталог, который с точки зрения пользователя ничем не будет отличаться от первого. Файловую систему, в которой присутствует изменённый корневой каталог, можно схематично представить так:

chroot

Файловая система разделена на две части, и они никак не влияют друг на друга. Как работает chroot? Сначала обратимся к исходному коду. В качестве примера рассмотрим реализацию chroot в OC 4.4 BSD-Lite.

Системный вызов chroot описан в файле vfs_syscall.c:

Самое главное происходит в предпоследней строке приведённого нами фрагмента: текущая директория становится корневой.
В ядре Linux системный вызов chroot реализован несколько сложнее (фрагмент кода взят отсюда):

Рассмотрим особенности работы chroot в Linux на практических примерах. Выполним следующие команды:

В результате выполнения второй команды мы получим сообщение об ошибке:

Ошибка заключается в следующем: не была найдена командная оболочка. Обратим внимание на этот важный момент: с помощью chroot мы создаём новую, изолированную файловую систему, которая не имеет никакого доступа к текущей. Попробуем снова:

Опять ошибка — несмотря на идентичное сообщение, совсем не такая, как в прошлый раз. Прошлое сообщение было выдал шелл, так как не нашёл нужного исполняемого файла. В примере выше об ошибке сообщил динамический линковщик: он не нашёл необходимых библиотек. Чтобы получить к ним доступ, их тоже нужно копировать в chroot. Посмотреть, какие именно динамические библиотеки требуется скопировать, можно так:

После этого выполним следующие команды:

Теперь получилось! Попробуем выполнить в новой файловой системе, например, команду ls:

В ответ мы получим сообщение об ошибке:

Причина понятна: в новой файловой системе команда ls отсутствует. Нужно опять копировать исполняемый файл и динамические библиотеки, как это уже было показано выше. В этом и заключается серьёзный недостаток chroot: все необходимые файлы нужно дублировать. Есть у chroot и ряд недостатков с точки зрения безопасности.

Попытки усовершенствовать механизм chroot и обеспечить более надёжную изоляцию предпринимались неоднократно: так, в частности, появились такие известные технологии, как FreeBSD Jail и Solaris Zones.
В ядре Linux изоляция процессов была усовершенствована благодаря добавлению новых подсистем и новых системных вызовов. Некоторые из них мы разберём ниже.

Механизм пространств имён

Пространство имён (англ. namespace) — это механизм ядра Linux, обеспечивающий изоляцию процессов друг от друга. Работа по его реализации была начата в версии ядра 2.4.19. На текущий момент в Linux поддерживается шесть типов пространств имён:

Пространство имён Что изолирует
PID PID процессов
NETWORK Сетевые устройства, стеки, порты и т.п.
USER ID пользователей и групп
MOUNT Точки монтирования
IPC SystemV IPC, очереди сообщений POSIX
UTS Имя хоста и доменное имя NIS

Все эти типы используются современными системами контейнеризации (Docker, LXC и другими) при запуске программ.

PID: изоляция PID процессов

Исторически в ядре Linux поддерживалось только одно дерево процессов. Дерево процессов представляет собой иерархическую структуру, подобную дереву каталогов файловой системы.

С появлением механизма namespaces стала возможной поддержка нескольких деревьев процессов, полностью изолированных друг от друга.

При загрузке в Linux сначала запускается процесс с идентификационным номером (PID) 1. В дереве процессов он является корневым. Он запускает другие процессы и службы. Механизм namespaces позволяет создавать отдельное ответвление дерева процессов с собственным PID 1. Процесс, который создаёт такое ответвление, являются частью основного дерева, но его дочерний процесс уже будет корневым в новом дереве.

Процессы в новом дереве никак не взаимодействуют с родительским процессом и даже не «видят» его. В то же время процессам в основном дереве доступны все процессы дочернего дерева. Наглядно это показано на следующей схеме:

PID Namespace

Можно создавать несколько вложенных пространств имён PID: один процесс запускает дочерний процесс в новом пространстве имён PID, a тот в свою очередь порождает новый процесс в новом пространстве и т.п.

Один и тот же процесс может иметь несколько идентификаторов PID (отдельный идентификатор для отдельного пространства имён).

Для создания новых пространств имён PID используется системный вызов clone() c флагом CLONE_NEWPID. С помощью этого флага можно запускать новый процесс в новом пространстве имён и в новом дереве. Рассмотрим в качестве примере небольшую программу на языке C (здесь и далее примеры кода взяты отсюда и незначительно нами изменены):

Скомпилируем и запустим эту программу. По завершении её выполнения мы увидим следующий вывод:

Во время выполнения такой маленькой программы в системе произошло много интересного. Функция clone() создала новый процесс, клонировав текущий, и начала его выполнение. При этом она отделила новый процесс от основного дерева и создала для него отдельное дерево процессов.

Попробуeм теперь изменить код программы и узнать родительский PID с точки зрения изолированного процесса:

Вывод изменённой программы будет выглядет так:

Строка «Родительский PID: 0» означает, что у рассматриваемого нами процесса родительского процесса нет. Внесём в программу ещё одно изменение и уберём флаг CLONE_NEWPID из вызова clone():

Системный вызов clone в этом случае сработал практически так же, как fork() и просто создал новый процесс. Между fork() и clone(), однако, есть существенное отличие, которое следует разобрать детально.

Fork() создаёт дочерний процесс, который представляет копию родительского. Родительский процесс копируется вместе со всем контекстом исполнения: выделенной памятью, открытыми файлами и т.п.

В отличие от fork() вызов clone() не просто создаёт копию, но позволяет разделять элементы контекста выполнения между дочерним и родительским процессами. В приведённом выше примере кода с функцией clone используется аргумент child_stack, который задаёт положение стека для дочернего процесса. Как только дочерний и родительский процессы могут разделять память, дочерний процесс не может выполняться в том же стеке, что и родительский. Поэтому родительский процесс должен установить пространство памяти для дочернего и передать указатель на него в вызове clone(). Ещё один аргумент, используемый с функцией clone() — это флаги, которые указывают, что именно нужно разделять между родительским и дочерним процессами. В приведённом нами примере использован флаг CLONE_NEWPID, который указывает, что дочерний процесс должен быть создан в новом пространстве имён PID. Примеры использования других флагов будут приведены ниже.

Итак, изоляцию на уровне процессов мы рассмотрели. Но это — всего лишь первый шаг. Запущенный в отдельном пространстве имён процесс все равно будет иметь доступ ко всем системным ресурсам. Если такой процесс будет слушать, например, 80-й порт, это этот порт будет заблокирован для всех остальных процессов. Избежать таких ситуаций помогают другие пространства имён.

NET: изоляция сетей

Благодаря пространству имён NET мы можем выделять для изолированных процессов собственные сeтевые интерфейсы. Даже loopback-интерфейс для каждого пространства имён будет отдельным.

Сетевые пространства имён можно создавать с помощью системного вызова clone() с флагом CLONE_NEWNET. Также это можно сделать с помощью iproute2:

Воспользуемся strace и посмотрим, что произошло в системе во время приведённой команды:

Обратим внимание: здесь для создания нового пространстве имён использован системный вызов unshare(), а не уже знакомый нам clone. Unshare() позволяет процессу или треду отделять части контекста исполнения, общие с другими процессами (или тредами).

Как можно помещать процессы в новое сетевое пространство имён?

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

Во-вторых, в ядре имеется специальный системный вызов — setns(). С его помощью можно поместить вызывающий процесс или тред в нужное пространство имён. Для этого требуется файловый дескриптор, который на это пространство имён ссылается. Он хранится в файле /proc/<PID процесса>/ns/net. Открыв этот файл, мы можем передать файловый дескриптор функции setns().

Можно пойти и другим путём. При создании нового пространства имён с помощью команды ip создаётся файл в директории /var/run/netns/ (см. в выводе трассировки выше). Чтобы получить файловый дескриптор, достаточно просто открыть этот файл.

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

MOUNT: изоляция файловой системы

Об изоляции на уровне файловой системы мы уже упоминали выше, когда разбирали системный вызов chroot (). Мы отметили, что системный вызов chroot() не обеспечивает надёжной изоляции. С помощью же пространств имён MOUNT можно создавать полностью независимые файловые системы, ассоциируемые с различными процессами:

MOUNT namespace

Для изоляции файловой системы используется системный вызов clone() c флагом CLONE_NEWNS:

Сначала дочерний процесс «видит» те же точки монтирования, что и родительский. Как только дочерний процесс перенесён в отдельное пространство имён, к нему можно примонтировать любую файловую системы, и это никак не затронет ни родительский процесс, ни другие пространства имён.

Другие пространства имён

Изолированный процесс также может быть помещён в другие пространства имён: UID, IPC и PTS. UID позволяет процессу получать привилегии root в пределах определённого пространства имён. С помощью пространства имён IPC можно изолировать ресурсы для коммуникации между процессами.

UTS используется для изоляции системных идентификаторов: имени узла (nodename) и имени домена (domainame), возвращаемых системным вызовом uname(). Рассмотрим ещё одну небольшую программу:

Вывод этой программы будет выглядеть так:

Как видим, функция child_fn() выводит имя узла, изменяет его, а затем выводит уже новое имя. Изменение происходит только внутри нового пространства имён.

Заключение

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

Если вы по тем или иным причинам не можете оставлять комментарии здесь — приглашаем в наш блог.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *