13-bo‘lim
Fayl tizimining ichki tuzilishi
Superblok, inode, blok ajratish, bilvosita bloklar, ekstentlar, jurnal (journaling), ext4 va boshqa fayl tizimlari.
Ushbu bo‘lim mundarijasi
Diskda faqat raqamlangan bloklar bor. "Fayl", "katalog", "nom" tushunchalari - fayl tizimi yaratgan tuzilmalar.
Diskning umumiy tuzilishi #
sudo dumpe2fs -h /dev/sda1
Filesystem volume name: <none>
Filesystem features: has_journal ext_attr dir_index extent 64bit
Filesystem state: clean
Inode count: 6553600
Block count: 26214400
Free blocks: 14829213
Free inodes: 6098442
First block: 0
Block size: 4096
Inode size: 256
Journal size: 1024M
inode nima? #
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
int main(void) {
FILE *f = fopen("inode_sinov.txt", "w");
if (f == NULL) {
return 1;
}
fputs("salom", f);
fclose(f);
struct stat h;
stat("inode_sinov.txt", &h);
printf("inode raqami : %s\n", h.st_ino > 0 ? "mavjud" : "yo'q");
printf("Havolalar : %ld\n", (long) h.st_nlink);
printf("Hajm : %ld bayt\n", (long) h.st_size);
printf("Blok hajmi : %ld bayt\n", (long) h.st_blksize);
printf("Egallagan blok : %ld (512 baytli)\n", (long) h.st_blocks);
/* Ikkinchi nom qo'shamiz */
link("inode_sinov.txt", "ikkinchi_nom.txt");
stat("inode_sinov.txt", &h);
printf("\nQattiq havoladan keyin:\n");
printf("Havolalar : %ld\n", (long) h.st_nlink);
printf("Hajm o'zgardimi? %s\n", h.st_size == 5 ? "yo'q" : "ha");
unlink("ikkinchi_nom.txt");
unlink("inode_sinov.txt");
return 0;
}
inode raqami : mavjud
Havolalar : 1
Hajm : 5 bayt
Blok hajmi : 4096 bayt
Egallagan blok : 8 (512 baytli)
Qattiq havoladan keyin:
Havolalar : 2
Hajm o'zgardimi? yo'q
ls -li
4521234 -rw-r--r-- 2 husanboy husanboy 5 sen 9 10:22 ikkinchi_nom.txt
4521234 -rw-r--r-- 2 husanboy husanboy 5 sen 9 10:22 inode_sinov.txt
Birinchi ustun - inode raqami. Ikkala nom bir xil raqamga ega.
Bloklarni ajratish usullari #
| Usul | G'oya | Kamchiligi |
|---|---|---|
| Uzluksiz | Fayl ketma-ket bloklarda | Fragmentatsiya, o'sish qiyin |
| Bog'langan ro'yxat | Har blok keyingisiga ishora | Tasodifiy kirish sekin |
| FAT | Ro'yxat alohida jadvalda | Jadval katta, RAM da turishi kerak |
| inode (bilvosita) | Manzillar ro'yxati inode da | Katta faylga qo'shimcha o'qish |
| Ekstent | (boshlanish, uzunlik) juftliklari | Juda parchalangan faylda samarasiz |
Bilvosita bloklar #
#include <stdio.h>
#define BLOK 4096
#define MANZIL 4 /* bitta manzil 4 bayt */
#define TOGRI 12
int main(void) {
long manzil_blokda = BLOK / MANZIL; /* 1024 */
long togri = (long) TOGRI * BLOK;
long bir = manzil_blokda * BLOK;
long ikki = manzil_blokda * manzil_blokda * BLOK;
long uch = manzil_blokda * manzil_blokda * manzil_blokda * BLOK;
printf("Bitta blokda %ld ta manzil sig'adi\n\n", manzil_blokda);
printf("To'g'ridan-to'g'ri : %8ld KB\n", togri / 1024);
printf("1-bilvosita : %8ld KB\n", bir / 1024);
printf("2-bilvosita : %8ld MB\n", ikki / (1024 * 1024));
printf("3-bilvosita : %8ld GB\n", uch / (1024 * 1024 * 1024));
long jami = togri + bir + ikki + uch;
printf("\nMaksimal fayl hajmi: %ld GB\n", jami / (1024 * 1024 * 1024));
/* Katta faylning oxirgi bloki uchun nechta o'qish kerak? */
printf("\n48 KB gacha fayl uchun o'qish: 1 ta (inode dagi manzil)\n");
printf("4 TB fayl oxiri uchun o'qish : 4 ta (3 bilvosita + blok)\n");
return 0;
}
Bitta blokda 1024 ta manzil sig'adi
To'g'ridan-to'g'ri : 48 KB
1-bilvosita : 4096 KB
2-bilvosita : 4096 MB
3-bilvosita : 4096 GB
Maksimal fayl hajmi: 4100 GB
48 KB gacha fayl uchun o'qish: 1 ta (inode dagi manzil)
4 TB fayl oxiri uchun o'qish : 4 ta (3 bilvosita + blok)
Ekstentlar - ext4 ning yechimi #
#include <stdio.h>
typedef struct {
long boshlanish; /* birinchi blok raqami */
long uzunlik; /* nechta ketma-ket blok */
} Ekstent;
int main(void) {
/* 1 GB lik fayl, 4 KB bloklar = 262144 blok */
long bloklar = 262144;
/* Bilvosita usulda har bir blok uchun alohida manzil */
long bilvosita_manzillar = bloklar;
long bilvosita_bayt = bilvosita_manzillar * 4;
/* Ekstent usulida: fayl 3 bo'lakda joylashgan bo'lsin */
Ekstent ekstentlar[3] = {
{ 100000, 131072 },
{ 400000, 65536 },
{ 700000, 65536 }
};
long ekstent_bayt = 3 * sizeof(Ekstent);
long jami = 0;
for (int i = 0; i < 3; i++) {
jami += ekstentlar[i].uzunlik;
}
printf("1 GB fayl = %ld ta blok\n\n", bloklar);
printf("Bilvosita usul : %ld ta manzil = %ld KB meta-ma'lumot\n",
bilvosita_manzillar, bilvosita_bayt / 1024);
printf("Ekstent usuli : 3 ta yozuv = %ld bayt meta-ma'lumot\n",
ekstent_bayt);
printf("\nEkstent bilan qamralgan bloklar: %ld\n", jami);
printf("Hammasi qamraldimi? %s\n", jami == bloklar ? "ha" : "yo'q");
printf("Meta-ma'lumot necha barobar kam? %ld\n",
bilvosita_bayt / ekstent_bayt);
return 0;
}
1 GB fayl = 262144 ta blok
Bilvosita usul : 262144 ta manzil = 1024 KB meta-ma'lumot
Ekstent usuli : 3 ta yozuv = 48 bayt meta-ma'lumot
Ekstent bilan qamralgan bloklar: 262144
Hammasi qamraldimi? ha
Meta-ma'lumot necha barobar kam? 21845
Ekstent - bu (boshlanish bloki, uzunlik) juftligi. Bitta yozuv minglab ketma-ket blokni ifodalaydi.
| Fayl turi | Ekstent soni |
|---|---|
| Yangi yozilgan video | 1-5 ta |
| Uzoq o'sgan log fayl | 100+ ta |
| Ma'lumotlar bazasi fayli | O'nlab |
Bu fragmentatsiya darajasiga bog'liq. Faylni ko'rish:
filefrag -v katta.iso
Filesystem type is: ef53
File size of katta.iso is 4700372992 (1147552 blocks of 4096 bytes)
ext: logical_offset: physical_offset: length: flags:
0: 0.. 32767: 1245184.. 1277951: 32768:
1: 32768.. 65535: 1277952.. 1310719: 32768:
katta.iso: 36 extents found
36 ta ekstent - juda yaxshi natija. 4.7 GB fayl uchun bilvosita usulda 1.1 million manzil kerak bo'lardi.
Jurnal (journaling) #
| Rejim | Nima jurnallanadi | Xavfsizlik | Tezlik |
|---|---|---|---|
journal | Meta-ma'lumot va ma'lumot | Eng yuqori | Eng sekin |
ordered | Faqat meta; ma'lumot avval yoziladi | Yaxshi | Odatiy |
writeback | Faqat meta, tartibsiz | Past | Tez |
mount | grep " / "
/dev/sda1 on / type ext4 (rw,relatime,errors=remount-ro)
sudo tune2fs -l /dev/sda1 | grep -i journal
Filesystem features: has_journal ext_attr resize_inode dir_index
Journal inode: 8
Journal backup: inode blocks
ordered rejim ham hamma narsani kafolatlamaydiordered (Linux dagi odatiy rejim) faqat shuni kafolatlaydi:
meta-ma'lumot ma'lumotdan keyin yoziladi.
Ya'ni siz hech qachon "fayl hajmi 8 KB, lekin ichida axlat" holatiga tushmaysiz.
Lekin write() qaytgani ma'lumot diskda degani emas - u faqat
yadro keshida bo'lishi mumkin.
Kafolat kerak bo'lsa:
write(fd, malumot, hajm);
fsync(fd); /* endi haqiqatan diskda */
Yangi fayl yaratgan bo'lsangiz, katalogni ham sinxronlash kerak:
int kd = open("katalog", O_RDONLY | O_DIRECTORY);
fsync(kd);
close(kd);
Aks holda fayl mazmuni saqlanadi, lekin uning nomi yo'qoladi.
Fayl tizimlarini taqqoslash #
| Fayl tizimi | Yil | Kuchli tomoni | Qayerda ishlatiladi |
|---|---|---|---|
| FAT32 | 1996 | Hamma joyda o'qiladi | USB fleshka |
| NTFS | 1993 | Jurnal, huquqlar, siqish | Windows |
| ext4 | 2008 | Barqaror, tez, ekstentlar | Linux odatiy |
| XFS | 1994 | Katta fayllar, parallel I/O | Serverlar |
| Btrfs | 2009 | Snapshot, nusxa-yozishda | OpenSUSE, NAS |
| ZFS | 2005 | Butunlik tekshiruvi, RAID | Ma'lumot omborlari |
| APFS | 2017 | SSD ga moslashgan, shifrlash | macOS, iOS |
df -Th
Filesystem Type Size Used Avail Use% Mounted on
/dev/sda1 ext4 100G 42G 53G 45% /
/dev/sda2 vfat 512M 6.1M 506M 2% /boot/efi
tmpfs tmpfs 7.8G 84M 7.7G 2% /dev/shm
inode tugashi #
#include <stdio.h>
int main(void) {
/* 100 GB disk, 4 KB bloklar */
long disk_gb = 100;
long blok = 4096;
long bloklar = disk_gb * 1024 * 1024 * 1024 / blok;
/* ext4 odatda har 16 KB ga bitta inode ajratadi */
long inodelar = disk_gb * 1024 * 1024 * 1024 / (16 * 1024);
printf("Disk hajmi : %ld GB\n", disk_gb);
printf("Bloklar soni : %ld\n", bloklar);
printf("inode lar : %ld\n\n", inodelar);
/* Agar hamma fayl 1 KB bo'lsa nima bo'ladi? */
long mayda_fayllar = inodelar;
long ishlatilgan_gb = mayda_fayllar * blok / (1024 * 1024 * 1024);
printf("Agar barcha fayl 1 KB bo'lsa:\n");
printf(" Sig'adigan fayl soni : %ld ta\n", mayda_fayllar);
printf(" Egallangan disk : %ld GB\n", ishlatilgan_gb);
printf(" Disk to'ladimi? : %s\n",
ishlatilgan_gb >= disk_gb ? "ha" : "yo'q - inode tugadi!");
return 0;
}
Disk hajmi : 100 GB
Bloklar soni : 26214400
inode lar : 6553600
Agar barcha fayl 1 KB bo'lsa:
Sig'adigan fayl soni : 6553600 ta
Egallangan disk : 25 GB
Disk to'ladimi? : yo'q - inode tugadi!
df bo'sh joy ko'rsatadiBu klassik holat - inode lar tugagan:
df -i
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/sda1 6553600 6553600 0 100% /
IUse% 100% - yangi fayl yaratib bo'lmaydi, garchi df -h 75 GB
bo'sh ko'rsatsa ham.
Sabab odatda:
- Kesh katalogida millionlab mayda fayl;
- Sessiya fayllari tozalanmagan;
- Mail queue to'lib ketgan.
Aybdorni topish:
sudo du --inodes -x -d 1 / | sort -rn | head
inode lar soni fayl tizimi yaratilganda belgilanadi va keyin o'zgartirib bo'lmaydi. Mayda fayllar ko'p bo'ladigan disk uchun oldindan sozlang:
mkfs.ext4 -i 8192 /dev/sdb1 # har 8 KB ga bitta inode
XFS va Btrfs da inode lar dinamik ajratiladi - bu muammo yo'q.
Fayl tizimini tekshirish #
sudo umount /dev/sdb1
sudo fsck.ext4 -f /dev/sdb1
e2fsck 1.46.5 (30-Dec-2021)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/sdb1: 11/65536 files (0.0% non-contiguous), 8896/262144 blocks
fsck ni ulangan diskda ishlatmangUlangan (mounted) fayl tizimini fsck bilan tuzatish uni
butunlay buzishi mumkin - yadro va fsck bir vaqtda bir xil
tuzilmalarni o'zgartiradi.
To'g'ri tartib:
umountbilan uzing;- Ildiz bo'lsa - jonli USB dan yuklaning;
- Muhim ma'lumot bo'lsa - avval
ddbilan to'liq nusxa oling.
lost+found katalogi - fsck topgan, lekin nomi yo'qolgan
fayllar shu yerga qo'yiladi (inode raqami nom sifatida).
statbilan faylning inode raqami va bloklarini ko'ring.- Qattiq havola yaratib,
ls -lida inode bir xilligini tasdiqlang. - Bilvosita bloklar bilan maksimal fayl hajmini hisoblang.
- Ekstent va bilvosita usulning meta-ma'lumot hajmini solishtiring.
filefrag -vbilan katta faylning ekstentlarini ko'ring.dumpe2fs -hbilan superblok ma'lumotini o'qing.mountchiqishida jurnal rejimini aniqlang.df -hvadf -ifarqini tushuntiring.- inode tugashi ssenariysini hisoblab chiqing.
du --inodesbilan eng ko'p fayl saqlagan katalogni toping.
Xulosa #
- Disk sohalari: yuklash bloki, superblok, bitmaplar, inode jadvali, ma'lumot bloklari.
- Superblok fayl tizimi haqidagi asosiy ma'lumotni saqlaydi.
- inode faylning hamma xossasini saqlaydi - nomidan tashqari.
- Bilvosita bloklar kichik fayllarni tez, kattalarini imkonli qiladi.
- Ekstentlar meta-ma'lumotni minglab barobar kamaytiradi.
- Jurnal tok o'chganda tiklanishni soniyalarga qisqartiradi.
orderedrejim odatiy: meta ma'lumotdan keyin yoziladi.writeqaytgani diskda degani emas - kafolat uchunfsync.- Yangi fayl uchun katalogni ham
fsyncqiling. - inode lar tugashi disk to'lishidan mustaqil muammo.
fsckni faqat uzilgan fayl tizimida ishlating.
Keyingi bo'limda kiritish-chiqarish va qurilmalarni 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.