Misol tariqasida Linuxdan foydalangan holda UNIX-ga o'xshash operatsion tizimlarda ishlash tamoyillari. O'zingizning engil jarayoningizni yaratish

Atrof-muhitdan ko'chib o'tishdagi eng zerikarli daqiqalardan biri Windows asosida foydalanish uchun buyruq qatori- oson ko'p vazifani yo'qotish. Hatto Linuxda ham, agar siz X Window tizimidan foydalansangiz, shunchaki bosish uchun sichqonchadan foydalanishingiz mumkin yangi dastur va uni oching. Biroq, buyruq satrida siz bir xil vazifani bajarish bilan bog'liqsiz. Ushbu maqolada biz sizga ko'rsatamiz buyruq qatori yordamida Linuxda ko'p vazifani qanday bajarish kerak.

Asosiy va ustuvor jarayonni boshqarish

Biroq, Linuxda ko'p vazifalarni bajarish usullari hali ham mavjud va ularning ba'zilari boshqalarga qaraganda kengroqdir. Hech qanday qo'shimcha talab qilmaydigan bitta o'rnatilgan usul dasturiy ta'minot, shunchaki fonda va oldingi fonda jarayonlarni harakatga keltiradi. Biz bu haqda gapiryapmiz. Biroq, uning ba'zi kamchiliklari bor.

Himoyasiz

Birinchidan Jarayonni fonda yuborish uchun avval uni to'xtatib qo'yishingiz kerak. Ishlayotgan dasturni fonga yuborish va bir vaqtning o'zida uni saqlab qolish mumkin emas.

Ikkinchidan, yangi buyruqni boshlash uchun ish jarayonini buzish kerak. Siz hozir qilayotgan ishingizdan chiqib, qobiqqa ko'proq buyruqlar kiritishingiz kerak. Bu ishlaydi, lekin bu noqulay.

Uchinchidan, siz fon jarayonlaridan chiqishlarni kuzatishingiz kerak. Ularning har qanday chiqishi buyruq satrida paydo bo'ladi va siz hozir qilayotgan ishingizga xalaqit beradi. Shunday qilib, fon vazifalari natijalarini yo'naltirishi kerak alohida fayl, yoki ular butunlay o'chirib qo'yilishi kerak.

Ushbu kamchiliklar tufayli fon va oldingi jarayonni boshqarishda katta muammolar mavjud. Eng yaxshi qaror– quyida ko‘rsatilganidek, “ekran” buyruq qatori yordam dasturidan foydalaning.

Lekin birinchi navbatda siz yangi SSH seansini ochasiz

Yangi SSH seansini ochayotganingizni unutmang.

Har doim yangi seanslarni ochish noqulay bo'lishi mumkin. Va o'sha paytda sizga "ekran" kerak bo'ladi.

Qulaylik ekran bir vaqtning o'zida bir nechta ochiq ish oqimlarini yaratishga imkon beradi - "oynalar" ga eng yaqin analog. Odatiy bo'lib, u oddiy Linux omborlarida mavjud. Quyidagi buyruq yordamida uni CentOS/RHEL-ga o'rnating:

Sudo yum o'rnatish ekrani

Yangi ekran ochilmoqda

Endi "ekran" ni yozish orqali seansingizni boshlang.

Bu yaratadi bo'sh oyna mavjud SSH sessiyasida va unga sarlavhada ko'rsatilgan raqamni bering:

Bizning ekranimiz ko'rsatilganidek, "0" bilan raqamlangan. Ushbu skrinshotda biz terminalni blokirovka qilish va uni kiritishni kutish uchun "o'qish" buyrug'idan foydalanamiz. Aytaylik, biz kutgancha boshqa biror narsa qilmoqchimiz.

Ochish uchun yangi ekran va boshqa biror narsa qiling, biz chop etamiz:

Ctrl+a c

“ctrl+a” – ekran dasturidagi ekranlarni boshqarish uchun standart tugmalar birikmasi. Undan keyin yozgan narsa amalni belgilaydi. Masalan:

  • ctrl + a c - C yangi ekranni faollashtiradi
  • ctrl+a [raqam]– maʼlum bir ekran raqamiga oʻtish
  • ctrl+a k – K joriy ekranni o'chiradi
  • ctrl+a n – ekranga o‘tish n
  • ctrl+a “- seansdagi barcha faol ekranlarni ko'rsatadi

Agar biz "ctrl + a c" tugmachalarini bossak, biz yangi raqam bilan yangi ekranga ega bo'lamiz.

Roʻyxat boʻylab harakatlanish va kerakli ekranga oʻtish uchun kursor tugmalaridan foydalanishingiz mumkin.
Ekranlar buyruqdagi tizim kabi "oyna" ga eng yaqin joylashgan joydir Linux qatori. Albatta, bu sichqonchani bosish kabi oddiy emas, lekin grafik quyi tizimi juda ko'p resurs talab qiladi. Ekranlar yordamida siz deyarli bir xil funksiyalarga ega bo'lishingiz va to'liq multitaskingni yoqishingiz mumkin!

UNIX dagi jarayonlar

UNIXda ko'p vazifalarni tashkil etishning asosiy vositasi va birligi jarayondir. Operatsion tizim dastur kodini ifodalovchi jarayon tasvirini, shuningdek, bajarilish muhitini belgilaydigan jarayon ma'lumotlari bo'limlarini manipulyatsiya qiladi.

Amalga oshirish paytida yoki "qanotlarda" kutish paytida, jarayonlar sahifani tashkil qilish bilan virtual xotirada saqlanadi. Ushbu virtual xotiraning bir qismi jismoniy xotira bilan taqqoslanadi. Jismoniy xotiraning bir qismi operatsion tizim yadrosi uchun ajratilgan. Foydalanuvchilar faqat jarayonlar uchun qolgan xotiraga kirishlari mumkin. Agar kerak bo'lsa, protsessual xotira sahifalari jismoniy xotiradan diskka, almashtirish maydoniga almashtiriladi. Virtual xotiradagi sahifaga kirishda, agar u jismoniy xotirada bo'lmasa, u diskdan almashtiriladi.

Virtual xotira UNIX yadrosi tomonidan amalga oshiriladi va avtomatik ravishda saqlanadi.

Jarayon turlari

UNIX operatsion tizimlarida uchta turdagi jarayonlar mavjud: tizimli, demon jarayonlari Va qo'llash jarayonlari.

Tizim jarayonlari yadroning bir qismi bo'lib, doimo joylashgan tasodifiy kirish xotirasi. Tizim jarayonlarida bajariladigan fayllar ko'rinishidagi tegishli dasturlar mavjud emas va tizim yadrosi ishga tushirilganda maxsus tarzda ishga tushiriladi. Ushbu jarayonlarning bajaruvchi ko'rsatmalari va ma'lumotlari tizim yadrosida joylashgan bo'lib, ular funktsiyalarni chaqirishlari va boshqa jarayonlar kira olmaydigan ma'lumotlarga kirishlari mumkin.

Tizim jarayonlari dastlabki ishga tushirish jarayonini o'z ichiga oladi, init, bu boshqa barcha jarayonlarning asoschisi. Garchi init yadroning bir qismi emas va uning bajarilishi bajariladigan fayldan sodir bo'ladi, uning ishlashi butun tizimning bir butun sifatida ishlashi uchun juda muhimdir.

Jinlar- bu interaktiv bo'lmagan jarayonlar bo'lib, ular odatdagi usulda - tegishli dasturlarni xotiraga yuklash orqali ishga tushiriladi va fonda bajariladi. Odatda, demonlar tizimni ishga tushirish vaqtida ishga tushiriladi, lekin yadro ishga tushirilgandan so'ng va turli UNIX quyi tizimlarining ishlashini ta'minlaydi: terminalga kirish tizimlari, bosib chiqarish tizimlari, tarmoq xizmatlari va hokazo. Jinlar hech qanday foydalanuvchi bilan bog'lanmagan. Ko'pincha, demonlar u yoki bu jarayonni so'rashni kutishadi maxsus xizmat.



TO qo'llash jarayonlari tizimda ishlaydigan barcha boshqa jarayonlarni o'z ichiga oladi. Odatda, bular foydalanuvchi sessiyasida paydo bo'ladigan jarayonlardir. Eng muhim foydalanuvchi jarayoni boshlang'ich buyruq tarjimoni, bu UNIX tizimida foydalanuvchi buyruqlarining bajarilishini ta'minlaydi.

Foydalanuvchi jarayonlari ham interaktiv (preemptive) va ham ishlashi mumkin fon rejimlari. Interaktiv jarayonlar terminalning eksklyuziv mulkiga ega va bunday jarayon uning bajarilishini tugatmaguncha, foydalanuvchi buyruq qatoriga kira olmaydi.

Jarayon atributlari

UNIX jarayoni bunga imkon beradigan bir qator atributlarga ega operatsion tizim ishini boshqaradi. Asosiy atributlar:

· Jarayon identifikatori (PID), tizim yadrosiga jarayonlarni farqlash imkonini beradi. Yaratilganda yangi jarayon, yadro unga keyingi bepul (ya'ni, hech qanday jarayon bilan bog'lanmagan) identifikatorni tayinlaydi. Identifikatorni tayinlash odatda ortib boruvchi tartibda sodir bo'ladi, ya'ni. Yangi jarayonning identifikatori undan oldin yaratilgan jarayonning identifikatoridan kattaroqdir. Agar ID maksimal qiymatga yetsa (odatda 65737), keyingi jarayon minimal bepul PID oladi va tsikl takrorlanadi. Jarayon tugaganda, yadro o'zi ishlatgan identifikatorni chiqaradi.

· Asosiy jarayon identifikatori (PPID)- bu jarayonni yaratgan jarayonning identifikatori. Tizimdagi barcha jarayonlar bundan mustasno tizim jarayonlari va jarayon init Qolgan jarayonlarning ajdodi bo'lgan , mavjud yoki ilgari mavjud bo'lgan jarayonlardan biri tomonidan hosil bo'ladi.

· Ustuvor tuzatish (NI)- ishga tushirish tartibini belgilashda rejalashtiruvchi tomonidan hisobga olinadigan jarayonning nisbiy ustuvorligi. Protsessor resurslarining haqiqiy taqsimoti bajarish ustuvorligi bilan belgilanadi (atribut PRI), bir nechta omillarga, xususan, berilgan nisbiy ustuvorlikka bog'liq. Nisbiy ustuvorlik butun jarayon davomida tizim tomonidan o'zgartirilmaydi, garchi uni buyruq yordamida jarayonni boshlashda foydalanuvchi yoki administrator o'zgartirishi mumkin. yaxshi. Aksariyat tizimlarda ustuvor o'sish qiymatlari diapazoni -20 dan 20 gacha. Agar o'sish belgilanmagan bo'lsa, standart qiymat 10 dan foydalaniladi. Ijobiy o'sish joriy ustuvorlikning pasayishini bildiradi. Oddiy foydalanuvchilar faqat ijobiy o'sishni o'rnatishi va shuning uchun faqat ustuvorlikni kamaytirishi mumkin. Foydalanuvchi ildiz salbiy o'sishni belgilashi mumkin, bu jarayonning ustuvorligini oshiradi va shu bilan uning yuqori bo'lishiga yordam beradi tez ish. Nisbiy ustuvorlikdan farqli o'laroq, jarayonning bajarilishi ustuvorligi rejalashtiruvchi tomonidan dinamik ravishda o'zgartiriladi.

· Terminal liniyasi (TTY)- jarayon bilan bog'liq terminal yoki psevdo-terminal. Ushbu terminal standart bilan bog'langan oqimlar: kiritish, Dam olish kuni Va xabarlar oqimi xatolar haqida. Oqimlar ( dastur kanallari) bor standart vositalar UNIX operatsion tizimida jarayonlararo aloqa. Daemon jarayonlari terminal bilan bog'liq emas.

· Haqiqiy (UID) va samarali (EUID) foydalanuvchi identifikatorlari. Berilgan jarayonning haqiqiy foydalanuvchi identifikatori jarayonni boshlagan foydalanuvchining identifikatoridir. Samarali identifikator jarayonning tizim resurslariga (birinchi navbatda, resurslarga) kirish huquqlarini aniqlash uchun ishlatiladi fayl tizimi). Odatda haqiqiy va samarali identifikatorlar bir xil, ya'ni. jarayon tizimda uni ishga tushirgan foydalanuvchi bilan bir xil huquqlarga ega. Biroq, sozlash orqali jarayonga foydalanuvchidan ko'ra ko'proq huquqlar berish mumkin SUID bit samarali identifikator bajariladigan fayl egasining identifikatoriga o'rnatilganda (masalan, foydalanuvchi ildiz).

· Haqiqiy (GID) va samarali (EGID) guruh identifikatorlari. Haqiqiy guruh identifikatori jarayonni boshlagan foydalanuvchining asosiy yoki joriy guruh identifikatoriga teng. Samarali identifikator guruh nomidan tizim resurslariga kirish huquqlarini aniqlash uchun ishlatiladi. Odatda samarali guruh identifikatori haqiqiy bilan bir xil bo'ladi. Ammo bajariladigan fayl o'rnatilgan bo'lsa SGID bit, bunday fayl samarali ega guruhi identifikatori bilan bajariladi.

3-son LABORATORIYA ISHI

KO'P MAZQALI DASTURLASHLINUX

1. Ishning maqsadi: Gcc kompilyatori, dasturlarni tuzatish usullari va jarayonlar bilan ishlash funktsiyalari bilan tanishing.

2. Qisqacha nazariy ma'lumotlar.

Gcc kompilyatorlarining minimal to'plami quyidagilardan iborat: - Wall (barcha xatolar va ogohlantirishlarni ko'rsatish) va - o (chiqish fayli):

gcc - Wall - yoki print_pid print_pid. c

Jamoa yaratadi bajariladigan fayl print_pid.

C standart kutubxonasi (libc, Linuxda glibc da joriy qilingan) Unix System V (keyingi o'rinlarda SysV) ning ko'p vazifali imkoniyatlaridan foydalanadi. Libc-da pid_t turi pidni o'z ichiga olishi mumkin bo'lgan butun son sifatida aniqlanadi. Joriy jarayonning pidi haqida xabar beruvchi funksiya pid_t getpid(void) prototipiga ega va unistd da pid_t bilan birga aniqlanadi. h va sys/turlari. h).

Yangi jarayon yaratish uchun fork funksiyasidan foydalaning:

pid_t vilka (bo'sh)

Uyqu va rand funksiyalaridan foydalanib, tasodifiy uzunlikdagi kechikishni kiritish orqali siz ko'p vazifalarni bajarish effektini aniqroq ko'rishingiz mumkin:

bu dasturni tasodifiy soniyalar soniga "uxlashga" olib keladi: 0 dan 3 gacha.

Funktsiyani asosiy jarayon sifatida chaqirish uchun uni tarmoqlangandan keyin chaqirish kifoya:

// agar bola jarayoni ishlayotgan bo'lsa, funktsiyani chaqiring

pid=jarayon(arg);

// jarayondan chiqish

Ko'pincha bola jarayoni sifatida boshqa dasturni ishga tushirish kerak. Buning uchun exec oilasi funktsiyalaridan foydalaning:

// agar bola jarayoni ishlayotgan bo'lsa, dasturni chaqiring


agar (execl("./file", "fayl", arg, NULL)<0) {

printf("Jarayonni boshlashda XATO\n");

else printf("jarayon boshlandi (pid=%d)\n", pid);

// jarayondan chiqish

Ko'pincha, ota-ona jarayoni kerakli vaqtda operatsiyalarni bajarish uchun o'z farzandlari bilan ma'lumot almashishi yoki hech bo'lmaganda ular bilan sinxronlashtirishi kerak. Jarayonlarni sinxronlashtirishning bir usuli bu wait va waitpid funktsiyalari:

#o'z ichiga oladi

#o'z ichiga oladi

pid_t wait(int *status) - joriy jarayonning har qanday bola jarayonlari tugamaguncha bajarilishini to'xtatib turadi.

pid_t waitpid (pid_t pid, int *status, int options) - ko'rsatilgan jarayon tugaguniga qadar joriy jarayonning bajarilishini to'xtatib turadi yoki ko'rsatilgan jarayonning bajarilishini tekshiradi.

Agar siz bola jarayoni tugagandan so'ng uning holatini va uning qaytariladigan qiymatini bilishingiz kerak bo'lsa, u holda WEXITSTATUS makrosidan foydalaning, unga bola jarayonining holatini parametr sifatida o'tkazing.

status=waitpid(pid,&status, WNOHANG);

agar (pid == holati) (

printf("PID: %d, Natija = %d\n", pid, WEXITSTATUS(holat)); )

Tugallangan jarayonlarning ustuvorliklarini o'zgartirish uchun belgilangan ustuvorlik va funktsiyalardan foydalaniladi. Ustuvorliklar -20 (eng yuqori) dan 20 (eng past) oralig'ida o'rnatiladi, normal qiymat 0. E'tibor bering, faqat superfoydalanuvchi ustuvorlikni me'yordan oshirishi mumkin!

#o'z ichiga oladi

#o'z ichiga oladi

int jarayoni (int i) (

setpriority(PRIO_PROCESS, getpid(),i);

printf("Process%d ThreadID: %d prioritet %d\n bilan ishlaydi",i, getpid(),getpriority(PRIO_PROCESS, getpid()));

qaytish(getpriority(PRIO_PROCESS, getpid()));

Jarayonni o'ldirish uchun o'ldirish funktsiyasidan foydalaning:

#o'z ichiga oladi

#o'z ichiga oladi

int kill(pid_t pid, int sig);

Agar pid > 0 bo'lsa, u signal yuboriladigan jarayonning PID ni belgilaydi. Agar pid = 0 bo'lsa, u holda signal joriy jarayon tegishli bo'lgan guruhning barcha jarayonlariga yuboriladi.

sig - signal turi. Linuxda signallarning ba'zi turlari:

SIGKILL Bu signal jarayonning darhol tugatilishiga olib keladi. Jarayon bu signalni e'tiborsiz qoldirolmaydi.

SIGTERM Bu signal jarayonni tugatish talabidir.

SIGCHLD Tizim ushbu signalni o'zining asosiy jarayonlaridan biri tugashi bilan jarayonga yuboradi. Misol:

agar (pid[i] == holati) (

printf("ThreadID: %d tugallandi %d\n holati", pid[i], WEXITSTATUS(holat));

else kill(pid[i],SIGKILL);

3. Metodik ko'rsatmalar.

3.1. Gcc kompilyator imkoniyatlari va C tili funksiyalarining tavsiflari bilan tanishish uchun man va info ko'rsatmalaridan foydalaning.

3.2. Dasturlarni disk raskadrovka qilish uchun fayl menejerining o'rnatilgan muharriridan foydalanish qulay Yarim tun qo'mondoni(MC), u turli xil til konstruksiyalarini rangda ajratib ko'rsatadi va kursorning fayldagi (qator, ustun) o'rnini ekranning yuqori qatorida ko'rsatadi.

3.3. Midnight Commander fayl menejerida klaviatura yorlig'i orqali chaqirilishi mumkin bo'lgan buyruq buferi mavjud - H, kursor strelkalari (yuqoriga va pastga) yordamida siljitish mumkin. Buferdan buyruq satriga buyruq kiritish uchun kalitdan foydalaning , buferdan buyruqni tahrirlash uchun - tugmalar<- и ->, Va .


3.4. Joriy katalog yo'lda yo'qligini unutmang, shuning uchun dasturni buyruq satridan "./print_pid" sifatida ishga tushirishingiz kerak. MC-da kursorni fayl ustiga olib boring va ustiga bosing .

3.5. Dasturning bajarilishi natijasini ko'rish uchun klaviatura yorliqlaridan foydalaning - O. Ular fayllarni tahrirlash rejimida ham ishlaydi.

3.6. Dasturni bajarish natijalarini jurnalga kiritish uchun chiqishni konsoldan faylga qayta yo'naltirishni qo'llash tavsiya etiladi: ./test > natija. Xabar

3.7. Yaratilgan fayllarga kirish uchun Linux serveri, mijoz dasturi Windows 2000 da mavjud va ichiga o'rnatilgan ftp protokolidan foydalaning. fayl menejeri FAR. Qayerda qayd yozuvi va parol ssh orqali ulanish bilan bir xil.

4.1. Gcc kompilyatorining imkoniyatlari va dasturlarni disk raskadrovka qilish usullari bilan tanishing.

4.2. 1-sonli laboratoriya ishi topshiriqlarining variantlari uchun yaratilgan jarayonni amalga oshiradigan dasturni yozing va disk raskadrovka qiling.

4.3. dan vazifa variantlari uchun laboratoriya ishi 1-sonli dasturni yozing va disk raskadrovka qiladi, u ota-ona jarayonini amalga oshiradi, u bolalar jarayonlari - dasturlarning holatini chaqiradi va nazorat qiladi (variantga qarab ularni tugatish yoki yo'q qilishni kutish).

4.4. 1-sonli laboratoriya ishi topshiriqlarining variantlari uchun bolalar jarayonlari holatini (variantga qarab ularning tugashini kutish yoki yo'q qilish) chaqiruvchi va nazorat qiluvchi ota-ona jarayonini amalga oshiradigan dasturni yozing va disk raskadrovka qiling.

5. Vazifalar uchun variantlar. 1-sonli laboratoriya ishidan topshiriqlar variantlariga qarang

6. Hisobotning mazmuni.

6.1. Ishning maqsadi.

6.2. Vazifa opsiyasi.

6.3. Dastur ro'yxati.

6.4. Dasturni bajarish protokollari.

7. Nazorat savollari.

7.1. Linuxda C dasturlarini kompilyatsiya qilish va ishga tushirish xususiyatlari.

7.2. Pid nima, uni operatsion tizim va dasturda qanday aniqlash mumkin?

7.3. Fork funktsiyasi - maqsad, qo'llanilishi, qaytariladigan qiymat.

7.4. Yaratilgan jarayonda funktsiyani qanday ishlatish kerak? Dastur?

7.5. Ota-onalar va bolalar jarayonlarini sinxronlashtirish usullari.

7.6. Tugallangan jarayon tugashi va u qaytaradigan qiymatini qanday aniqlash mumkin?

7.7. Jarayon ustuvorliklarini qanday boshqarish kerak?

7.8. Operatsion tizim va dasturda jarayonni qanday o'ldirish mumkin?

Biz Linux yadrosida multithreading mavzusini davom ettiramiz. Oxirgi marta men uzilishlar, ularni qayta ishlash va vazifalar to'g'risida gapirgan edim va dastlab bu bitta maqola bo'lishi mo'ljallanganligi sababli, ish navbati haqidagi hikoyamda men o'quvchi ular bilan tanish bo'lgan deb hisoblagan holda topshiriqlarga murojaat qilaman.
O'tgan safargidek, men hikoyamni iloji boricha batafsil va batafsil qilishga harakat qilaman.

Seriyadagi maqolalar:

  1. Linux yadrosida multitasking: ish navbati

Ish navbati

Ish navbati- bu topshiriqlardan ko'ra murakkabroq va og'irroq ob'ektlar. Men bu erda amalga oshirishning barcha nozikliklarini tasvirlashga harakat qilmayman, lekin umid qilamanki, men eng muhim narsalarni ko'proq yoki kamroq batafsil tahlil qilaman.
Ish navbatlari, masalan, vazifalar jadvallari kabi, kechiktirilgan uzilishlarni qayta ishlash uchun xizmat qiladi (garchi ular boshqa maqsadlarda ishlatilishi mumkin bo'lsa-da), lekin ular vazifa jadvallaridan farqli o'laroq, yadro jarayoni kontekstida bajariladi; shunga ko'ra, ular atomik bo'lishi shart emas va uyqu rejimidan foydalanishi mumkin. () funktsiyasi, turli xil sinxronlash vositalari va boshqalar.

Keling, avvalo, ish navbatini qayta ishlash jarayoni qanday tashkil etilganligini tushunaylik. Rasmda bu juda taxminan va soddalashtirilgan ko'rsatilgan, hamma narsa aslida qanday sodir bo'lishi quyida batafsil tavsiflangan.

Ushbu qorong'u materiyada bir nechta mavjudotlar ishtirok etadi.
Birinchidan, ish elementi(shunchaki qisqacha ish) biz rejalashtirmoqchi boʻlgan funksiyani (masalan, uzilish ishlovchisi) tavsiflovchi tuzilma boʻlib, uni vazifalar tuzilmasi analogi sifatida koʻrish mumkin. Rejalashtirishda vazifalar foydalanuvchidan yashirin navbatlarga qo'shildi, ammo endi biz maxsus navbatdan foydalanishimiz kerak - ish navbati.
Vazifalar rejalashtiruvchi funksiyasi tomonidan racklanadi va ish navbati ishchilar deb ataladigan maxsus iplar tomonidan qayta ishlanadi.
Ishchi ning ish navbatdan asinxron bajarilishini ta'minlaydi. Garchi ular ishni aylanish tartibida chaqirsalar ham, umumiy holatda qat'iy, ketma-ket bajarish haqida gap bo'lmaydi: axir, bu erda oldindan olish, uxlash, kutish va hokazo.

Umuman olganda, ishchilar yadro iplari, ya'ni ular asosiy Linux yadrosi rejalashtiruvchisi tomonidan boshqariladi. Ammo ishchilar ishning parallel bajarilishini qo'shimcha tashkil etishni rejalashtirishga qisman aralashadilar. Bu quyida batafsilroq muhokama qilinadi.

Ish navbati mexanizmining asosiy imkoniyatlarini tavsiflash uchun men APIni o'rganishni taklif qilaman.

Navbat va uning yaratilishi haqida

alloc_workqueue(fmt, bayroqlar, max_active, args...)
fmt va args parametrlari nom va unga argumentlar uchun printf formatidir. Max_activate parametri ushbu navbatdan bitta protsessorda parallel ravishda bajarilishi mumkin bo'lgan ishlarning maksimal soni uchun javobgardir.
Navbatni quyidagi bayroqlar bilan yaratish mumkin:
  • WQ_HIGHPRI
  • WQ_UNBOUND
  • WQ_CPU_INTENSIVE
  • WQ_FREEZABLE
  • WQ_MEM_RECLAIM
Bayroqqa alohida e'tibor berilishi kerak WQ_UNBOUND. Ushbu bayroqning mavjudligiga qarab, navbatlar bog'langan va bog'lanmaganlarga bo'linadi.
Bog'langan navbatlarda Qo'shilganda, ishlar joriy protsessorga bog'lanadi, ya'ni bunday navbatlarda ishlar uni rejalashtiruvchi yadroda bajariladi. Shu nuqtai nazardan, bog'langan navbatlar topshiriqlarga o'xshaydi.
Biriktirilmagan navbatlarda ish har qanday yadroda bajarilishi mumkin.

Linux yadrosida ish navbatini amalga oshirishning muhim xususiyati - bog'langan navbatlarda mavjud bo'lgan parallel bajarishning qo'shimcha tashkil etilishi. Quyida batafsilroq yozilgan, ammo hozir aytamanki, u imkon qadar kamroq xotira ishlatadigan va protsessor bo'sh turmasligi uchun amalga oshiriladi. Bularning barchasi bitta ishda juda ko'p protsessor sikllaridan foydalanilmaydi degan taxmin bilan amalga oshiriladi.
Bu biriktirilmagan navbatlar uchun emas. Aslida, bunday navbatlar ishchilarga kontekstni taqdim etadi va ularni imkon qadar erta boshlaydi.
Shunday qilib, agar protsessor intensiv ish yuki kutilsa, biriktirilmagan navbatlardan foydalanish kerak, chunki bu holda rejalashtiruvchi bir nechta yadrolarda parallel bajarilishini nazorat qiladi.

Vazifalar bilan taqqoslaganda, ishlarga oddiy yoki yuqori bajarilish ustuvorligi berilishi mumkin. Ustuvorlik butun navbat uchun umumiydir. Odatiy bo'lib, navbat odatdagi ustuvorlikka ega va agar siz bayroqni o'rnatsangiz WQ_HIGHPRI, keyin, mos ravishda, yuqori.

Bayroq WQ_CPU_INTENSIVE faqat bog'langan navbatlar uchun mantiqiy. Ushbu bayroq parallel ijro etishni qo'shimcha tashkil etishda ishtirok etishdan bosh tortishdir. Ish protsessor vaqtini ko'p sarflashi kutilayotganda ushbu bayroqdan foydalanish kerak, bu holda mas'uliyatni rejalashtiruvchiga o'tkazish yaxshiroqdir. Bu quyida batafsilroq tavsiflanadi.

Bayroqlar WQ_FREEZABLE Va WQ_MEM_RECLAIM aniq va mavzu doirasidan tashqarida, shuning uchun biz ularga batafsil to'xtalib o'tirmaymiz.

Ba'zan o'z navbatlaringizni yaratish emas, balki umumiy navlardan foydalanish mantiqan to'g'ri keladi. Asosiylari:

  • system_wq - tez ishlash uchun bog'langan navbat
  • system_long_wq - bajarilishi uzoq vaqt talab qilinadigan ishlar uchun bog'langan navbat
  • system_unbound_wq - bog'lanmagan navbat

Ish va ularni rejalashtirish haqida

Endi ishlar bilan shug'ullanamiz. Birinchidan, ishga tushirish, deklaratsiya va tayyorlash makroslarini ko'rib chiqamiz:
DECLARE(_DELAYED)_WORK(nom, bekor (*funksiya)(struct work_struct *ish)); /* kompilyatsiya vaqtida */ INIT(_DELAYED)_WORK(_work, _func); /* bajarish paytida */ TAYYORLASH(_KECIKTIRIB)_ISH(_ish, _func); /* bajarilayotgan funksiyani o‘zgartirish uchun */
Ishlar quyidagi funktsiyalar yordamida navbatga qo'shiladi:
bool queue_work(struct workqueue_struct *wq, struct work_struct *ish); bool queue_delayed_work(struct workqueue_struct *wq, struct delayed_work *dwork, imzosiz uzoq kechikish); /* ish faqat kechikish muddati tugagandan keyingina navbatga qo'shiladi */
Bu haqida batafsilroq to'xtalib o'tishga arziydi. Garchi biz navbatni parametr sifatida belgilagan bo'lsak-da, aslida ishlar, tuyulishi mumkin bo'lganidek, ish navbatining o'zida emas, balki butunlay boshqa ob'ektda - ishchi_pool strukturasining navbat ro'yxatida joylashtiriladi. Tuzilishi ishchi_hovuz, aslida, ish navbati mexanizmini tashkil qilishda eng muhim ob'ektdir, garchi foydalanuvchi uchun u sahna ortida qolsa. Aynan ular bilan ishchilar ishlaydi va ularda barcha asosiy ma'lumotlar mavjud.

Keling, tizimda qanday hovuzlar borligini ko'rib chiqaylik.
Boshlash uchun, bog'langan navbatlar uchun hovuzlar (rasmda). Har bir protsessor uchun ikkita ishchi hovuzi statik ravishda ajratilgan: biri yuqori ustuvorlikdagi ishlar uchun, ikkinchisi normal ustuvorlik bilan ishlash uchun. Ya'ni, agar bizda to'rtta yadro bo'lsa, unda kerakli darajada ko'p ish navbati bo'lishi mumkinligiga qaramasdan, faqat sakkizta bog'langan hovuz bo'ladi.
Ish navbatini yaratganimizda, u har bir protsessor uchun ajratilgan xizmatga ega pool_workqueue(pwq). Har bir bunday pool_workqueue bir xil protsessorda ajratilgan va navbat turiga ustuvorlik bilan mos keladigan ishchilar puli bilan bog'langan. Ular orqali ish navbati ishchilar hovuzi bilan o'zaro ta'sir qiladi.
Ishchilar dastlab qaysi ish navbatiga tegishli ekanligini ajratmasdan, ishchilar hovuzidan ishni beg'araz bajaradilar.

Biriktirilmagan navbatlar uchun ishchi hovuzlari dinamik ravishda ajratiladi. Barcha navbatlarni o'z parametrlariga ko'ra ekvivalentlik sinflariga bo'lish mumkin va har bir bunday sinf uchun o'z ishchilar puli yaratiladi. Ularga maxsus xesh-jadval yordamida kirish mumkin, bu erda kalit parametrlar to'plamidir va qiymat mos ravishda ishchilar hovuzidir.
Aslida, bog'lanmagan navbatlar uchun hamma narsa biroz murakkabroq: agar bog'langan navbatlar uchun pwq va navbatlar har bir CPU uchun yaratilgan bo'lsa, bu erda ular har bir NUMA tugun uchun yaratilgan, ammo bu biz batafsil ko'rib chiqmaydigan qo'shimcha optimallashtirish.

Har xil kichik narsalar

Rasmni to'ldirish uchun men API-dan bir nechta funktsiyalarni ham beraman, lekin ular haqida batafsil gapirmayman:
/* Majburiy bajarish */ bool flush_work(struct work_struct *ish); bool flush_kechiktirilgan_ish(tuzilma kechiktirilgan_ish *dwork); /* Ishning bajarilishini bekor qilish */ bool cancel_work_sync(struct work_struct *ish); bool bekor qilish_kechiktirilgan_ish(tuzilma kechiktirilgan_ish *dwork); bool cancel_delayed_work_sync(tuzilma kechiktirilgan_ish *dwork); /* Navbatni o'chirish */ yo'q qilish_ishchi navbati(struct workqueue_struct *wq);

Ishchilar o'z ishlarini qanday bajarishadi

Endi biz API bilan tanishganimizdan so'ng, keling, uning qanday ishlashi va boshqarilishini batafsilroq tushunishga harakat qilaylik.
Har bir hovuzda vazifalarni bajaradigan ishchilar to'plami mavjud. Bundan tashqari, ishchilar soni mavjud vaziyatga moslashib, dinamik ravishda o'zgaradi.
Biz allaqachon bilib olganimizdek, ishchilar yadro kontekstida ishni bajaradigan iplardir. Ishchi ularni ketma-ket, u bilan bog'langan ishchilar hovuzidan oladi va ishchilar, biz allaqachon bilganimizdek, turli manba navbatlariga tegishli bo'lishi mumkin.

Ishchilar shartli ravishda uchta mantiqiy holatda bo'lishi mumkin: ular bo'sh, ishlaydigan yoki boshqaruvchi bo'lishi mumkin.
Ishchi mumkin bo'sh turish va hech narsa qilmang. Bu, masalan, barcha ishlar allaqachon bajarilayotganda. Ishchi bu holatga kirganda, u uyquga ketadi va shunga ko'ra, uyg'onmaguncha ijro etmaydi;
Agar hovuzni boshqarish talab qilinmasa va rejalashtirilgan ishlar ro'yxati bo'sh bo'lmasa, ishchi ularni bajarishni boshlaydi. Biz shartli ravishda bunday ishchilarni chaqiramiz yugurish.
Agar kerak bo'lsa, ishchi rolni o'z zimmasiga oladi menejer basseyn. Hovuzda faqat bitta boshqaruvchi bo'lishi mumkin yoki umuman ishchi bo'lmasligi mumkin. Uning vazifasi har bir hovuz uchun optimal ishchi sonini saqlab qolishdir. U buni qanday qiladi? Birinchidan, uzoq vaqt davomida ishlamay qolgan ishchilar o'chiriladi. Ikkinchidan, bir vaqtning o'zida uchta shart bajarilsa, yangi ishchilar yaratiladi:

  • hali bajarilishi kerak bo'lgan vazifalar bor (hovuzda ishlaydi)
  • bo'sh ishchilar yo'q
  • ishlaydigan ishchilar yo'q (ya'ni faol va uxlamagan)
Biroq, oxirgi shart o'z nuanslariga ega. Agar hovuz navbatlari biriktirilmagan bo'lsa, unda ishlaydigan ishchilar hisobga olinmaydi, ular uchun bu shart har doim to'g'ri. Xuddi shu narsa bog'langan vazifani bajarayotgan ishchi uchun ham amal qiladi, lekin bayroq bilan WQ_CPU_INTENSIVE, navbatlar. Bundan tashqari, navbatlar bog'langan bo'lsa, ishchilar umumiy hovuzdagi ishlar bilan ishlaganligi sababli (yuqoridagi rasmdagi har bir yadro uchun ikkitadan biri), ularning ba'zilari ishlayotgan deb hisoblanadi, ba'zilari esa yo'q. Bundan tashqari, ishni bajarishdan kelib chiqadi WQ_CPU_INTENSIVE navbatlar darhol boshlanmasligi mumkin, lekin ular o'zlari boshqa ishlarning bajarilishiga xalaqit bermaydilar. Endi bu bayroq nima uchun shunday deb nomlangani va ishning tugashi uchun uzoq vaqt kerak bo'lganda nima uchun qo'llanilishi aniq bo'lishi kerak.

Ishlaydigan ishchilarni hisobga olish to'g'ridan-to'g'ri asosiy Linux yadrosi rejalashtiruvchisidan amalga oshiriladi. Ushbu nazorat mexanizmi ish navbatining juda ko'p ishchilarni yaratishiga yo'l qo'ymaslik uchun optimal parallellik darajasini ta'minlaydi, lekin ishni juda uzoq vaqt davomida keraksiz kutishiga olib kelmaydi.

Qiziqqanlar yadrodagi ishchi funksiyasiga qarashlari mumkin, u worker_thread() deb ataladi.

Ta'riflangan barcha funktsiyalar va tuzilmalarni fayllarda batafsilroq topish mumkin include/linux/workqueue.h, kernel/workqueue.c Va yadro/workqueue_internal.h. Ish navbati bo'yicha hujjatlar ham mavjud Documentation/workqueue.txt.

Shuni ham ta'kidlash kerakki, ish navbati mexanizmi yadroda nafaqat kechiktirilgan uzilishlarni qayta ishlash uchun ishlatiladi (garchi bu juda keng tarqalgan stsenariy bo'lsa ham).

Shunday qilib, biz Linux yadrosida kechiktirilgan uzilishlarni qayta ishlash mexanizmlarini ko'rib chiqdik - ko'p vazifalarni bajarishning maxsus shakli bo'lgan vazifa va ish navbati. Siz uzilishlar, topshiriqlar va ish navbatlari haqida Jonatan Korbet, Greg Kroah-Xartman, Alessandro Rubinining "Linux qurilma drayverlari" kitobida o'qishingiz mumkin, garchi u erdagi ma'lumotlar ba'zan eskirgan bo'lsa ham.

Biz Linux yadrosida multithreading mavzusini davom ettiramiz. Oxirgi marta men uzilishlar, ularni qayta ishlash va vazifalar to'g'risida gapirgan edim va dastlab bu bitta maqola bo'lishi mo'ljallanganligi sababli, ish navbati haqidagi hikoyamda men o'quvchi ular bilan tanish bo'lgan deb hisoblagan holda topshiriqlarga murojaat qilaman.
O'tgan safargidek, men hikoyamni iloji boricha batafsil va batafsil qilishga harakat qilaman.

Seriyadagi maqolalar:

  1. Linux yadrosida multitasking: ish navbati

Ish navbati

Ish navbati- bu topshiriqlardan ko'ra murakkabroq va og'irroq ob'ektlar. Men bu erda amalga oshirishning barcha nozikliklarini tasvirlashga harakat qilmayman, lekin umid qilamanki, men eng muhim narsalarni ko'proq yoki kamroq batafsil tahlil qilaman.
Ish navbatlari, masalan, vazifalar jadvallari kabi, kechiktirilgan uzilishlarni qayta ishlash uchun xizmat qiladi (garchi ular boshqa maqsadlarda ishlatilishi mumkin bo'lsa-da), lekin ular vazifa jadvallaridan farqli o'laroq, yadro jarayoni kontekstida bajariladi; shunga ko'ra, ular atomik bo'lishi shart emas va uyqu rejimidan foydalanishi mumkin. () funktsiyasi, turli xil sinxronlash vositalari va boshqalar.

Keling, avvalo, ish navbatini qayta ishlash jarayoni qanday tashkil etilganligini tushunaylik. Rasmda bu juda taxminan va soddalashtirilgan ko'rsatilgan, hamma narsa aslida qanday sodir bo'lishi quyida batafsil tavsiflangan.

Ushbu qorong'u materiyada bir nechta mavjudotlar ishtirok etadi.
Birinchidan, ish elementi(shunchaki qisqacha ish) biz rejalashtirmoqchi boʻlgan funksiyani (masalan, uzilish ishlovchisi) tavsiflovchi tuzilma boʻlib, uni vazifalar tuzilmasi analogi sifatida koʻrish mumkin. Rejalashtirishda vazifalar foydalanuvchidan yashirin navbatlarga qo'shildi, ammo endi biz maxsus navbatdan foydalanishimiz kerak - ish navbati.
Vazifalar rejalashtiruvchi funksiyasi tomonidan racklanadi va ish navbati ishchilar deb ataladigan maxsus iplar tomonidan qayta ishlanadi.
Ishchi ning ish navbatdan asinxron bajarilishini ta'minlaydi. Garchi ular ishni aylanish tartibida chaqirsalar ham, umumiy holatda qat'iy, ketma-ket bajarish haqida gap bo'lmaydi: axir, bu erda oldindan olish, uxlash, kutish va hokazo.

Umuman olganda, ishchilar yadro iplari, ya'ni ular asosiy Linux yadrosi rejalashtiruvchisi tomonidan boshqariladi. Ammo ishchilar ishning parallel bajarilishini qo'shimcha tashkil etishni rejalashtirishga qisman aralashadilar. Bu quyida batafsilroq muhokama qilinadi.

Ish navbati mexanizmining asosiy imkoniyatlarini tavsiflash uchun men APIni o'rganishni taklif qilaman.

Navbat va uning yaratilishi haqida

alloc_workqueue(fmt, bayroqlar, max_active, args...)
fmt va args parametrlari nom va unga argumentlar uchun printf formatidir. Max_activate parametri ushbu navbatdan bitta protsessorda parallel ravishda bajarilishi mumkin bo'lgan ishlarning maksimal soni uchun javobgardir.
Navbatni quyidagi bayroqlar bilan yaratish mumkin:
  • WQ_HIGHPRI
  • WQ_UNBOUND
  • WQ_CPU_INTENSIVE
  • WQ_FREEZABLE
  • WQ_MEM_RECLAIM
Bayroqqa alohida e'tibor berilishi kerak WQ_UNBOUND. Ushbu bayroqning mavjudligiga qarab, navbatlar bog'langan va bog'lanmaganlarga bo'linadi.
Bog'langan navbatlarda Qo'shilganda, ishlar joriy protsessorga bog'lanadi, ya'ni bunday navbatlarda ishlar uni rejalashtiruvchi yadroda bajariladi. Shu nuqtai nazardan, bog'langan navbatlar topshiriqlarga o'xshaydi.
Biriktirilmagan navbatlarda ish har qanday yadroda bajarilishi mumkin.

Linux yadrosida ish navbatini amalga oshirishning muhim xususiyati - bog'langan navbatlarda mavjud bo'lgan parallel bajarishning qo'shimcha tashkil etilishi. Quyida batafsilroq yozilgan, ammo hozir aytamanki, u imkon qadar kamroq xotira ishlatadigan va protsessor bo'sh turmasligi uchun amalga oshiriladi. Bularning barchasi bitta ishda juda ko'p protsessor sikllaridan foydalanilmaydi degan taxmin bilan amalga oshiriladi.
Bu biriktirilmagan navbatlar uchun emas. Aslida, bunday navbatlar ishchilarga kontekstni taqdim etadi va ularni imkon qadar erta boshlaydi.
Shunday qilib, agar protsessor intensiv ish yuki kutilsa, biriktirilmagan navbatlardan foydalanish kerak, chunki bu holda rejalashtiruvchi bir nechta yadrolarda parallel bajarilishini nazorat qiladi.

Vazifalar bilan taqqoslaganda, ishlarga oddiy yoki yuqori bajarilish ustuvorligi berilishi mumkin. Ustuvorlik butun navbat uchun umumiydir. Odatiy bo'lib, navbat odatdagi ustuvorlikka ega va agar siz bayroqni o'rnatsangiz WQ_HIGHPRI, keyin, mos ravishda, yuqori.

Bayroq WQ_CPU_INTENSIVE faqat bog'langan navbatlar uchun mantiqiy. Ushbu bayroq parallel ijro etishni qo'shimcha tashkil etishda ishtirok etishdan bosh tortishdir. Ish protsessor vaqtini ko'p sarflashi kutilayotganda ushbu bayroqdan foydalanish kerak, bu holda mas'uliyatni rejalashtiruvchiga o'tkazish yaxshiroqdir. Bu quyida batafsilroq tavsiflanadi.

Bayroqlar WQ_FREEZABLE Va WQ_MEM_RECLAIM aniq va mavzu doirasidan tashqarida, shuning uchun biz ularga batafsil to'xtalib o'tirmaymiz.

Ba'zan o'z navbatlaringizni yaratish emas, balki umumiy navlardan foydalanish mantiqan to'g'ri keladi. Asosiylari:

  • system_wq - tez ishlash uchun bog'langan navbat
  • system_long_wq - bajarilishi uzoq vaqt talab qilinadigan ishlar uchun bog'langan navbat
  • system_unbound_wq - bog'lanmagan navbat

Ish va ularni rejalashtirish haqida

Endi ishlar bilan shug'ullanamiz. Birinchidan, ishga tushirish, deklaratsiya va tayyorlash makroslarini ko'rib chiqamiz:
DECLARE(_DELAYED)_WORK(nom, bekor (*funksiya)(struct work_struct *ish)); /* kompilyatsiya vaqtida */ INIT(_DELAYED)_WORK(_work, _func); /* bajarish paytida */ TAYYORLASH(_KECIKTIRIB)_ISH(_ish, _func); /* bajarilayotgan funksiyani o‘zgartirish uchun */
Ishlar quyidagi funktsiyalar yordamida navbatga qo'shiladi:
bool queue_work(struct workqueue_struct *wq, struct work_struct *ish); bool queue_delayed_work(struct workqueue_struct *wq, struct delayed_work *dwork, imzosiz uzoq kechikish); /* ish faqat kechikish muddati tugagandan keyingina navbatga qo'shiladi */
Bu haqida batafsilroq to'xtalib o'tishga arziydi. Garchi biz navbatni parametr sifatida belgilagan bo'lsak-da, aslida ishlar, tuyulishi mumkin bo'lganidek, ish navbatining o'zida emas, balki butunlay boshqa ob'ektda - ishchi_pool strukturasining navbat ro'yxatida joylashtiriladi. Tuzilishi ishchi_hovuz, aslida, ish navbati mexanizmini tashkil qilishda eng muhim ob'ektdir, garchi foydalanuvchi uchun u sahna ortida qolsa. Aynan ular bilan ishchilar ishlaydi va ularda barcha asosiy ma'lumotlar mavjud.

Keling, tizimda qanday hovuzlar borligini ko'rib chiqaylik.
Boshlash uchun, bog'langan navbatlar uchun hovuzlar (rasmda). Har bir protsessor uchun ikkita ishchi hovuzi statik ravishda ajratilgan: biri yuqori ustuvorlikdagi ishlar uchun, ikkinchisi normal ustuvorlik bilan ishlash uchun. Ya'ni, agar bizda to'rtta yadro bo'lsa, unda kerakli darajada ko'p ish navbati bo'lishi mumkinligiga qaramasdan, faqat sakkizta bog'langan hovuz bo'ladi.
Ish navbatini yaratganimizda, u har bir protsessor uchun ajratilgan xizmatga ega pool_workqueue(pwq). Har bir bunday pool_workqueue bir xil protsessorda ajratilgan va navbat turiga ustuvorlik bilan mos keladigan ishchilar puli bilan bog'langan. Ular orqali ish navbati ishchilar hovuzi bilan o'zaro ta'sir qiladi.
Ishchilar dastlab qaysi ish navbatiga tegishli ekanligini ajratmasdan, ishchilar hovuzidan ishni beg'araz bajaradilar.

Biriktirilmagan navbatlar uchun ishchi hovuzlari dinamik ravishda ajratiladi. Barcha navbatlarni o'z parametrlariga ko'ra ekvivalentlik sinflariga bo'lish mumkin va har bir bunday sinf uchun o'z ishchilar puli yaratiladi. Ularga maxsus xesh-jadval yordamida kirish mumkin, bu erda kalit parametrlar to'plamidir va qiymat mos ravishda ishchilar hovuzidir.
Aslida, bog'lanmagan navbatlar uchun hamma narsa biroz murakkabroq: agar bog'langan navbatlar uchun pwq va navbatlar har bir CPU uchun yaratilgan bo'lsa, bu erda ular har bir NUMA tugun uchun yaratilgan, ammo bu biz batafsil ko'rib chiqmaydigan qo'shimcha optimallashtirish.

Har xil kichik narsalar

Rasmni to'ldirish uchun men API-dan bir nechta funktsiyalarni ham beraman, lekin ular haqida batafsil gapirmayman:
/* Majburiy bajarish */ bool flush_work(struct work_struct *ish); bool flush_kechiktirilgan_ish(tuzilma kechiktirilgan_ish *dwork); /* Ishning bajarilishini bekor qilish */ bool cancel_work_sync(struct work_struct *ish); bool bekor qilish_kechiktirilgan_ish(tuzilma kechiktirilgan_ish *dwork); bool cancel_delayed_work_sync(tuzilma kechiktirilgan_ish *dwork); /* Navbatni o'chirish */ yo'q qilish_ishchi navbati(struct workqueue_struct *wq);

Ishchilar o'z ishlarini qanday bajarishadi

Endi biz API bilan tanishganimizdan so'ng, keling, uning qanday ishlashi va boshqarilishini batafsilroq tushunishga harakat qilaylik.
Har bir hovuzda vazifalarni bajaradigan ishchilar to'plami mavjud. Bundan tashqari, ishchilar soni mavjud vaziyatga moslashib, dinamik ravishda o'zgaradi.
Biz allaqachon bilib olganimizdek, ishchilar yadro kontekstida ishni bajaradigan iplardir. Ishchi ularni ketma-ket, u bilan bog'langan ishchilar hovuzidan oladi va ishchilar, biz allaqachon bilganimizdek, turli manba navbatlariga tegishli bo'lishi mumkin.

Ishchilar shartli ravishda uchta mantiqiy holatda bo'lishi mumkin: ular bo'sh, ishlaydigan yoki boshqaruvchi bo'lishi mumkin.
Ishchi mumkin bo'sh turish va hech narsa qilmang. Bu, masalan, barcha ishlar allaqachon bajarilayotganda. Ishchi bu holatga kirganda, u uyquga ketadi va shunga ko'ra, uyg'onmaguncha ijro etmaydi;
Agar hovuzni boshqarish talab qilinmasa va rejalashtirilgan ishlar ro'yxati bo'sh bo'lmasa, ishchi ularni bajarishni boshlaydi. Biz shartli ravishda bunday ishchilarni chaqiramiz yugurish.
Agar kerak bo'lsa, ishchi rolni o'z zimmasiga oladi menejer basseyn. Hovuzda faqat bitta boshqaruvchi bo'lishi mumkin yoki umuman ishchi bo'lmasligi mumkin. Uning vazifasi har bir hovuz uchun optimal ishchi sonini saqlab qolishdir. U buni qanday qiladi? Birinchidan, uzoq vaqt davomida ishlamay qolgan ishchilar o'chiriladi. Ikkinchidan, bir vaqtning o'zida uchta shart bajarilsa, yangi ishchilar yaratiladi:

  • hali bajarilishi kerak bo'lgan vazifalar bor (hovuzda ishlaydi)
  • bo'sh ishchilar yo'q
  • ishlaydigan ishchilar yo'q (ya'ni faol va uxlamagan)
Biroq, oxirgi shart o'z nuanslariga ega. Agar hovuz navbatlari biriktirilmagan bo'lsa, unda ishlaydigan ishchilar hisobga olinmaydi, ular uchun bu shart har doim to'g'ri. Xuddi shu narsa bog'langan vazifani bajarayotgan ishchi uchun ham amal qiladi, lekin bayroq bilan WQ_CPU_INTENSIVE, navbatlar. Bundan tashqari, navbatlar bog'langan bo'lsa, ishchilar umumiy hovuzdagi ishlar bilan ishlaganligi sababli (yuqoridagi rasmdagi har bir yadro uchun ikkitadan biri), ularning ba'zilari ishlayotgan deb hisoblanadi, ba'zilari esa yo'q. Bundan tashqari, ishni bajarishdan kelib chiqadi WQ_CPU_INTENSIVE navbatlar darhol boshlanmasligi mumkin, lekin ular o'zlari boshqa ishlarning bajarilishiga xalaqit bermaydilar. Endi bu bayroq nima uchun shunday deb nomlangani va ishning tugashi uchun uzoq vaqt kerak bo'lganda nima uchun qo'llanilishi aniq bo'lishi kerak.

Ishlaydigan ishchilarni hisobga olish to'g'ridan-to'g'ri asosiy Linux yadrosi rejalashtiruvchisidan amalga oshiriladi. Ushbu nazorat mexanizmi ish navbatining juda ko'p ishchilarni yaratishiga yo'l qo'ymaslik uchun optimal parallellik darajasini ta'minlaydi, lekin ishni juda uzoq vaqt davomida keraksiz kutishiga olib kelmaydi.

Qiziqqanlar yadrodagi ishchi funksiyasiga qarashlari mumkin, u worker_thread() deb ataladi.

Ta'riflangan barcha funktsiyalar va tuzilmalarni fayllarda batafsilroq topish mumkin include/linux/workqueue.h, kernel/workqueue.c Va yadro/workqueue_internal.h. Ish navbati bo'yicha hujjatlar ham mavjud Documentation/workqueue.txt.

Shuni ham ta'kidlash kerakki, ish navbati mexanizmi yadroda nafaqat kechiktirilgan uzilishlarni qayta ishlash uchun ishlatiladi (garchi bu juda keng tarqalgan stsenariy bo'lsa ham).

Shunday qilib, biz Linux yadrosida kechiktirilgan uzilishlarni qayta ishlash mexanizmlarini ko'rib chiqdik - ko'p vazifalarni bajarishning maxsus shakli bo'lgan vazifa va ish navbati. Siz uzilishlar, topshiriqlar va ish navbatlari haqida Jonatan Korbet, Greg Kroah-Xartman, Alessandro Rubinining "Linux qurilma drayverlari" kitobida o'qishingiz mumkin, garchi u erdagi ma'lumotlar ba'zan eskirgan bo'lsa ham.