Лекция №5. Лекция 5 Эта лекция будет первой в цикле лекций, которые будут посвящены управлению процессами
Скачать 30.18 Kb.
|
Лекция №5 Эта лекция будет первой в цикле лекций, которые будут посвящены управлению процессами. 1 Подсистема управления процессами. Мы начинаем с нее, потому что основная задача операционной системы заключается в том, чтобы управлять пользовательскими приложениями. Раз мы говорим про подсистему управления процессами, первое с чего надо начать - это с определения “процесс”. Процесс характеризует некоторую совокупность набора исполняющихся команд, ассоциированных с ним ресурсов и текущего момента его выполнения, находящуюся под управлением операционной системы. Совокупность набора исполняющихся команд, с точки зрения принципа программного управления фон Неймана у нас выполнение программы - это последовательный выбор и исполнение команд из некоторого набора. Тогда понятно, что если мы реализуем некоторый процесс, то есть приложение запустили и оно как процесс теперь существует в операционной системе, то для нас процесс это в том числе набор вот этих исполняющих команд но почему мы не можем здесь поставить точку дело в том что программа в процессе ее исполнения это не только команда этой программы я могу запустить несколько экземпляров одной и той же программы ну например я зашел в одну консоль и запустил редактор Vim зашел в другую консоль запустил еще один редактор Vim. с точки зрения исполняемого кода, код абсолютно одинаковый набор команд но в одном я один файл обрабатываю в другом экземпляре я соответственно работаю с другим файлом. у меня поменялись ресурс ассоциированные с этими наборами команд, каждый экземпляр запуска моего, каждый процесс обладает своим собственным как минимум адресным пространством потому что раз я запустил два экземпляра Vim то это получается что я пользуюсь ими асинхронно как-то то это значит что у меня в памяти существует уже два набор этих команд, два сегмента с кодом. у меня могут быть разные естественно данные, я начал набирать текст он у меня где-то в памяти в виде данных хранится, в сегменте данных у меня тоже разные данные в разных экземплярах и открыл разные файлы при этом и это опять же ресурсы, соответственно получается что процесс это как минимум уже теперь набор команд и ассоциированные с ним ресурсы но и этого нам не хватает дело в том что эти процессы могут переключаться. мы можем по очереди передавать ресурс например центрального процессора, ядра отдельного центрального процессора разным процессам. это значит что процессы могут быть в состоянии действительно исполнения а могут быть в состоянии ожидания например когда мы опять предоставим возможность исполнится.тогда получается что мы должны иметь возможность потом восстановить исполнение этого процесса но тогда нам мало только набора команды ресурсов ведь на самом деле когда мы останавливали процесс, состояние процессора было каким-то конкретным и для того чтобы возобновить выполнение вот этого вычислительного процесса мы должны как минимум восстановить все эти регистры а кроме регистров у нас есть еще и другие составляющие которые в совокупности принято называть контекстом. ну например это стеки. у меня происходили какие-то вызовы процедур в том числе рекурсивные, соответственно нужно будет потом возвращаться после выполнения этих процедур, передавались параметры. вот уже получается эти три составляющие. ну и последний - находящиеся под управлением операционной системы. дело в том что процесс для операционной системы существует только до тех пор пока она может им управлять. ну а теперь опять же если мы оглянемся на несколько лекций назад то мы вспомним что мы при этом считаем что процесс для операционной системы это некая структура данных PCB или дескриптор процесса. операционная система создав процесс, создает вот эту структуру, заполняет ее данными, с процессом что-то происходит и у нас меняются эти данные мы уничтожаем процесс мы убираем соответствующую структуру. вот пока эта структура есть и пока операционная система может менять соответствующие данные для нее и существует этот процесс. поэтому мы говорим что процесс находится под управлением операционной системы. как все таки мы будем соотносить понятие процесса и понятия программы или приложения? здесь важно понимать что соотнесение этих понятий не является ему знаком равенства. дело в том что может быть ситуация когда в рамках одного процесса исполняется несколько разных программ и может быть ситуация когда одна программа порождает множество процессов. Второй случай наиболее понятен, например, я делаю большую сложную программу которая в том числе может быть и параллелизм использует и соответственно я могу исполняя одну программу, в конечном итоге запустить множество процессов. с другой стороны у меня может быть и другая ситуация, например, я делаю системный вызов и у меня выполняется код ядра но на самом деле исполнение этого года происходит в рамках выполнения конкретного процесса потому что этот код ядра выполняет привилегированную операцию но привилегированную операцию в логике выполнения этого процесса с этой точки зрения мы можем говорить что у нас это в рамках этого процесса происходит выполнение кода ядра. мы не можем строго поставить знак равенства между процессом и программой но теперь понимаем как они между собой соотносятся. развитие операционных систем и развитие в первую очередь понятия мультипрограммных работ и параллельного исполнения привело к тому что понятие процесс перестало удовлетворять как единственный элемент управления всеми вычислительными операциями. почему это так? дело в том что процессы, раз они имеют собственное адресное пространство с точки зрения концепции защиты адресного пространства должны быть изолированы друг от друга. теперь представим себе ситуацию у меня есть большая растровая картинка и мне нужно сделать над ними какие-то простые операции ну например их осветлить. Я могу делать эти операции независимо для разных групп пикселей и вообще даже для самих разных пикселей. у меня многоядерные процессоры или многопроцессорная вычислительная система, то есть у меня есть возможность параллельно вычислять эти значения параллельно осуществлять вычислительные операции. было бы хорошо тогда чтобы я взял эту картинку частями начал обрабатывать параллельно, я бы намного быстрее это сделал если нет другой нагрузки, но я не могу это сделать в логике управления процессами потому что у меня картинка будет в адресном пространстве одного процесса. соответственно один процесс - вот он один набор команд которые он выполняет. другой процесс не сможет получить доступ к этому же изображению, либо мне придется нарушать принцип этой изоляции. поэтому появилось правильное решение давайте мы внутри процесса разрешим создавать несколько наборов команд но эти несколько наборов команд естественным образом потянуть за собой связаны с ними контексты и дело в том что мы же не можем переключаясь между разными наборами команд не использовать их контекст. опять же регистру и контекст процессор это как минимум будет нужно тоже поменять если мы переключаемся между этими наборами, ну и стеки у них тоже должны быть разные, даже минимум этот говорит нам о том что у нас должна быть вот эта пара набор команд и соответствующий стек. и вот такая пара получила название - thread(поток,нить). соответственно тогда я скажу что у меня в общем случае мой процесс может включать в себя множество потоков. каждый из этих потоков это отдельный набор команд и контекст но при этом эти потоки имеют доступ к общему адресному пространству а в более широком смысле вообще к общим ресурсам относящимся к этому процессу. отсюда появилась модель когда стали говорить что процесс это просто контейнер ресурсов но в разных операционных системах отношения к этому немного разные поэтому мы не будем менять исходное определение процесса и его упрощать. мы можем создавать процесс и в не многопоточности и больше того огромное количество программ которые мы используем это не многопоточное решения. соответственно поэтому получается что в любой современной операционной системе запуск приложения это создание процесса и как минимум одного потока в рамках этого процесса. важно понимать что в большинстве современных операционных систем единицей диспетчеризации, собственно управления, планирования является как раз поток. то есть переключает и дает машинное время дает время вычисления на процессоре операционная система не процессом а отдельным потоком каждого процесса. это привело к следующим сложностям. во первых тогда получается что если я многопоточно написал какое-то свое приложение то исполнение этого приложения а именно переключения между потоками тогда возможно только через переключение в режим ядра. это добавит существенную нагрузку, накладные расходы. Во-вторых для того чтобы решать как управлять очередью из этих потоков у меня же будет какое-то большое количество процессов и каждый из них имеет какое-то количество потоков мне нужно будет иметь какие-то алгоритмы эти алгоритмы должны быть с одной стороны достаточно простыми иначе на их собственное вычисление будет съедаться слишком много ресурсов но при этом эффективные для широкого числа разных ситуаций потому что процессы разные. а алгоритм который должен принимать решение о распределении нагрузки между этими потоками должен быть один. и естественно чем более универсальный алгоритм мы пытаемся создать тем менее он будет эффективен но эта плата за универсальность и может тогда получиться ситуация что логика по которой будет работать операционная система предоставляя и переключая потоки моего процесса будет противоречить сценарию который я как разработчик закладывал. я бы хотел чтобы у меня например поровну получали процессы вычислительного времени, а операционная система обнаружила что какой-то один процесс более интерактивен чем другой, более интерактивному процессу начинает отдавать больше предпочтения. В результате у меня происходит рассинхронизация этих процессов и я теряю выгоду от многопоточности исполнения а может быть в некоторой ситуации может быть получаю ухудшение относительно ситуации когда я просто выполнял бы это все в однопоточном режиме. это привело к тому что появилась идея. а нельзя ли нам делать многопоточность на пользовательском уровне вне инструментария операционной системы и для этого решения появился еще один уровень иерархии которая получила название Fibre(волокно). это тоже разные наборы команд, это тоже разные контексты, но управление переключением между ними и планирование переключения в этом случае берет на себя код все того же самого потока но как правило в одном из волокон исполняющийся и мы получаем теперь уже управление многопоточностью на пользовательском уровне. для операционной системы вот этих всех волокон не существует, для нее есть один поток она ему дает временное использование ресурсов а уже внутри этого потока оказывается происходит переключение вот этих волокон. Плюсы:нет переключения в режим ядра, мы остаемся в пользовательском режиме,нет соответствующих накладных расходов; мы сами можем управлять. минусы: раз мы сами управляем то мы должны сами реализовывать алгоритмы отсюда накладные расходы на реализацию этих алгоритмов пока они будут выполняться, сложность разработки а значит уменьшается ее надежность и безопасность. возникает еще одна серьезная сложность ведь операционная система имеет штатный механизм который позволит ей переключать потоки - это таймер. а здесь у нас такого механизма нет, потому что обработчик прерывания приложению недоступен это прерогатива операционной системы тогда получается что основное решение которое здесь стали использовать - кооперативная многозадачность. идея кооперативной многозадачности заключается в том что само волокно в какой то момент времени отдаст управление либо следующему волокну либо специальному волокну который является диспетчером. фактически это значит что у нас в коде неким синхронным образом будет происходить вызов специальных каких-то функций и эти функции будут позволяет нам передавать вот это управление следующему волокну. но с другой стороны мы понимаем что тогда сбой например зацикливание кода может привести к тому что мы не дойдем до очередной функции передачи управления и на самом деле собьем всю эту модель многопоточного исполнения кода. поэтому эти облегченные потоки используют далеко не везде и не всегда. при этом поддержка их тоже есть на разном уровне. иногда поддержка есть на уровне операционной системы ну например windows насколько я помню полностью с windows 2000 начиная они стали это активно поддерживать, есть специальная библиотека которая позволяет мне работать вот с такими волокнами но это не значит что операционная система при этом поддерживает их на уровне планирования она просто предоставляет библиотеку для удобной разработки приложений с использованием этого механизма. иногда поскольку речь идет о пользовательском режиме это реализуется на уровне конкретного языка и технологий программирования ну например есть green потоки в Эрланге это как раз реализация этой идеи. Корутины на Kotline по большому счету если так задуматься они так себя не называют но это тоже облегченные потоки. они нужны для того чтобы обеспечить как раз управление и синхронизацию операций особенно интерактивных связаных с вводом-выводом в таком асинхронном режиме не зависящим от планировщиков операционной системы. это кстати позволяет в приложении на Kotline сделать сотню а то и тысячу вот этих легковесных потоков и при этом обеспечивает приемлемую производительность и даже наворот повышения производительности относительно классического многопоточного решения. уже получилось три уровня иерархии но дальше оказалось что даже этих трех уровней недостаточно чтобы управлять вычислительными процессами в операционной системе. возникла вот какая проблема. представим себе работу ну скажем браузера в этом браузере у нас множество вкладок первая мысль которая приходит в голову давайте сделаем так чтобы каждая вкладка это просто отдельный поток а все это будет один процесс браузера казалось бы логично одно предложение там одни ресурсы один процесс, а вкладки это разные потоки. но оказалось что это очень не удобно по ряду причин.во-первых в этой ситуации сложно обеспечить безопасность потому что код исполняющийся исполняющийся в разных вкладках имеет доступ к единому адресного пространства этого процесса а это значит что если в какой-то вкладки я запущу вредоносный код то он может например из другой вкладки считать хэши каких-то паролей,идентификаторы ключи сессий но и вообще говоря много чего плохого сделать. во вторых в такой ситуации мне в случае сбоев поскольку опять же адресное пространство одно будет сложно предотвратить ситуации когда сбой в коде какого-то одного потока реализующего одну из этих вкладок приведет к тому что будет нарушен соответственно данные или код в других каких-то вкладках. появляется мысль:ну хорошо давайте тогда мы просто сделаем иерархию процесс у нас будет некий корневой процесс он породит множество процессов следующего уровня и у нас каждая вкладка будет своим процессом. но тогда может быть вот какая модель,у меня на создавалась множество вкладок и при этом я запустил еще какой-нибудь word чтобы там набрать текст а теперь выясняется что с точки зрения внешнего вида у меня один браузер и 1 word а с точки зрения операционной системы у меня одна сотая это процессы ворда и еще 99 из 100 это процессы моего браузера а планировщик учитывает вообще говоря их всех на одном уровне. отсюда появилась идея что нужно научиться ограничивать доступ к ресурсам для некоторых групп процессов. в этой ситуации теперь у меня появляется еще один уровень иерархии теперь у меня тоже становятся много процессов и я создаю соответственно отдельный уровень который бы объединял некую совокупность процессов. в разных операционных схема он по-разному называется в терминологии windows это - job (задание,работа) термин который использовался до этого в более старых вообще в разных решениях еще на уровне программ диспетчеров мы создали задание как совокупность каких-то исполняемых дальше операции над данными.значит здесь в данном случае job это скорее набор квод для тех или иных ресурсов в Linux это - контрольная группа функционал на самом деле очень похож идея заключается в том что мы в рамках этой контрольной группы или задания можем установить квоту на суммарное использование процессорного времени на суммарное использование физических адресов памяти на суммарное даже использование доступа к диску или к какому-то устройству ввода-вывода. это уже вопрос что я реализую. важно то что у меня тогда может происходить вот такое квотирование и сделав в разных облаках одного задания мой браузер а в рамках другого задания например там какой-то офисный пакет я как раз и сбалансирует тем самым нагрузку между ними сделаю так что я смогу спокойно пользоваться этим офисным пакетом. вот мы получили вот эту иерархию но двигаясь дальше когда мы сейчас с вами начнем разговаривать уже о том как операционная система исполняет те или иные операции мы на самом деле будем немножко упрощать модель и в основном говорить о процессах немножко говоря о процессах и потоках. понятно что это более сложная модель но если мы попытаемся сразу же разбираться на всех четырех уровнях это скорее всего приведет к некоторому хаосу у нас в понимании. логично тогда нам начать с того чтобы попытаться представить себе перечень уже конкретного функционала подсистемы управления процессами а дальше начать разбираться как каждая из этих функций будет выполняться. основные функции которые есть у подсистемы управления процессами: создание. процесс нужно создать причем мы теперь понимаем что это сознание процессов и потоков потому что мы должны в рамках процесса создать как минимум один поток исполнения; обеспечение ресурсами. обеспечение ресурсами созданному процессу в момент создания и дальше по ходу нужны будут ресурсы (память файлы сетевые порты и так далее); изоляция. мы должны обеспечить изоляцию процессов друг от друга; планирование - это решение о том в каком порядке и в каком объеме предоставлять доступ процессу или потоку к тем или иным ресурсам; диспетчеризация - это уже исполнение нашего плана, это переключение процессов между различными состояниями между тем что процесс исполняет сейчас или он чего-то ждёт или он из состояния ожидания каких-то одних ресурсов или собственные ожидания какие-то других ресурсов; взаимодействие. мы должны придумать что то чтобы процессы преодолевая изоляцию друг от друга могли тем не менее взаимодействует друг с другом.Например вы запускаете конвейер процессов тем самым процессом обеспечена взаимодействие между собой но как если они на самом деле не могут работать с данными друг другу поскольку у них нет доступа к адресному пространству друг другу; синхронизация. еще более тяжелая проблема, процессы могут начать конфликтовать между собой за ресурсы то есть процессы могут попытаться например обратиться к не разделяемому ресурсу а за счет того что у нас мультипрограммность они это сделают по очереди не завершив каждый свое обращение но и в результате приведут к какому-то коллапсу вплоть до аппаратных каких то проблем на соответствующем устройстве. мы должны будем обеспечить синхронизацию то есть обеспечить одновременно и исполнение условий взаимоисключения наличия прогресса и отсутствие голодания; уничтожение. мы должны уничтожить процесс после того как он завершил работу поскольку мы знаем что процессов на самом-то деле структура данных, мы должны как бы тоже структуру данных уничтожить и это тоже непростая задача. вот что делает подсистема управления процессами ну а теперь мы должны будем с вами попытаться понять а как она это делает. ну и начнем мы собственно с первого пункта. читая литературу по разным операционным системам вы почти всегда встретите термин “рождение процесса” это не потому что специалисты по операционным системам это такие вот образно мыслящие люди которые отождествляют процессы с чем-то живым и соответственно говорят о том что процесс родился,это действительно связано с тем что термин рождения и вообще как бы связь тем самым между процессами очень хорошо характеризует реальное устройство механизмов операционной системе а именно в операционной системе любой процесс порождается другим процессом. процесс не создается абстрактно кем-то извне процесс имеет родительский процесс любой процесс породил другой какой-то процесс. а кто тогда породил первый процесс? мы попадаем в эту самую ситуацию проблема курицы и яйца.пока мы будем считать что эта начальная проблема имеет какое-то решение поэтому у нас есть процесс порождения вот этих процессов и тогда у нас появляется иерархия процессов. эта иерархия процессов будет разная у разных операционных систем и во многом будет создавать их отличие. второе отличие будет в организации структур данных но про структуры данных мы более-менее сейчас сможем тем не менее показать некую обобщенную структуру которая в той или иной степени будет характеризовать нам любую операционную систему. что у нас будет храниться в process control блоке ну или соответственно в дескрипторе процесса?мы можем сказать что там будет несколько категорий информации - это информация по идентификации процесса. в любой операционной системе у любого процесса существует как минимум один идентификатор это PID(англ. Process IDentifier;рус. Идентификатор процесса). идентификатор процесса - уникальный числовой целочисленный номер который мы присваиваем каждому процессу. в многих операционных системах есть еще PPID(рус.Идентификатор родительского процесса) как мы сейчас выясним дальше на примере linux нам важно знать а кто является родителем у данного процесса процесс должен знать своих родителей но кстати родителю тоже неплохо бы знать кто его дети. очень часто у нас используется UID(идентификатор пользователя, запустившего процесс).процесс работы исполняясь на самом деле обращается к каким-то ресурсам но обращаясь к ресурсам мы знаем что операционная система будет пытаться определять права то есть а имеет ли право на доступ данный процесс к этому ресурсу и для того чтобы это сделать процесс должен быть ассоциирован с неким пользователем кто этот процесс запустил то есть грубо говоря тот же самый редактор Vim мог запустить я, мог запустить как пользователь рядовой, мог запустить руд и соответственно в одном случае я к системным файлам на редактирование должен получить через Vim доступ а в другом случае нет, получается что это же процесс получает доступ к файлу, но тогда этот доступ должен регулироваться правами которые связаны не с процессом а с пользователем который его запустил поэтому я должна иметь каким-то образом сведения об идентификаторе соответствующего пользователя. ну а дальше на самом деле можно продолжать просто в том же linux есть еще гид группа у групп идентификатор а потом выяснится что гид может быть еще реальный и эффективные и вот мы получаем такую значительно более сложную систему связанную с идентификатором. дальше у нас должна быть информация по состоянию - статус/контекст. естественно мы сохраняем сам по себе контекст процесса и в промежутках между тем когда процесс исполняется очевидно что этот контекст где-то в этих же структурах ну или во всяком случае в подчиненных структурах должен сохраняться ну кроме того мы должны еще знать статус процессов. Вот у меня процесс ждет операции ввода-вывода с диском а если мне теперь к этому процессу придет прерывание от клавиатуры мне можно его прервать или нет, если я скажу можно я могу нарушить нормальное выполнение программы если скажу нельзя то если у меня ошибка сейчас чтение данных из за этого процесса завис он не может завершить операцию а я не могу прервать у меня как бы прерывание там от клавиатуры или от мышки соответственно туда просто не дойдут. и у нас есть история - что происходило с этим процессами как история болезни. сколько раз просил операцию ввода-вывода конкретную,когда давали - сколько раз отказали, сколько выполнялся на процессоре сколько из этого времени появлялся в режиме ядра соответственно сколько выполнялся в пользовательском сколько раз переключали его сколько раз мы его отрывали от процессора и переключали режим готовности пока он ждал следующей попытки выполнится. вот этих параметров на самом деле много, конкретные их значения будут зависеть даже не просто от операционной системы а от версии этой операционной системы от того какой планировщик там будет например там в более старых версиях Linux вы встретили бы одни наборы данных истории а потому что там использовался u1 планировщик в более новых версиях когда стал использоваться sfs там соответственно тут же поменялся набор параметров потому что логика алгоритма и структура данных с которыми эти алгоритмы работают они поменялись но тем не менее в любом случае вот этот блок истории у нас тоже есть. с этой позиции создать процесс это создать вот эту структуру данных. вопрос опять же как ее создать? и вот здесь уже начинаются очень существенные отличия. в Linux процессы порождаясь образуют дерево(граф в котором нет циклов и в котором у нас при этом существует направленность всех наших связей то есть мы на самом деле знаем кто кого породил, у нас есть корень) вот этот корневой процесс в Linux будет называться init. у него будет бит равен единице, PPID равен нулю при этом не будет никакого процесса с PID 0 это будет такая как бы уловка для того чтобы у него на самом деле породитель вроде какой-то был при этом родителя по факту нет. в Linux таких деревьева 2 потому что отдельно сделано дерево для пользовательских процессов а еще есть отдельно дерево для потоков ядра у него самостоятельный корень и дальше от него порождаются все потоки ядра уже. вот но не суть важно потому что логика работы этих деревьев практически одна и та же поэтому можем рассмотреть на примере на пользовательскую деле она все-таки более живое в плане того что админу в потоке ядра админ руками все равно не лезет ну как правило потому что это там безнадежно ну вот а здесь как раз все управление применяется и так в линуксе вот это порождение процесса происходит методом клонирования то есть когда вот этот процесс а породил некий процесс b на самом деле что произошло был некий специальный системный вызов for который сделал полную копию адресного пространства родительского процесса если а после этого не буду делать никакие другие системные вызовы то вообще говоря я могу взять и делегировать часть исполняемого какого-то своего функционала просто в другой процесс это уже будет достаточно в ответ на ford родительскому процессу будет сообщен пит ребенка а у ребенка будет установлен новый пит который мы будет выдан операционной системы в качестве портфель будет установлен бит его родители челы notification этим сам произойдет а вот все остальное включая кстати данные по идентификации типа и вида от наследуется от родительского процесса чем нам это классно поможет дело в том что в такой ситуации у нас родительский процесс получит ровно столько прав и возможностей сколько было у родительского дочерний процесс унаследует от родители его права и возможности он унаследует от него например таблицу обработчиков сигналов он наследует от родителя там сведения о доступе файловой системе и так далее значит заряда как бы как минимум помогает нам с точки зрения безопасности мы знаем что никакой дочерний процесс не получит прав больше чем было в его родителям и ниоткуда и взять но не всегда мы хотим естественно чтобы код при этом тоже про дублировался поэтому по факту дальше выполняется какой-то из системных вызовов из группы y как правило казаками хотя может быть там и другие варианты который заменит теперь код сегмент кода процесса б на какое-то другое приложение вот я запустил скрипт скрипт . 1 page а он вызвал команду греб но и прекрасно вот соответственно как бы это теперь создала сколько адресного пространства процесса скрипта от персик нет кода заменился на код гриппа ну и пожалуйста теперь мы встали на указатели на mail условно говоря да на начало и с этого указателя мы начали выполнять в сегменте кода исполнять наши команды значит когда процесс при этом завершается он отсчитывается своему родителю о завершении причем процесс может завершиться штатно да как бы систему вызовом экзит или он может завершиться нештатно например в поймав сигнал от операционной системы на завершение например процесс попытался сделать что-то нехорошее типа деление на ноль или обращение в чужие памяти в ответ поймал сигнал от операционной системы обработчик сигнала завершил этот процесс но в любом случае родителю придет специальный сигнал в линуксе это sick child сигнала то что его потомок прекратил существование вернее не прекратил существование а завершил работу и дальше родительский процесс должен будет читать код завершения дочернего вот это как раз на вы позволяет обеспечить преемственность процессов и контроль за их исполнением то есть я могу получая доступ мне дает операционная система доступ через специальный системный вызов уэйд прочитать ситуации код завершения дочернего процесса дальше могу его обработать какой-нибудь там tracked конструкцию его облечь еще что-то придумали того чтобы соответственно этот код завершение обработать и принять какие-то выводы по этому поводу вот эта иерархия в свою очередь она приводит к ситуации когда потенциально меня может оказаться ситуация когда у меня например вот этот процесс а завершил работу вор бы даже а война до того как завершил процесс б если процесс а шла про завершает работу то как правило он посылает всем своим дочерним процессом там сектор миллисекунд и они все потихонечку завершаются корректно а уже после этого по поймав от них от всех sick child и с читов и кодов завершения что они корректно завершились это уже окончательно завершается родительский процесс ну и сирийский процесс умер неожиданно из-за какой-то аварийной ситуации его дочерний процесс осиротел значит плюс он сел у меня с этим бороться осиротевший процесс будет тут же независимо от уровня например если вот так вот кто то же все они будут усыновлены или удочерил и не знаю какой у процесса пол родительским вот эти вот корневым процессов то есть они там или систем де почему это произойдет а потому что дерево не должно стать несвязанным графа меня не может какая-то ветка или какой-то отдельный процесс как лист да вдруг оторваться значит почему потому что когда завершится вот этот процесс теперь он должен кому-то во-первых sky что он завершился второй кто-то должен его сигнал его код завершения тоже все таки сочетать ну а собственно говоря и не ты ли чести в день умеют это делать и они всегда эту операцию завершат правда в линуксе есть одна не очень красивая ситуациям и они потом подробнее поговорим на следующей нашей лекции это когда у нас родительский процесс жив а вот исполнять свои обязанности по тому чтобы читать код возврата код завершения вернее да и его обработать не может вот если так произойдет то тогда вот такой процесс он станет зомби процессом то есть процессом которые на самом деле и не умер до конца но не умеет он убил но при этом мы не можем его окончательно выкинуть из операционной системы на все она будет существовать в этом вот странном состоянии зомби процесса но об этом еще раз для любой поговорим подробнее на следующей лекции когда вообще будем разбирать разные состояния процессов и так эта модель как у нас рождение процессов происходит в линуксе windows все на самом деле существенно проще но и только на первый взгляд у меня есть диспетчер процессов ну естественно это тоже бросается который порождает все процесс и является родителем их ну вернее как у меня все есть родительский процесс но он не сам породит дочерних путем клонирования собственного адресного пространства нет он сделает системный вызов сюда диспетчер сказал что ему нужен потомок диспетчер уже в ответ создаст потомка родителю скажет отчитается что все удачно произошло и такая система похоже на инкубатор в этой ситуации есть свои плюсы и свои минусы понятно что в этой ситуации диспетчер осуществляет централизованный тотальный контроль за появлением всех процессов а значит на самом деле его удобно регулировать с этой точки зрения управления планирования работы операционной системы вы планировали рождаемости здесь можно делать очень четким с другой стороны вот здесь как раз появляется гибкость но она же имеющая обратную сторону медали потому что процесс идти право возможности которые приобретет порождаемый процесс они будут определяться обеспечиваем процессов и формально я могу создать процесс с правами выше чем у родительского процесса понятно что скорее всего большинстве случаев будут механизмы операционной системы которые будут это пытаться контролировать и препятствовать но это их можно пытаться ломать здесь такой механизм просто нету и поэтому лавой деловая по-другому не сделаешь а здесь у меня всегда будет оставаться некую уязвимость которую нужно себе будет закрывать а значит на ее выполнение нужно будет тратить соответственно определенное время это вот как бы такая некая принципиальная соответственно в этом смысле разница насчет и так это вот создание процесс теперь про создания процесс мы с вами поговорили дальше обеспечение ресурсами обеспечение ресурсами у нас происходит в разные моменты понятно что когда процесс только создается он уже обеспечивается определенными ресурсами вы говорили до копируются адресное пространство значит появляется свое адресное пространство процесса значит может быть при этом сразу же какой-то файл этот процесс при старте будет открывать соответственно дескриптор этого файла у нас тоже будет обеспечен этого процесса обычно говорят что тем самым мы обеспечили процесс статическими ресурсами то есть ресурсы которые вам самом начале выделены но и видимо до окончания они будут ему принадлежать но есть еще динамические ресурсы когда процесс в процессе своего исполнения что-то просит ну во первых в какой-то степени динамическому ресурсов можно считать даже процессор на и время процессах время хочет выполнять свои команды выполнять его хочешь на процессоре начнут динамически иисус плюс процессы часто хотят больше памяти дабы соответственно может затребовать добавляется расширения нашего адресного пространства естественно процесса хотят больше открытых файлов значит все вот эти вот ресурсы обеспечение этими ресурсами это получается задачи связанные с либо планированием во времени либо планированием и условно говоря в пространстве вы помните да что когда мы рассуждаем а что по задаче линейного или динамического программирования поговорим с у нас есть обычно 2 класса таких задач эта задача расписания задача рюкзаки если бы мы решаем в каком порядке да выполнять какие-то операции ли вы бы лишаем в каком порядке уложить в каком-то замкнутом пространстве набор предметов здесь приблизительно то же самое когда мы говорим обеспечение ресурсами это либо решение задачи планирования ну и в этой степени на самом деле мы вылетели вот здесь вот в отдельный пункт потому что дальше планирование она шире но она не сводится к планирование только с точки зрения обеспечения ресурсов или задача называемые аллокация локаторы да то есть предоставление и расположение в каком-то адресном пространстве как правило потому что у нас с этой точки зрения нас пространство пространство адресов адреса оперативной памяти адреса блоки на жестком диске это в любом случае задача аллокации то есть я должен файл разместить каких-то блоков диска я должен соответственно страницы памяти разместить в памяти это вот обеспечение ресурсами мы не будем сейчас про него подробно говорить потому что поскольку опять же ресурс это разные мы будем с вами добирает на тех или иных ресурсов ну например договора для оперативной памяти добираясь до оперативной памяти добираясь до дискового пространства как раз дальше и показывать специфику обеспечения ресурсами на этих уровнях значит пока все посчитаем что поговорим изоляция ну про изоляцию на самом деле мы уже говорили на предыдущим витке спирали и дальше мы они поговорим тоже в двух разных контекстах мы когда будем говорить про память и про работу с адресами про разные модели работы с адресами мы одновременно с этим вынужденным образом будем рассуждать и про то какой то ситуация обеспечивается изоляция ну вот второй момент это когда у меня с вами говорить про синхронизацию про соответственно там в том числе тупике там мы тоже на самом деле коснемся и вопросов связанных с изоляцией в этом отдельно опять же это не будет планирование вот планирование это вообще будет отдельная лекция потому что планирование как мы выясним это очень многоуровневый процесс надо планировать давать ли процессору процессор на и время это надо планировать давайте процессору возможность располагая процессу располагать своей странице физической памяти ли он должен эти стране содержать файл подкачки страничного обменом менять это планирование очередей на ввод-вывод устройству к любому жесткого диска к сети к чему угодно за концов это ща планирования самой рождаемости позволит ли процессу родиться тоже вопрос может быть он сейчас родится это приведет к краху системы которые уже там на грани вся переполнена там процесса просто все свои ресурсы съели на него родится ещё одного процесса все закончится плохо поэтому про планирование это у нас будет отдельный разговор отдельной лекции диспетчеризация но вот диспетчеризации мы сейчас с вами вернемся поэтому бака галочку не обведу и пару слов по поводу остальных значит взаимодействие процессов в рамках этого курса мы будем касаться достаточно слабо потому что за его аресте процессов существенно отличается и кардинальное мерзкого отличается в разных операционных системах в линуксе это механизм сигналов там это механизм связанный с конвейером именован ими каналами это механизм связанные с сокетами поэтому дальше уже в отдельно курсе администрированию linux скорее всего их курсе active directory которые тоже вам будет читаться всем ведущим перечню вот там эти вопросы мы разберем более менее подробно водку поэтому в этом курсе мы вас упоминает что эта проблема есть и наверно вопрос закрываем синхронизация это будет отдельные лекции я даже может быть там чуть больше и почти две реакции где мы как раз разберемся вот а вот будет всякие на слуху крутящиеся такие термины типа семафор имеют x и тупике дам де лакло яблок да и так далее вот это все вот здесь нам о синхронизации то есть это мы отдельно изберем уничтожение но вот уничтожение это на самом деле процесс тоже как бы кажущейся простым казалось ну что протоколов вы должны взять посту стереть такую структуру освободить пит и сказать все процессы лет но процесс имел ресурсы ресурсы он эти имел в том числе такие которые требуют для их освобождения как минимум удостовериться что использование этого ресурса корректно завершилась а может быть его корректно завершить ну например тот же даже работа с дисками с каким-то файл мне открыл файл я сохранил в него данные но это на самом деле совершенно не факт что данные синхронизировались на физический носитель во-первых большинство файловых систем использует механизм отложенные записи для оптимизации своей работы и работы с очередями доступа к данным на этом устройстве хранения используется механизм когда я накапливаю гуфи рисую требование к на запись каких-то данных и потом оптом блоком да еще может быть переставить их местами чтобы потом меньше гонять головку на диске я осуществлю соответственно запись на этот диск в этой ситуации у меня может получиться так что процесс завершился он считает процесс что он записал данный файл на самом деле реально запись еще не произошло операционной система должна эту запись тогда принудительно вот в этот момент сделать потому что потока процесс будет уничтожен уже как бы адресное пространство не существуют важничать куда не сохранить будет соответственно могут быть блокировки всякие то есть процесс пока работал требовал ресурсы поскольку эти ресурсы были не разделяемыми то ему их еще и заблокировали то есть под него задайте блокировки надо снять противном случае следующий процесс просто не сможет выполнить он упрется в недоступность ресурсов хотя по большому счету кое-что уже ресурс свободен процесс которые вот использовал завершён ну и наконец мы должны обеспечить вот эту вот отчетность то есть родительский процесс должен получить код возврата вы должны проанализировать что он его получил для того чтобы корректно цепочки до порождения процессов завершились а может быть кстати еще и посмотреть нет ли у нашего процесса который сейчас мы уничтожаем потомков потому что с ней что-то надо делать может быть их надо установить может быть их нужно просто тоже завершить а если кто-то совершить каскадно ставят задачи связанные тогда с ними все то же самое сделать поэтому это вот как бы задачу уничтожения получается тоже специфична и обладает своими требованиями своими лагает вами которые будут ее решать ну и теперь вернемся к диспетчеризации диспетчеризация фактически эта процедура связанная с переключением процессов то есть мы меняем состояние процесса значит самая простая диспетчеризация связано с просто тем что процесс исполняется сейчас на процессоре или процесс соответственно нами вытеснен потому что вы дали возможность выполняться следующему с этой точки зрения не важно по какой че не произошло вытеснение таймер сработал или сам процесс решил что ему операций ввода-вывода нужно сработала какая-нибудь защита и соответствующий сигнал у нас получился важно то что мы должны взять и поменять соответственно процесс вот эта смена происходит в три шага мы сохраняем контекст одного процесса во первых вещь про регистры в данном случае контекст мы загружаем в процессов регистры процессора контекста другого процесса а потом меняем их состояния весь забавная штука дело в том что станет над поменять у двух процессов но вот эта операция смена состоянии почему-то должна быть а там арно и понятно почему потому что в противном случае мы получим неуправляемое состояние системы то есть я поменял одному процессу уже состоянии с того что он ожидает на то что он теперь исполняется следующим шагом хотел поменять другому данные что не исполняется ожидает тут не произошло прерывание таймер сработал еще какое-то прерывание я передал управление обработчика прерываний и теперь я получаю состояние когда у меня два процесса и оба находятся в состоянии что они исполняются в эту ситуацию это как два меча на поле игра должна быть остановлена все уже невозможно управлять такую игру я могу по наоборот решить сделать сначала 1 процессу поменять с исполнения состояние на то что он ожидает потом другого с ожидания на исполнение но опять же произошел его прерывания и у меня вообще нет никого кто исполняется что вот этого не происходило используется одна хитрый механизм и про них поговорим подробнее как раз при синхронизации частности например есть операционной системы которую вы до станции переходит в одно программный режим они просто запрещают любое прерывание пока не выполнит вот эту операцию связанную со сменой статусу и только потом снимает этот на программный режим вот там тоже своей проблемы если в процессе выполнения той операцию не произошел сбой то все у меня как бы сделать уже не я ничего не смогу у меня полностью остановился работа моей вычислительной системы значит и но это сейчас бы это просто сама процедура переключения но на самом-то деле нас же интересует не столько процедура переключения сколько нас интересует а между какими состояниями это переключение может происходить ведь действительно но первое что приходит волос процесс выполняется или он сейчас чего-то ждёт но ждать то он может очень разных вещей и поэтому мы с вами на следующей лекции как раз начнем разбирать вот эти вот возможные состояния процессов и правила по которым они могут переходить друг другу между этими состояниями частности мы выясним что у разных операционных систем это разные модели состояния и есть состояние характерные только для каких-то одних систем месте я которые есть у любой операционной системы а это в свою очередь вот эти вот диаграммы состояний нам покажут и подведут нас к задачи планирования поэтому мы следующую нашу лекцию начнем с диспетчеризации ну и потом с диспетчеризации перейдем на планирование а после планирования уже на синхронизацию и тем самым завершим цикл лекций связанных с управлением процессами вот это пожалуй в этом смысле мы не можем даже это не называть. |