18-bo‘lim
Yuklanish jarayoni va init tizimi
BIOS va UEFI, yuklovchi, yadro yuklanishi, initramfs, PID 1 va systemd, xizmatlarni boshqarish va daemon yaratish.
Ushbu bo‘lim mundarijasi
Tugmani bosgandan qobiq belgisi chiqqunicha o'nlab bosqich o'tadi. Ularni bilish nosozliklarni topishda hal qiluvchi ahamiyatga ega.
To'liq zanjir #
UEFI va BIOS #
| Xususiyat | BIOS (eski) | UEFI (zamonaviy) |
|---|---|---|
| Disk jadvali | MBR | GPT |
| Maksimal disk | 2 TB | 9 ZB |
| Bo'limlar soni | 4 ta asosiy | 128+ |
| Yuklovchi joyi | Birinchi 512 bayt | EFI bo'limidagi fayl |
| Xavfsiz yuklash | Yo'q | Secure Boot |
[ -d /sys/firmware/efi ] && echo "UEFI" || echo "BIOS"
UEFI
sudo efibootmgr
BootCurrent: 0001
BootOrder: 0001,0000,2001
Boot0000* Windows Boot Manager
Boot0001* ubuntu
Boot2001* EFI USB Device
lsblk -o NAME,SIZE,FSTYPE,MOUNTPOINT
NAME SIZE FSTYPE MOUNTPOINT
nvme0n1 476G
├─p1 512M vfat /boot/efi
├─p2 1G ext4 /boot
└─p3 474G LVM2_member
Yadro parametrlari #
cat /proc/cmdline
BOOT_IMAGE=/vmlinuz-6.8.0-45-generic root=UUID=a1b2c3d4 ro quiet splash
| Parametr | Ma'nosi |
|---|---|
root= | Ildiz fayl tizimi qayerda |
ro | Avval faqat o'qishga ulash |
quiet | Yuklanish xabarlarini yashirish |
single | Bir foydalanuvchili rejim |
init=/bin/bash | systemd o'rniga qobiq |
nomodeset | Video drayverni yuklamaslik |
GRUB menyusida e bosib, linux qatoriga qo'shing:
init=/bin/bash
Ctrl+X bilan yuklaganingizda systemd o'rniga to'g'ridan-to'g'ri
qobiq ochiladi - parolsiz, root sifatida.
Keyin:
mount -o remount,rw /
passwd husanboy
exec /sbin/init
Bu jismoniy kirish - parolni chetlab o'tish demakdir. Shuning uchun serverlarda:
- GRUB ga parol qo'yiladi;
- Disk shifrlanadi (LUKS);
- Secure Boot yoqiladi.
Shifrlanmagan disk va jismoniy kirish - hamma parol va huquqlar ma'nosiz demakdir.
initramfs nima uchun kerak? #
lsinitramfs /boot/initrd.img-$(uname -r) | head -12
.
bin
conf
etc
init
lib
scripts
usr/lib/modules/6.8.0-45-generic/kernel/drivers/md/raid1.ko
usr/lib/modules/6.8.0-45-generic/kernel/drivers/scsi/sd_mod.ko
usr/lib/modules/6.8.0-45-generic/kernel/fs/ext4/ext4.ko
Yadro ildiz fayl tizimini ulashi kerak. Buning uchun unga kerak:
- Disk kontrolleri drayveri (NVMe, SATA, RAID);
- Fayl tizimi drayveri (ext4, XFS, Btrfs);
- Shifrlangan bo'lsa - LUKS moduli;
- LVM bo'lsa - LVM vositalari.
Lekin bu drayverlar diskda yotibdi, unga esa hali kira olmaymiz.
initramfs - xotiraga yuklanadigan kichik vaqtinchalik fayl
tizimi. Unda kerakli modullar va init skripti bor. U:
- Kerakli modullarni yuklaydi;
- Shifrlangan diskdan parolni so'raydi;
- LVM/RAID ni yig'adi;
- Haqiqiy ildizni ulaydi;
switch_rootbilan boshqaruvni unga o'tkazadi.
Yadroni yangilagandan keyin initramfs ni qayta qurish kerak:
sudo update-initramfs -u -k all
Aks holda tizim yuklanmay qolishi mumkin - eng ko'p uchraydigan "yuklanmayapti" sababi.
PID 1 #
#include <stdio.h>
#include <unistd.h>
int main(void) {
pid_t ozim = getpid();
pid_t ota = getppid();
printf("Bizning PID : %s\n", ozim == 1 ? "1 - biz init miz" : "1 emas");
printf("Otamiz bormi? : %s\n", ota > 0 ? "ha" : "yo'q");
printf("Ota PID 1 mi? : %s\n",
ota == 1 ? "ha - to'g'ridan-to'g'ri init dan" : "yo'q");
printf("\nPID 1 ning maxsus xossalari:\n");
printf(" - Uni o'ldirib bo'lmaydi (yadro panic beradi)\n");
printf(" - Yetim jarayonlar unga meros qoladi\n");
printf(" - U zombi jarayonlarni yig'ishi shart\n");
printf(" - Odatiy signal ta'siri unga qo'llanmaydi\n");
return 0;
}
Bizning PID : 1 emas
Otamiz bormi? : ha
Ota PID 1 mi? : yo'q
PID 1 ning maxsus xossalari:
- Uni o'ldirib bo'lmaydi (yadro panic beradi)
- Yetim jarayonlar unga meros qoladi
- U zombi jarayonlarni yig'ishi shart
- Odatiy signal ta'siri unga qo'llanmaydi
ps -p 1 -o pid,comm,args
PID COMMAND COMMAND
1 systemd /sbin/init splash
Konteynerda sizning dasturingiz PID 1 bo'ladi. Bu ikki muammo tug'diradi:
1. Zombi jarayonlar to'planadi
Konteyner ichida dasturingiz bola yaratib, ularni yig'masa, ular abadiy zombi bo'lib qoladi - chunki ularni yig'adigan "haqiqiy init" yo'q.
2. Signallar ishlamaydi
PID 1 uchun odatiy signal ta'siri qo'llanmaydi. Ishlovchi
o'rnatilmagan bo'lsa, SIGTERM shunchaki e'tiborsiz qoladi.
Natija: docker stop 10 soniya kutadi, keyin SIGKILL yuboradi.
Ma'lumot yo'qoladi.
Yechimlar:
# 1. Kichik init ishlatish
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
CMD ["node", "server.js"]
# 2. Docker ning o'z init i
docker run --init mening-obrazim
# 3. exec shakli - qobiq oradan chiqadi
CMD ["node", "server.js"] # to'g'ri
# CMD node server.js # noto'g'ri - PID 1 bu sh
Uchinchisi eng ko'p uchraydigan xato: CMD ning qobiq shaklida
PID 1 bo'lib /bin/sh qoladi va u signalni dasturingizga
uzatmaydi.
systemd birliklari #
| Tur | Nima uchun |
|---|---|
.service | Xizmat (daemon) |
.socket | Soketni tinglash, so'rovda xizmatni ishga tushirish |
.timer | Vaqt bo'yicha ishga tushirish (cron o'rniga) |
.mount | Fayl tizimini ulash |
.target | Birliklar guruhi (runlevel o'rniga) |
.path | Fayl o'zgarganda ishga tushirish |
systemctl list-units --type=service --state=running | head -6
UNIT LOAD ACTIVE SUB DESCRIPTION
cron.service loaded active running Regular background program
dbus.service loaded active running D-Bus System Message Bus
nginx.service loaded active running A high performance web server
ssh.service loaded active running OpenBSD Secure Shell server
systemd-journald.service loaded active running Journal Service
[Unit]
Description=Mening veb xizmatim
After=network.target
Requires=postgresql.service
[Service]
Type=notify
User=veb
Group=veb
WorkingDirectory=/opt/mening-xizmatim
ExecStart=/opt/mening-xizmatim/server
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5
# Xavfsizlik cheklovlari
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/lib/mening-xizmatim
AmbientCapabilities=CAP_NET_BIND_SERVICE
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now mening-xizmatim
systemctl status mening-xizmatim
Yuqoridagi faylning "Xavfsizlik" qismi juda kuchli - u AppArmor profiliga o'xshash himoya beradi, lekin sozlash ancha oson:
| Sozlama | Ta'siri |
|---|---|
NoNewPrivileges | setuid orqali huquq ko'tarib bo'lmaydi |
PrivateTmp | O'z alohida /tmp katalogi |
ProtectSystem=strict | Butun fayl tizimi faqat o'qishga |
ProtectHome | /home ko'rinmaydi |
ReadWritePaths | Faqat sanab o'tilgan joyga yozish |
PrivateDevices | /dev cheklangan |
RestrictAddressFamilies | Faqat kerakli soket turlari |
Xizmatingiz qanchalik himoyalanganini baholash:
systemd-analyze security nginx.service
→ Overall exposure level for nginx.service: 8.1 EXPOSED 🙁
Ball 0 dan 10 gacha - past bo'lgani yaxshi. Har bir sozlamani qo'shgach ball tushadi.
Yuklanish tezligini tahlil qilish #
systemd-analyze
Startup finished in 4.812s (firmware) + 2.104s (loader) + 3.284s (kernel)
+ 8.412s (userspace) = 18.613s
graphical.target reached after 8.401s in userspace
systemd-analyze blame | head -6
4.821s NetworkManager-wait-online.service
2.104s snapd.service
1.284s docker.service
892ms systemd-journal-flush.service
621ms [email protected]
systemd-analyze critical-chain
graphical.target @8.401s
└─multi-user.target @8.398s
└─docker.service @7.112s +1.284s
└─network-online.target @7.108s
└─NetworkManager-wait-online.service @2.284s +4.821s
+ belgisi - xizmatning o'z ishlash vaqti; @ - u
boshlangan payt.
Daemon yaratish #
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
/* An'anaviy daemon yaratish - klassik ikki fork usuli */
static int daemonlashtirish(void) {
pid_t birinchi = fork();
if (birinchi < 0) {
return -1;
}
if (birinchi > 0) {
_exit(0); /* ota chiqadi - bola yetim bo'ladi */
}
/* Yangi sessiya - terminaldan uziladi */
if (setsid() < 0) {
return -1;
}
/* Ikkinchi fork - endi terminal ola olmaymiz */
pid_t ikkinchi = fork();
if (ikkinchi < 0) {
return -1;
}
if (ikkinchi > 0) {
_exit(0);
}
umask(0);
if (chdir("/") < 0) { /* ulangan diskni band qilmaslik */
return -1;
}
return 0;
}
int main(void) {
printf("Daemon yaratish bosqichlari:\n");
printf(" 1. fork - ota chiqadi, bola yetim bo'ladi\n");
printf(" 2. setsid - yangi sessiya, terminaldan uzilish\n");
printf(" 3. fork - sessiya yetakchisi bo'lmaslik\n");
printf(" 4. umask(0) - huquqlarni to'liq nazorat qilish\n");
printf(" 5. chdir(\"/\") - ulangan diskni bo'shatish\n");
printf(" 6. 0,1,2 ni /dev/null ga yo'naltirish\n");
/* Funksiya ishlatilganini kompilyatorga bildiramiz */
printf("\nFunksiya mavjudmi? %s\n",
daemonlashtirish != NULL ? "ha" : "yo'q");
printf("\nsystemd bilan bularning hech biri KERAK EMAS\n");
printf("Type=simple bilan oddiy dastur yozing\n");
return 0;
}
Daemon yaratish bosqichlari:
1. fork - ota chiqadi, bola yetim bo'ladi
2. setsid - yangi sessiya, terminaldan uzilish
3. fork - sessiya yetakchisi bo'lmaslik
4. umask(0) - huquqlarni to'liq nazorat qilish
5. chdir("/") - ulangan diskni bo'shatish
6. 0,1,2 ni /dev/null ga yo'naltirish
Funksiya mavjudmi? ha
systemd bilan bularning hech biri KERAK EMAS
Type=simple bilan oddiy dastur yozing
Yuqoridagi ikki fork usuli - 1980-yillar an'anasi. systemd davrida u nafaqat keraksiz, balki zararli:
| Muammo | Sabab |
|---|---|
| systemd PID ni yo'qotadi | Ota chiqib ketadi |
| Loglar yo'qoladi | stdout /dev/null ga ketgan |
| Qayta ishga tushirish buziladi | Holatni kuzatib bo'lmaydi |
To'g'ri yondashuv - oddiy dastur yozing:
int main(void) {
while (ishlaymiz) {
sorovni_qayta_ishlash();
printf("so'rov bajarildi\n"); /* journald yig'adi */
}
}
[Service]
Type=simple
ExecStart=/opt/xizmat/server
Loglar avtomatik journald ga tushadi:
journalctl -u mening-xizmatim -f
Agar xizmat "tayyorman" deb aytishi kerak bo'lsa, Type=notify
va sd_notify(0, "READY=1") ishlating - bu systemd ga aniq
signal beradi.
Loglarni ko'rish #
journalctl -b -p err
sen 09 08:14:22 husanboy-pc kernel: ACPI Error: No handler for Region
sen 09 08:14:31 husanboy-pc bluetoothd[891]: Failed to set mode: Blocked
| Buyruq | Nima ko'rsatadi |
|---|---|
journalctl -b | Joriy yuklanish loglari |
journalctl -b -1 | Oldingi yuklanish |
journalctl -u nginx -f | Xizmat loglarini kuzatish |
journalctl -p err | Faqat xatolar |
journalctl --since "1 hour ago" | Vaqt bo'yicha |
journalctl -k | Faqat yadro xabarlari |
journalctl --disk-usage | Loglar egallagan joy |
dmesg -T | tail -3
[Mon Sep 9 08:14:18 2026] EXT4-fs (nvme0n1p3): mounted filesystem
[Mon Sep 9 08:14:19 2026] systemd[1]: systemd 255 running in system mode
[Mon Sep 9 08:14:22 2026] nvidia: loading out-of-tree module
- Tizimingiz UEFI yoki BIOS ekanini aniqlang.
/proc/cmdlinedagi yadro parametrlarini tushuntiring.lsinitramfsbilan initramfs ichidagi modullarni ko'ring.- initramfs nima uchun kerakligini o'z so'zingiz bilan ayting.
ps -p 1bilan PID 1 nima ekanini aniqlang.- Docker da PID 1 muammosini va uch yechimini sanang.
- O'zingizning
.servicefaylingizni yozing. systemd-analyze securitybilan xizmatni baholang.systemd-analyze blamebilan sekin xizmatni toping.journalctl -b -p errbilan yuklanish xatolarini ko'ring.
Xulosa #
- Yuklanish: UEFI → yuklovchi → yadro → initramfs → PID 1 → login.
- UEFI GPT bilan ishlaydi va Secure Boot ni qo'llab-quvvatlaydi.
- Yadro parametrlari
/proc/cmdlineda ko'rinadi. init=/bin/bashbilan parolni chetlab o'tish mumkin - disk shifrlash shart.- initramfs "tovuq va tuxum" muammosini hal qiladi.
- Yadro yangilangach initramfs ni qayta quring.
- PID 1 ni o'ldirib bo'lmaydi; u zombi larni yig'adi.
- Konteynerda PID 1
SIGTERMni e'tiborsiz qoldiradi. CMDning exec shaklini ishlating.- systemd birliklari:
.service,.socket,.timer,.target. - systemd xavfsizlik cheklovlari AppArmor kabi himoya beradi.
- Zamonaviy xizmat daemon bo'lishi shart emas -
Type=simple.
Keyingi bo'limda virtualizatsiya va konteynerlarni ko'ramiz.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
Xatolik topdingizmi?
Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.