Раздели на сайта
Избор на редактора:
- Използване на стилове в Excel Как да създадете свой собствен нов стил
- Какви грешки възникват по време на инсталацията?
- Социален статус на човек в обществото
- Пълна интерпретация на грешките
- Как да се обадите директно на „жив“ оператор на Beeline: безплатни телефонни номера
- Основни PDF четци
- Lineage II - Interlude: The Chaotic Throne няма да започне?
- Възстановяване на парола за Excel
- Как да добавите нов циферблат на смарт часовници с Android Wear
- Най-печелившият тарифен план Life
реклама
Многозадачно програмиране в Linux. Предистория на многозадачното програмиране на Linux и управление на приоритетни процеси |
Linux- многозадачност и много потребители операционна системаза образование, бизнес, индивидуално програмиране. Linux принадлежи към семейството на UNIX-подобни операционни системи. Linux първоначално е написан от Линус Торвалдс и след това е подобрен от безброй хора по света. Това е клонинг на операционната система Unix, една от първите мощни операционни системи, разработени за компютри, но не е безплатна. Но нито Unix System Laboratories, създателите на Unix, нито университетът Бъркли, разработчиците на Berkeley Software Distribution (BSD), са участвали в създаването му. Един от най интересни фактиот историята на Linux е, че хора от цял свят са участвали едновременно в създаването му - от Австралия до Финландия - и продължават да го правят и до днес. Linux първоначално е проектиран да работи на 386 процесор. Един от първите проекти на Линус Торвалдс беше програма, която можеше да превключва между процеси, единият от които щеше да отпечата AAAA, а другият да отпечата BBBB. Тази програма впоследствие прерасна в Linux. Би било по-правилно да се каже, че Линус е разработил ядрото на ОС и той е отговорен за неговата стабилност. Linux поддържа повечето популярни Unix софтуер, включително графична система X Window - и това е огромен брой програми, но си струва да се подчертае, че Linux идва АБСОЛЮТНО БЕЗПЛАТНО. Най-много, което трябва да платите, е опаковката и компактдиска, на който е записана дистрибуцията на Linux. Дистрибуцията е самата ОС + набор от софтуерни пакети за Linux. Също така си струва да споменем, че всичко това идва с изходния код и всяка програма, написана под Linux, може да бъде модифицирана, за да отговаря на вашите нужди. Това също ви позволява да прехвърляте всяка програма на всяка платформа - Intel PC, Macintosh. Между другото, всичко по-горе се случи благодарение на Фондацията за свободен софтуер, фонд безплатни програми, който е част от проекта GNU. И именно за тези цели е създаден GPL - General Public License, въз основа на който Linux е безплатен, както и целият софтуер за него, а търговската употреба на софтуер за Linux или негови части е забранена. конфигурационна система unix linux Освен горното, Linux е много мощна и стабилна операционна система. Използването му в интернет се отплаща, а хакването му не е толкова лесно. Днес развитието на Linux следва два клона. Първият, с четни номера на версията (2.0, 2.2, 2.4), се счита за по-стабилна и надеждна версия на Linux. Вторият, чиито версии са номерирани с нечетни номера (2.1, 2.3), е по-смел и по-бързо развиващ се и следователно (за съжаление) по-богат на грешки. Но това е въпрос на вкус. В Linux няма разделение задвижва C, D, а процесът на комуникация с устройства е много удобен. Всички устройства имат свои собствени системен файл, всички дискове са свързани към една файлова система и всичко изглежда монолитно, едно. Ясната структура на директорията ви позволява незабавно да намерите всяка информация. За библиотечни файлове - собствена директория, за стартирани файлове - собствена, за файлове с настройки - собствена, за файлове на устройство - собствена и т.н. Модулността на ядрото ви позволява да свържете всякакви OS услуги, без да рестартирате компютъра. Освен това можете да преработите самото ядро на ОС, тъй като изходните кодове на ядрото също са налични във всяка дистрибуция. Linux OS много умело, така да се каже, използва идеята за многозадачност, т.е. всички процеси в системата се изпълняват едновременно (сравнете с Windows: копирането на файлове на флопи диск и опитът за слушане на музика в този момент не винаги са съвместими). Но не всичко е толкова просто. Linux е малко по-сложен от Windows и не всеки може лесно да премине към него след използване на Windows. На пръв поглед може дори да изглежда, че е много неудобно и трудно за конфигуриране. Но това не е вярно. Целият акцент на Linux е, че можете да го персонализирате за себе си, да го конфигурирате така, че да изпитате голямо удовлетворение от използването на тази операционна система. Огромен брой настройки ви позволяват да промените външния (и вътрешния) вид на операционната система, а не една единствена Linux система ще бъде подобна на вашата. В Linux имате избор при използване на графична обвивка, има няколко. офис пакети, сървърни програми, защитни стени... Просто цял куп различни програмиза всеки вкус. През 1998 г. Linux беше най-бързо развиващата се сървърна операционна система, като приемането се увеличи с 212% през тази година. Днес има повече от 20 000 000 потребители на Linux. Под Linux има много приложения, предназначени и за двете домашна употреба, както и за напълно функционални UNIX работни станции и интернет сървъри. Linux вече не е просто операционна система. Linux все повече се превръща в култ. Достигането до истината в случай на култ става все по-трудно. Да започнем с фактите. Така че Linux е:
Новобранците в Linux са привлечени преди всичко от факта, че е „готин“ и модерен. Има мит, че тази операционна система не е наистина подходяща за крайния потребител. За да се сглоби надежден и устойчив на хакове сървър, това е повече от добро решение, но не и за прост потребителкойто иска комфорт, удобство и изобщо не иска да разбере и усети системата, с която работи в момента. Това не е съвсем вярно. Персонализираната Linux система с графичен интерфейс е лесна за използване и интуитивна като операционна система на Microsoft. Просто настройването на Linux изисква много усилия и знания. В резултат на тези характеристики на своето създаване и развитие, Linux придоби много специфични „черти на характера“. От една страна, това е типична UNIX система, многопотребителска и многозадачна. От друга страна, има типична система от хакери, студенти и изобщо всякакви хора, които обичат непрекъснато да учат и разбират всичко до най-малкия детайл. Гъвкавостта на настройката и използването на Linux вероятно няма равна. Можете да го използвате на нивото, на което работи win95 - тоест да имате графичен десктоп с всички негови функции под Windows: икони, лента на задачите, контекстно менюи т.н. Освен това можете да инсталирате работен плот, който няма да се различава по нищо външен види функции от Windows. (Най-общо казано, опции мениджъри на прозорципод Linux просто няма край, от супер-спартанския icewm до супер-сложния Enlightment + Gnome). От друга страна, Linux ви дава безпрецедентен достъп до хардуера на всяко ниво на достъпност. Вярно, за това няма да е достатъчно да можете да пляскате с десния бутон на мишката; ще трябва да научите SI и компютърната архитектура. Но човек, който веднъж е усетил тази миризма на мисъл, това вдъхновение на програмист, когато държите машината „за ушите“ и можете да правите с нея буквално всичко, на което е способна - такъв човек никога няма да може да се върне меките лапи на Windows. Ако при използване на търговска операционна система потребителят е принуден да изчака пускането на следващата версия, за да получи система без проблеми и грешки от предишната версия, тогава модулността на Linux ви позволява да изтеглите ново ядро, който се пуска поне веднъж на два месеца или дори по-често (стабилна версия) . Отговори на въпроса "Какво е Linux?" можете да намерите много. Много хора вярват, че Linux е само ядро. Но само ядрото не е от полза за потребителя. Въпреки че ядрото несъмнено е основата на операционната система Linux, потребителят трябва да работи с приложни програми през цялото време. Тези програми са не по-малко важни от ядрото. Следователно Linux е колекция от ядро и основни приложни програми, които обикновено се инсталират на всеки компютър с тази операционна система. Комбинацията от ядрото и приложните програми в едно цяло е отразено и в името на системата: GNU/Linux. GNU е проект за създаване на набор от програми, подобни на това, което обикновено придружава Unix-подобна система. Често срещано оплакване на поддръжниците на Linux е, че когато говорят за предимствата на Linux, те изброяват недостатъците на Windows. Но това често е неизбежно, тъй като всичко се научава чрез сравнение и повечето компютърни потребители вече са запознати само с Windows. И така, какво ви дава Linux? Оригинал: Леки процеси: Дисекция на Linux нишки Тази статия, предназначена за разработчици на Linux и студенти по компютърни науки, обхваща основите на нишките и тяхното внедряване с помощта на леки процеси в Linux, с примери за изходен код за по-добро разбиране. Програмните нишки са основният елемент на многозадачна софтуерна среда. Програмната нишка може да бъде описана като среда за изпълнение на процес; следователно всеки процес има поне една нишка. Многонишковостта включва наличието на множество паралелни (на многопроцесорни системи) и обикновено синхронизирани среди за изпълнение на процес. Програмните нишки имат свои собствени идентификатори (ID на нишка) и могат да се изпълняват независимо една от друга. Те споделят едно нещо помежду си адресно пространствопроцес и да използват тази функция като предимство, което им позволява да не използват IPC канали (междупроцесни комуникационни системи - споделена памет, канали и други системи) за обмен на данни. Нишките на процес могат да си взаимодействат - например независими нишки могат да получат/променят стойността на глобална променлива. Този комуникационен модел елиминира допълнителните разходи за IPC повиквания на ниво ядро. Тъй като нишките работят в едно адресно пространство, превключванията на контекста на нишките са бързи и не изискват много ресурси. Всяка програмна нишка може да се обработва индивидуално от планировчика на задачи, така че многонишковите приложения са много подходящи за паралелно изпълнение на многопроцесорни системи. Освен това създаването и унищожаването на нишки е бързо. За разлика от повикването fork(), нишката не създава копие на адресното пространство на родителския процес, вместо това нишките споделят адресното пространство заедно с други ресурси, включително манипулатори на файлове и манипулатори на сигнали. Многопоточното приложение използва ресурсите оптимално и възможно най-ефективно. В такова приложение програмните нишки се справят с различни задачи, като се има предвид оптималното използване на системата. Една нишка може да чете файл от диск, друга може да записва данни в сокет. И двете нишки ще работят в тандем, като са независими една от друга. Този модел оптимизира използването на системата, като по този начин подобрява производителността. Няколко интересни функцииНай-известната функция при работа с нишки е тяхната синхронизация, особено когато има споделен ресурс, маркиран като критичен сегмент. Това е сегмент от код, който има достъп до споделен ресурс и не трябва да бъде достъпен от повече от една нишка по всяко време. Тъй като всяка нишка може да се изпълнява независимо, достъпът до споделения ресурс не се контролира, което води до необходимостта от използване на примитиви за синхронизация, включително мутекси (взаимно изключване), семафори, брави за четене/запис и други. Тези примитиви позволяват на програмистите да контролират достъпа до споделен ресурс. В допълнение към горното, нишките, подобно на процесите, са податливи на влизане в състояния на блокиране или изчакване, ако моделът на синхронизация не е проектиран правилно. Отстраняването на грешки и анализирането на многонишкови приложения също може да бъде доста тромаво. Как се реализират нишките в Linux?Linux ви позволява да разработвате и използвате многонишкови приложения. На потребителско ниво внедряването на нишки в Linux следва отворения стандарт POSIX (интерфейс на преносима операционна система за uniX). Unix системи), обозначен като IEEE 1003. Библиотеката на потребителско ниво (glibc.so на Ubuntu) осигурява изпълнение на POSIX API за нишки. В Linux програмните нишки съществуват в две отделни пространства - потребителско пространство и пространство на ядрото. В потребителското пространство нишките се създават с помощта на API, съвместим с POSIX pthread библиотека. Тези нишки на потребителското пространство са неразривно свързани с нишките на пространството на ядрото. В Linux нишките на пространството на ядрото се третират като "леки процеси". Лекият процес е единица от основната среда за изпълнение. За разлика от различните варианти на UNIX, включително системи като HP-UX и SunOS, Linux няма отделна система за нишки. Процес или нишка в Linux се третира като "задача" и използва същите вътрешни структури (серия от структури struct task_structs). За редица нишки на процеси, създадени в потребителското пространство, има редица леки процеси, свързани с тях в ядрото. Един пример илюстрира тази точка: #include Използвайки помощната програма ps, можете да получите информация за процеси, както и леки процеси/нишки на тези процеси: kanaujia@ubuntu:~/Desktop$ ps -fL UID PID PPID LWP C NLWP STIME TTY TIME CMD kanaujia 17281 5191 17281 0 1 Jun11 pts/ 2 00:00:02 bash kanaujia 22838 17281 22838 0 1 08:47 pts/2 00:00:00 ps -fL kanaujia 17647 14111 17647 0 2 00:06 pts/0 00:00:00 vi клонинг. s Какво представляват леките процеси?Лекият процес е процес, който поддържа нишката на потребителското пространство. Всяка нишка на потребителското пространство е неразривно свързана с лек процес. Процедурата за създаване на лек процес е различна от процедурата за създаване на обикновен процес; Потребителският процес "P" може да има редица свързани олекотени процеси със същия идентификатор на група. Групирането позволява на ядрото да разделя ресурси (ресурси включват адресно пространство, страници физическа памет(VM), манипулатори на сигнали и файлови дескриптори). Това също така позволява на ядрото да избягва контекстни превключвания, когато работи с тези процеси. Изчерпателното споделяне на ресурси е причината тези процеси да се наричат леки. Как Linux създава леки процеси?IN Създаване на Linuxолекотените процеси се изпълняват с помощта на нестандартизираното системно извикване clone(). Подобно е на fork(), но с повече функционалност. По принцип извикването на fork() се реализира чрез извикване на clone() с допълнителни параметри, указващи ресурси, които ще бъдат споделени между процесите. Извикването на clone() създава процес, като детето споделя елементи на времето за изпълнение с родителя, включително памет, манипулатори на файлове и манипулатори на сигнали. Библиотеката pthread също използва извикването clone() за внедряване на нишки. Вижте файла с изходния код ./nptl/sysdeps/pthread/createthread.cв директорията с изходния код на glibc версия 2.11.2. Създаване на ваш собствен лек процесНека демонстрираме пример за използване на извикването clone(). Вижте изходен кодот файла demo.c по-долу: #включи Програмата demo.c ви позволява да създавате нишки по същество по същия начин като библиотеката pthread. Директното използване на clone() обаче не е препоръчително, защото ако се използва неправилно, разработваното приложение може да се провали. Синтаксисът на функцията clone() в Linux е даден по-долу: #include Първият аргумент е функцията на нишката; извиква се при стартиране на нишката. След като извикването на clone() завърши успешно, функцията fn започва да се изпълнява едновременно с процеса на извикване. Следващият аргумент е указател към място в паметта за стека на дъщерния процес. Стъпката преди извикването на fork() и clone() изисква от програмиста да резервира памет и да предаде указател за използване като стек на дъщерния процес, тъй като родителският и дъщерният процес споделят страници с памет - те включват стека. Дъщерен процес може да извика функция, различна от родителския процес, поради което е необходим отделен стек. В нашата програма запазваме тази част от паметта в купчината с помощта на функцията malloc(). Размерът на стека беше зададен на 64 KB. Тъй като стекът x86 расте надолу, е необходимо да се симулира подобно поведение чрез използване на разпределена памет от края на секцията. Поради тази причина предаваме следния адрес на функцията clone(): (char*) stack + STACK Следващият аргумент за знамена е особено важен. Тя ви позволява да посочите кои ресурси да се споделят със създадения процес. Ние избрахме битовата маска SIGCHLD | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_VMописано по-долу:
Последният параметър е аргументът, предаден на функцията (threadFunction), в нашия случай файлов дескриптор. Моля, вижте примера за работа с леки процеси demo.c, който публикувахме по-рано. Нишката затваря файла (/dev/null), отворен от родителския процес. Тъй като родителският процес и нишката споделят таблицата с файлови дескриптори, операцията по затваряне на файла засяга и родителския процес, което води до неуспех на последващите извиквания write(). Родителският процес чака нишката да приключи (в момента, в който получи сигнала SIGCHLD). След това освобождава запазена памети връща контрола. Компилирайте и стартирайте програмата както обикновено; изходът трябва да бъде подобен на този по-долу: $gcc demo.c $./a.out Създаване на дъщерна нишка дъщерна нишка влизане в дъщерна нишка излизане Родител: дете затвори нашия файлов дескриптор $ Linux осигурява поддръжка за ефективна, проста и мащабируема нишкова инфраструктура. Това насърчава програмистите да експериментират и да разработват библиотеки с нишки, които използват clone() като основна функция. Продължаваме темата за многопоточността в ядрото на Linux. Последният път, когато говорих за прекъсвания, тяхната обработка и тасклети, и тъй като първоначално беше замислено това да е една статия, в моята история за workqueue ще се позова на тасклети, ако приемем, че читателят вече е запознат с тях. Статии от поредицата:
Работна опашкаРаботна опашка- това са по-сложни и тежки единици от tasklets. Дори няма да се опитвам да опиша всички тънкости на изпълнението тук, но се надявам да анализирам най-важните неща повече или по-малко подробно.Workqueues, подобно на tasklets, служат за обработка на отложено прекъсване (въпреки че могат да се използват и за други цели), но за разлика от tasklets, те се изпълняват в контекста на процес на ядрото; съответно не е необходимо да са атомарни и могат да използват спящ режим (), различни инструменти за синхронизиране и др. Нека първо разберем как като цяло е организиран процесът на обработка на работната опашка. Картината го показва много приблизително и опростено, как всъщност се случва всичко е описано подробно по-долу. Няколко субекта участват в тази тъмна материя. По принцип работниците са нишки на ядрото, т.е. те се контролират от основния планировчик на ядрото на Linux. Но работниците частично се намесват в планирането на допълнителна организация на паралелното изпълнение на работата. Това ще бъде разгледано по-подробно по-долу. За да очертая основните възможности на механизма на работната опашка, предлагам да проучите API. За опашката и нейното създаванеalloc_workqueue(fmt, флагове, max_active, аргументи...)Параметрите fmt и args са форматът printf за името и аргументите към него. Параметърът max_activate отговаря за максималния брой работи, които от тази опашка могат да бъдат изпълнени паралелно на един CPU. Опашка може да бъде създадена със следните флагове:
В свързани опашкиКогато се добавят, работата е обвързана с текущия процесор, т.е. в такива опашки работата се изпълнява в ядрото, което я планира. В това отношение обвързаните опашки приличат на tasklets. В необвързани опашкиработата може да се изпълнява на всяко ядро. Важна характеристика на реализацията на workqueue в ядрото на Linux е допълнителната организация на паралелното изпълнение, която присъства в обвързаните опашки. По-подробно е написано по-долу, но сега ще кажа, че се извършва по такъв начин, че да се използва възможно най-малко памет и така че процесорът да не стои празен. Всичко това се реализира с предположението, че една работа не използва твърде много процесорни цикли. По аналогия със задачите, на работите може да се присвои приоритет на изпълнение, нормален или висок. Приоритетът е общ за цялата опашка. По подразбиране опашката има нормален приоритет и ако зададете флага WQ_HIGHPRI, тогава, съответно, високо. Флаг WQ_CPU_INTENSIVEима смисъл само за обвързани опашки. Този флаг е отказ от участие в допълнителна организация на паралелно изпълнение. Този флаг трябва да се използва, когато се очаква работата да изразходва много процесорно време, в който случай е по-добре да прехвърлите отговорността на планировчика. Това е описано по-подробно по-долу. Знамена WQ_FREEZABLEИ WQ_MEM_RECLAIMса специфични и извън рамките на темата, затова няма да се спираме подробно на тях. Понякога има смисъл да не създавате свои собствени опашки, а да използвате общи. Основните от тях:
За работата и планирането имСега нека се заемем с произведенията. Първо, нека да разгледаме макросите за инициализация, декларация и подготовка:DECLARE(_DELAYED)_WORK(име, void (*функция)(struct work_struct *work)); /* по време на компилиране */ INIT(_DELAYED)_WORK(_work, _func); /* по време на изпълнение */ PREPARE(_DELAYED)_WORK(_work, _func); /* за промяна на изпълняваната функция */ Работите се добавят към опашката с помощта на функциите: bool queue_work(struct workqueue_struct *wq, struct work_struct *work); bool queue_delayed_work(struct workqueue_struct *wq, struct delayed_work *dwork, unsigned long delay); /* работата ще бъде добавена към опашката само след изтичане на забавянето */ На това си струва да се спрем по-подробно. Въпреки че посочваме опашка като параметър, всъщност работата не се поставя в самата работна опашка, както може да изглежда, а в съвсем различен обект - в списъка с опашки на структурата worker_pool. Структура пул_работницивсъщност е най-важният субект в организирането на механизма на работната опашка, въпреки че за потребителя остава зад кулисите. Именно с тях работят работниците и именно в тях се съдържа цялата основна информация. Сега нека видим какви пулове има в системата. За неприкрепени опашки работните групи се разпределят динамично. Всички опашки могат да бъдат разделени на класове на еквивалентност според техните параметри, като за всеки такъв клас се създава собствен пул от работници. Достъпът до тях се осъществява чрез специална хеш-таблица, където ключът е набор от параметри, а стойността, съответно, е работният пул. Всякакви дреболииЩе дам и няколко функции от API, за да допълня картината, но няма да говоря за тях в подробности:/* Принудително завършване */ bool flush_work(struct work_struct *work); bool flush_delayed_work(struct delayed_work *dwork); /* Отмяна на изпълнението на работа */ bool cancel_work_sync(struct work_struct *work); bool cancel_delayed_work(struct delayed_work *dwork); bool cancel_delayed_work_sync(struct delayed_work *dwork); /* Изтриване на опашка */ void destroy_workqueue(struct workqueue_struct *wq); Как работниците си вършат работатаСега, след като сме запознати с API, нека се опитаме да разберем по-подробно как всичко работи и се управлява.Всеки пул има набор от работници, които се справят със задачите. Освен това броят на работниците се променя динамично, адаптирайки се към текущата ситуация. Както вече разбрахме, работниците са нишки, които извършват работа в контекста на ядрото. Работникът ги извлича в ред, един след друг, от групата работници, свързани с него, и работниците, както вече знаем, могат да принадлежат към различни опашки източници. Работниците могат условно да бъдат в три логически състояния: те могат да бъдат бездействащи, работещи или управляващи.
Отчитането на работещите работници се извършва директно от основния планировчик на ядрото на Linux. Този контролен механизъм осигурява оптимално ниво на паралелност, предотвратявайки създаването на твърде много работници в работната опашка, но също така не кара работата да чака ненужно твърде дълго. Който се интересува може да разгледа работната функция в ядрото, тя се казва worker_thread(). Всички описани функции и структури могат да бъдат намерени по-подробно във файловете include/linux/workqueue.h, ядро/workqueue.cИ kernel/workqueue_internal.h. Има и документация за работна опашка в Документация/workqueue.txt. Също така си струва да се отбележи, че механизмът на работната опашка се използва в ядрото не само за обработка на отложено прекъсване (въпреки че това е доста често срещан сценарий). По този начин разгледахме механизмите за обработка на отложено прекъсване в ядрото на Linux - tasklet и workqueue, които са специална форма на многозадачност. Можете да прочетете за прекъсванията, задачите и работните опашки в книгата „Драйвери на устройства за Linux“ от Джонатан Корбет, Грег Кроа-Хартман, Алесандро Рубини, въпреки че информацията там понякога е остаряла.
ЛАБОРАТОРНА РАБОТА №3 МНОГОЗАДАЧНО ПРОГРАМИРАНЕ ВLINUX 1. Цел на работата:Запознайте се с компилатора gcc, техниките за отстраняване на грешки в програмата и функциите за работа с процеси. 2. Кратка теоретична информация. Минималният набор от превключватели на gcc компилатора са - Wall (показва всички грешки и предупреждения) и - o (изходен файл): gcc - Стена - o print_pid print_pid. c Командата ще създаде изпълним файл print_pid. C стандартната библиотека (libc, внедрена в Linux в glibc) се възползва от възможностите за многозадачност на Unix System V (наричана по-долу SysV). В libc типът pid_t се дефинира като цяло число, което може да съдържа pid. Функцията, която отчита pid на текущия процес, има прототип на pid_t getpid(void) и е дефинирана заедно с pid_t в unistd. h и sys/типове. з). За да създадете нов процес, използвайте функцията fork: pid_t fork(void) Чрез вмъкване на забавяне с произволна дължина, използвайки функциите за заспиване и ранд, можете да видите по-ясно ефекта от многозадачността: това ще накара програмата да "заспи" за произволен брой секунди: от 0 до 3. За да извикате функция като дъщерен процес, просто я извикайте след разклоняване: // ако се изпълнява дъщерен процес, извикайте функцията pid=процес(арг); // изход от процеса Често е необходимо да стартирате друга програма като дъщерен процес. За да направите това, използвайте функциите на семейството exec: // ако се изпълнява дъщерен процес, извикайте програмата if (execl("./file","file",arg, NULL)<0) { printf("ГРЕШКА при стартиране на процес\n"); else printf("процесът стартира (pid=%d)\n", pid); // изход от процеса Често родителският процес трябва да обменя информация със своите деца или поне да се синхронизира с тях, за да извършва операции в точното време. Един от начините за синхронизиране на процесите е с функциите wait и waitpid: #включи #включи pid_t wait(int *status) - спира изпълнението на текущия процес, докато някой от неговите дъщерни процеси не приключи. pid_t waitpid (pid_t pid, int *status, int options) - спира изпълнението на текущия процес, докато посоченият процес завърши или провери за завършване на посочения процес. Ако трябва да разберете състоянието на дъщерния процес, когато той приключи и стойността, която връща, тогава използвайте макроса WEXITSTATUS, като му предадете състоянието на дъщерния процес като параметър. status=waitpid(pid,&status, WNOHANG); ако (pid == състояние) ( printf("PID: %d, Резултат = %d\n", pid, WEXITSTATUS(състояние)); ) За да промените приоритетите на създадените процеси, се използват функциите setpriority и . Приоритетите са зададени в диапазона от -20 (най-висок) до 20 (най-нисък), нормалната стойност е 0. Имайте предвид, че само суперпотребител може да увеличи приоритета над нормалния! #включи #включи int процес(int i) ( setpriority(PRIO_PROCESS, getpid(),i); printf("Процес %d ThreadID: %d работи с приоритет %d\n",i, getpid(),getpriority(PRIO_PROCESS, getpid())); return(getpriority(PRIO_PROCESS, getpid())); За да убиете процес, използвайте функцията kill: #включи #включи int kill(pid_t pid, int sig); Ако pid > 0, тогава той определя PID на процеса, към който е изпратен сигналът. Ако pid = 0, тогава сигналът се изпраща до всички процеси от групата, към която принадлежи текущият процес. sig - тип сигнал. Някои видове сигнали в Linux: SIGKILL Този сигнал кара процеса да прекрати незабавно. Процесът не може да игнорира този сигнал. SIGTERM Този сигнал е искане за прекратяване на процеса. SIGCHLD Системата изпраща този сигнал към процес, когато един от неговите дъщерни процеси приключи. Пример: if (pid[i] == състояние) ( printf("ThreadID: %d завърши със състояние %d\n", pid[i], WEXITSTATUS(статус)); else kill(pid[i],SIGKILL); 3. Методически указания. 3.1. За да се запознаете с опциите на компилатора на gcc и описанията на функциите на езика C, използвайте инструкциите за човек и информация. 3.2. За отстраняване на грешки в програми е удобно да използвате вградения редактор на файловия мениджър Midnight Commander (MC), който подчертава различни езикови конструкции в цвят и показва позицията на курсора във файла (ред, колона) в горния ред на екрана. 3.3. Файловият мениджър на Midnight Commander има команден буфер, който може да бъде извикан чрез клавишна комбинация 3.4. Не забравяйте, че текущата директория не се съдържа в path, така че от команден редтрябва да стартирате програмата като "./print_pid". В MC просто задръжте курсора на мишката над файла и щракнете 3.5. За да видите резултата от изпълнението на програмата, използвайте клавишната комбинация 3.6. За да регистрирате резултатите от изпълнението на програмата, препоръчително е да използвате пренасочване на изхода от конзолата към файл: ./test > result. txt 3.7. За достъп до файлове, създадени на Linux сървър, кандидатствайте ftp протокол, клиентска програмакойто е наличен в Windows 2000 и е вграден в файлов мениджърДАЛЕЧ. В същото време сметкаи паролата е същата като при свързване през ssh. 4.1. Запознайте се с опциите на gcc компилатора и методите за отстраняване на грешки в програми. 4.2. За варианти на задачи от лабораторна работа № 1 напишете и дебъгвайте програма, която реализира генерирания процес. 4.3. За варианти на задачи от лабораторна работа№ 1 напишете и дебъгвайте програма, която имплементира родителски процес, който извиква и следи състоянието на дъщерните процеси - програми (изчаква тяхното завършване или ги унищожава, в зависимост от опцията). 4.4. За варианти на задачи от лабораторна работа № 1 напишете и дебъгвайте програма, която реализира родителски процес, който извиква и следи състоянието на дъщерните процеси - функции (изчаква завършването им или ги унищожава, в зависимост от варианта). 5. Опции за задачи.Вижте варианти на задачи от лабораторна работа №1 6. Съдържание на доклада. 6.1. Цел на работата. 6.2. Вариант за задача. 6.3. Списъци с програми. 6.4. Протоколи за изпълнение на програмата. 7. Тестови въпроси. 7.1. Характеристики на компилиране и изпълнение на C програми на Linux. 7.2. Какво е pid, как да го определите в операционната система и програмата? 7.3. Функция Fork – предназначение, приложение, връщана стойност. 7.4. Как да стартирате функция в създаден процес? програма? 7.5. Начини за синхронизиране на родителски и дъщерни процеси. 7.6. Как мога да разбера състоянието на създадения процес, когато той приключи, и стойността, която връща? 7.7. Как да управлявате приоритетите на процеса? 7.8. Как да убия процес в операционната система и програмата? Въведете следната команда във вашата обвивка: −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− На екрана ще се покаже списък с всички процеси, изпълнявани в системата. Ако искате да преброите броя на процесите, напишете нещо подобно: −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− $ ps -e --no-headers | nl | опашка -n 1 74 4650 точки/0 00:00:00 опашка −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− Първото число е броят на процесите, изпълнявани в системата. Потребителите на KDE могат да използват програмата kpm, а потребителите на Gnome могат да използват програмата gnome-system-monitor, за да получат информация за процесите. Това е целта на Linux, за да позволи на потребителя да прави същото по различни начини. Възниква въпросът: "Какво е процес?" Процесите в Linux, подобно на файловете, са аксиоматични понятия. Понякога процесът се идентифицира с работеща програматова обаче не винаги е така. Да приемем, че процесът е работеща единица на система, която прави нещо. Многозадачността е способността няколко процеса да съществуват едновременно в една система. Linux е многозадачна операционна система. Това означава, че процесите в него работят едновременно. Естествено, това е условна формулировка. Ядрото на Linux непрекъснато превключва процесите, тоест от време на време дава на всеки от тях малко процесорно време. Превключването става доста бързо, така че ни се струва, че процесите се изпълняват едновременно. Някои процеси могат да генерират други процеси, образувайки дървовидна структура. Произвеждащите процеси се наричат родители или родителски процеси, а децата се наричат деца или дъщерни процеси. В горната част на това „дърво“ е процесът на стартиране, който се заражда автоматично от ядрото по време на процеса на зареждане на системата. Всеки процес в системата е свързан с двойка неотрицателни цели числа: идентификатор на процес PID (Process IDentifier) и идентификатор на родителски процес PPID (Parent Process IDentifier). За всеки процес PID е уникален (в определен момент от време) и PPID е равен на ID на родителския процес. Ако въведете командата ps -ef в обвивката, ще се покаже списък с процеси със стойностите на техните PID и PPID (съответно втора и трета колона). Пример за тази команда: −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− UID PID PPID C STIME TTY TIME CMD корен 1 0 0 17:08? 00:00:00 /sbin/init корен 2 0 0 17:08? 00:00:00 корен 3 2 0 17:08? 00:00:00 корен 4 2 0 17:08? 00:00:00 корен 5 2 0 17:08? 00:00:00 корен 6 2 0 17:08? 00:00:00 корен 7 2 0 17:08? 00:00:00 корен 8 2 0 17:08? 00:00:00 корен 9 2 0 17:08? 00:00:00 корен 10 2 0 17:08? 00:00:00 корен 11 2 0 17:08? 00:00:00 корен 12 2 0 17:08? 00:00:00 корен 13 2 0 17:08? 00:00:00 корен 14 2 0 17:08? 00:00:00 корен 15 2 0 17:08? 00:00:00 корен 16 2 0 17:08? 00:00:00 корен 17 2 0 17:08? 00:00:00 корен 18 2 0 17:08? 00:00:00 корен 19 2 0 17:08? 00:00:00 df00 16389 16387 0 20:10 точки/1 00:00:00 /bin/bash df00 17446 2538 0 20:26? 00:00:00 df00 18544 2932 0 20:41 точки/2 00:00:00 /bin/bash -l df00 19010 18544 0 20:48 точки/2 00:00:00 ps -ef −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− Трябва да се отбележи, че процесът на init винаги има идентификатор 1 и PPID 0. Въпреки че в действителност няма процес с идентификатор 0. Дървото на процеса може също да се визуализира с помощта на опцията --forest на програмата ps: −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− 2? 00:00:00 kthread 3 ?00:00:00 \_ миграция/0 4 ?00:00:00 \_ ksoftirqd/0 5 ?00:00:00 \_ пазач/0 6 ?00:00:00 \_ миграция/1 7 ?00:00:00 \_ ksoftirqd/1 8 ?00:00:00 \_ пазач/1 9 ?00:00:00 \_ събития/0 10 ?00:00:00 \_ събития/1 11 ?00:00:00 \_ cpuset 12 ?00:00:00 \_ khelper 13 ?00:00:00 \_netns 14 ?00:00:00 \_ async/mgr 15 ?00:00:00 \_ kintegrityd/0 16 ?00:00:00 \_ kintegrityd/1 18544 точки/2 00:00:00 \_ bash 16388 ?00:00:00 \_ gnome-pty-helpe 16389 точки/1 00:00:00 \_ bash −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− Ако извикате програмата ps без аргументи, ще се покаже списък с процеси, принадлежащи към текущата група, тоест изпълняващи се под текущия терминал. Използване на getpid() и getppid() Процесът може да открие своя PID, както и своя родителски PPID, използвайки системните извиквания getpid() и getppid(). Системните извиквания getpid() и getppid() имат следните прототипи: −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− pid_t getpid(void); pid_t getppid(void); −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− За да използвате getpid() и getppid(), заглавните файлове unistd.h и sys/types.h (за типа pid_t) трябва да бъдат включени в програмата с помощта на директивата #include. Извикването getpid() връща идентификатора на текущия процес (PID), а getppid() връща родителския идентификатор (PPID). pid_t е целочислен тип, чието измерение зависи от конкретната система. Стойностите от този тип могат да се оперират като редовни цели числа от тип int. Нека сега да разгледаме проста програма, който показва PID и PPID и след това замръзва, докато потребителят не натисне −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− #включи #включи #включи pid_t pid, ppid; pid = getpid(); ppid = getppid(); printf("PID: %d\n", pid); printf("PPID: %d\n", ppid); fprintf(stderr, "Натисни −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− Нека сега да проверим как работи тази програма. За да направите това, нека го компилираме и стартираме: −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− $ gcc -o getpid getpid.c Натиснете −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− Сега, без да натискате −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− $ ps -ef | grep getpid df00 19724 19702 0 20:58 точки/3 00:00:00 ./главен df00 19856 18544 0 21:00 точки/2 00:00:00 grep --colour=auto main −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− |
Популярни:
Нов
- Какви грешки възникват по време на инсталацията?
- Социален статус на човек в обществото
- Пълна интерпретация на грешките
- Как да се обадите директно на „жив“ оператор на Beeline: безплатни телефонни номера
- Основни PDF четци
- Lineage II - Interlude: The Chaotic Throne няма да започне?
- Възстановяване на парола за Excel
- Как да добавите нов циферблат на смарт часовници с Android Wear
- Най-печелившият тарифен план Life
- Как да прехвърля данни от Samsung към Xiaomi Miui google contacts