Почему функция fork() должна возвращать файловый дескриптор?

La herramienta de reparación de arranque dice que su/dev/sda(= el disco desde el que se supone que debe arrancar Ubuntu instalado )tiene Disklabel type: dosy Boot files: /grub/grub.cfg /grub/i386-pc/core.img, por lo que la instalación esperaba hacer un arranque de estilo MBR heredado -, e instaló una versión de GRUB hecha a medida.

Por otro lado, su pantalla de configuración indica claramente que su sistema está configurado para arrancar en el estilo UEFI.

Su sistema no debe tener una, sino dos opciones para iniciar un instalador desde cualquier CD -ROM o medio de instalación USB. Uno debería dar como resultado un arranque de estilo UEFI -nativo; el otro, que aparentemente ha utilizado, es un arranque de estilo MBR -heredado.

El truco es que, debe iniciar el instalador del sistema operativo usando el mismo estilo que se espera que use el sistema operativo instalado.

Si inicia el instalador en estilo MBR, no podrá acceder a las variables de inicio EFI en la NVRAM del sistema y, por lo tanto, no podrá completar la instalación de un cargador de inicio estilo UEFI -. También asumirá que lo que necesita es una partición y un cargador de arranque de estilo MBR -:, creará una tabla de partición de estilo MBR -si está particionando discos -desde cero, y no creará la partición del sistema EFI (ESP ).

Si no hay nada que deba conservar en el sistema, debe reiniciar el instalador de Ubuntu nuevamente, pero esta vez al estilo UEFI. Luego, debe eliminar todas las particiones existentes para que el instalador pueda cambiar el estilo de partición a GPT.

16
20.07.2019, 17:05
4 ответа

Проблема описана там в вашем источнике, select()должен прерываться сигналами типа SIGCHLD, но в некоторых случаях это не так хорошо работает. Таким образом, обходным путем является запись сигнала в канал, за которым затем следит select(). select()предназначен для наблюдения за файловыми дескрипторами, так что это решает проблему.

Обходной путь по существу превращает событие сигнала в событие дескриптора файла. Если бы fork()просто вернул fd, обходной путь не потребовался бы, так как этот fd можно было бы использовать напрямую с select().

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


Еще одна причина, по которой fd (или какой-либо другой вид дескриптора ядра )лучше простого идентификатора процесса, заключается в том, что PID можно повторно использовать после того, как процесс умирает. Это может быть проблемой в некоторых случаях при отправке сигналов процессам, может быть невозможно точно знать, что это именно тот процесс, о котором вы думаете, а не другой, повторно использующий тот же PID. (Хотя я думаю, что это не должно быть проблемой при отправке сигналов дочернему процессу, так как родитель должен выполнить wait()для дочернего процесса, чтобы его PID был освобожден.)

14
27.01.2020, 19:48

Бернстайн не приводит большого контекста для этого замечания «Правильно», но рискну предположить, что :fork (2 )return PID несовместим с open (2 ), creat (2 )и т.д., возвращающие файловые дескрипторы. Остальная часть системы Unix могла выполнять манипуляции с процессами с файловым дескриптором, представляющим процесс, вместо PID. Существует системный вызов signalfd (2 ), который обеспечивает несколько лучшее взаимодействие между сигналами и файловыми дескрипторами и показывает, что файловый -дескриптор -, представляющий процесс, может работать.

8
27.01.2020, 19:48

Это просто размышление о том, что «было бы здорово, если бы Unix проектировался иначе, чем он есть».

Проблема с PID заключается в том, что они живут в глобальном пространстве имен, где их можно повторно использовать для другого процесса, и было бы неплохо, если бы fork()возвращал в родителя какой-то дескриптор, который гарантированно всегда будет ссылаться на процесс. дочерний процесс, и что он может передаваться другим процессам через наследование или unix-сокеты /SCM_RIGHTS[1].

См. также обсуждение здесь для недавней попытки «исправить» это в Linux, включая добавление флага в clone(), который заставит его возвращать pid -fd вместо PID.

Но даже в этом случае это не устранило бы необходимости во взломе -канала [2] или улучшенных интерфейсах, поскольку сигналы, уведомляющие родительский процесс о состоянии дочернего процесса, — не единственные, которые вы хотели бы использовать. дескриптор в основном цикле программы. К сожалению, такие вещи, как epoll(7) + signalfd(2)в Linux или kqueue(2)в BSD, не являются стандартными --единственный стандартный интерфейс (, но не поддерживаемый в более старых системах )намного хуже pselect(2).

[1] Предотвращение повторного -цикла PID к моменту возврата системного вызова waitpid()и использования его возвращаемого значения, вероятно, может быть достигнуто в более новых системах с использованием вместо этого waitid(.., WNOWAIT).

[2] Я бы не стал комментировать Д.Дж. Бернштейн утверждает, что это он изобрел (извините за апофазию; -)).

9
27.01.2020, 19:48

Дело в том, что существует множество программ, которые работают с моделью цикла событий -, основанной на мониторинге файловых дескрипторов с select (2)/ poll (2 ). / epoll (7). Но были различные события, которые исторически не уведомлялись с помощью файловых дескрипторов --, среди них переход состояния процесса (, например, завершение )дочернего процесса. Необходимость отдельной обработки этих других событий (, которые включают в себя истечение времени таймера, сигналы и события синхронизации, такие как изменения семафора ), усложняет программирование модели цикла событий -.

За последние несколько лет разработка Linux упростила решение этой проблемы, так что в настоящее время у нас есть signalfd (2)(сделать сигналы доступными для чтения из файлового дескриптора ), eventfd (2)(примитив синхронизации, дескриптор которого является файловым дескриптором ), и timerfd _создание (2)(создание таймеров, которые уведомляют через файловый дескриптор ), все которые создают файловые дескрипторы, которые можно передать в select (2)/ poll (2)/ epoll (7).

И, наконец, в последних версиях Linux добавлена ​​концепция дескриптора процесса в виде файлового дескриптора. Флаг CLONE_PIDFDдля clone3()может использоваться для создания дочернего процесса, для которого возвращается файловый дескриптор в качестве дескриптора. Дескриптор файла также может быть передан в select (2)/ poll (2)/ epoll (7)и указывается как читаемый, если дочерний процесс завершается.

1
18.02.2020, 10:34

Теги

Похожие вопросы