Fayllar

§2 Fayllar

2.1 Fayl və qovluq əmrləri

2.2 Köçürmə və silmə

2.3 Open sistem çağırışı

2.4 Close sistem çağırışı

2.5 Yeni faylın yaradılması

2.6 Fayldan oxuma

2.7 Fayla yazma

2.8 Qovluqlar

2.9 Bölmənin strukturu

Bu başlıqda Unix-də fayl və qovluqlarla işləmək üçün istifadə olunan əmrlər və proqramlaşdırma qaydaları, habelə, Unixdə qovluqlar ierarxiyasının strukturu ilə tanış olacağıq.


Kök qovluq

Unix sisteminin ən mühüm prinsipi “Hər şey fayldır” prinsipidir. Sistemdə hər şeyə, hard diskdə yerləşən adi fayllara, kompüterin müxtəlif qurğularına, şəbəkə əlaqələrinə, proqramlararası əlaqə vasitələrinə fayl kimi baxılır.

Bu isə eyni funksiyalara müraciət etməklə, sistemin bütün bu müxtəlif komponentləri üzərində giriş/çıxış əməliyyatlarını (informasiyanın qəbulu və ötürülməsi) aparmağa imkan verir.

Biz adi məlumat fayllarını nəzərdən keçirəcəyik.

Adi fayllar bizim gündəlik istifadə etdiyimiz müxtəlif mətn, şəkil, musiqi, video və s. məlumat fayllarıdır. Fayllar daimi yaddaşda (hard disk və ya disk adlandıracağıq, CD/DWD, USB) yerləşir. Fayllar necə gəldi yox, mütləq hansısa bir qovluğun içində yerləşir. Hər bir qovluq da öz növbəsində hansısa bir digər qovluğun içərisində. Beləliklə, biz daimi yaddaşda yerləşən fayllar və qovluqlar küllüsü almış oluruq və həmçinin qeyd etdik ki, hər bir qovluq və ya fayl mütləq hansısa bir qovluğun içərisində olmalıdır. Nəticədə biz fayl və qovluqlardan ibarət ierarxik strukturlu bir küllü alırıq. Bu ierarxiyanın ən yüksək yerində, Unix-də kök qovluq adlandırılan qovluq dayanır. Bu qovluq bütün digər qovluq və fayllar üçün başlanğıc qovluqdur.

Unix-də kök qovluq "/" kimi işarə olunur.


2.1 Fayl və qovluq əmrləri

Bu bölmədə biz Unix-də fayl və qovluqlarla işləyən zaman əsas istifadə olunan əmrləri öyrənəcəyik.

Qeyd elədik ki, Unix-də bütün fayl və qovluqların başlanğıc qovluğu kök qovluqdur.

Unix sistemlərində adətən kök qovluq özündə bin, var, tmp, home və s. kimi alt qovluqları saxlayır. Unix-də hər hansı qovluqda yerləşən fayl və qovluqların siyahısına baxmaq üçün əmrlər pəncərəsindən (terminal, console) ls baxmaq_istədiyiniz_qovluq əmrini daxil etmək lazımdır. Misal üçün, əgər kök qovluğunda yerləşən fayl və qovluqların siyahısına baxmaq istəsək, terminaldan ls / əmrini daxil etməliyik. Məndə nəticə aşağıdakı kimidir:


[ferid@fedora ~]$ 
[ferid@fedora ~]$ ls /
bin cgroup etc lib lost+found mnt proc run selinux sys usr
boot dev home lib64 media opt root sbin srv tmp var
[ferid@fedora ~]$ 
[ferid@fedora ~]$

Qeyd edək ki, heç bir arqumentsiz ls əmrini daxil etsək, onda ls bizə hal hazırki qovluqda olan fayl və qovluqlar barəsində məlumat çap edər.


[ferid@fedora ~]$ 
[ferid@fedora ~]$ ls
docr shirvan
Documents son
Downloads temp
drupal temp1
emacs-23.3-7.fc15.x86_64.rpm Templates
emacs-common-23.3-7.fc15.x86_64.rpm test
emacs-filesystem-23.3-7.fc15.x86_64.rpm test1
[ferid@fedora ~]$ 
[ferid@fedora ~]$ 

Hal-hazırki qovluğu öyrənmək üçün pwd əmrini daxil etməliyik, print working directory - işçi qovluğu çap et.


[ferid@fedora ~]$ 
[ferid@fedora ~]$ pwd
/home/ferid
[ferid@fedora ~]$ 
[ferid@fedora ~]$

Hazırda olduğumuz qovluqdan hansısa digər qovluğa keçmək istəsək, cd əmrindən istifadə edirik, change directory - işçi qovluğu dəyiş. Bu zaman əmri cd yeni_qovluq kimi daxil etməliyik, nəticədə biz yeni_qovluq qovluğuna daxil olarıq. Bunu yoxlamaq üçün isə, bayaq qeyd etdiyimiz pwd əmrindən istifadə edə bilərik. Misal üçün, əgər mən Documents qovluğuna keçmək istəsəm, cd Documents əmrini daxil etməliyəm, daha sonra isə, pwd əmri ilə hal hazırda olduğum qovluğun adını öyrənə bilərəm. Aşağıdakı kimi:


[ferid@fedora ~]$ 
[ferid@fedora ~]$ cd Documents
[ferid@fedora Documents]$ 
[ferid@fedora Documents]$ pwd
/home/ferid/Documents
[ferid@fedora Documents]$ 
[ferid@fedora Documents]$

2.2 Köçürmə və silmə

Gündəlik iş zamanı biz müxtəlif fayl və qovluqları bir ünvandan digərinə birdəfəlik köçürürük, nüsxəsini yaratmaqla köçürürük və ya yaddaşdan silirik. Gəlin, Unix-də terminaldan bu əməliyyatların icrası ilə tanış olaq. Hər hansı faylı və ya qovluğu bir yerdən başqa yerə köçürmək üçün cp əmrindən istifadə olunur. cp əmrinin istifadə qaydası cp fayl1 fayl2kimidir, nəticədəfayl1-in fayl2 adlı oxşarını yaratmış oluruq. Misal üçün, tutaq ki, işçi qovluqda test adlı hər hansı fayl var. Əgər biz bu fayldan test1 adlı nüsxə yaratmaq istəsək, ondacp test test1 əmrini daxil etməliyik. Aşağıdakı kimi:


[ferid@fedora unix]$ 
[ferid@fedora unix]$ ls
test
[ferid@fedora unix]$ 
[ferid@fedora unix]$ cp test test1
[ferid@fedora unix]$ 
[ferid@fedora unix]$ ls
test test1
[ferid@fedora unix]$ 
[ferid@fedora unix]$ 

Fayl və ya qovluğu silmək üçün isə rm əmrini daxil etməliyik. rm əmrinin istifadə qaydası rm faylkimidir. Misal üçün, əgər mən test faylını silmək istəsəm, rm test əmrini daxil etməliyəm. Aşağıdakı kimi:


[ferid@fedora unix]$
[ferid@fedora unix]$ ls 
test test1 
[ferid@fedora unix]$ 
[ferid@fedora unix]$ rm test
[ferid@fedora unix]$ 
[ferid@fedora unix]$ ls
test1
[ferid@fedora unix]$ 
[ferid@fedora unix]$ 

Hər hansı yeni qovluq yaratmaq üçün isə, mkdir əmrindən istifadə edirik, mkdir yeni_qovluq. Misal üçün, əgər qov1 adlı yeni qovluq yaratmaq istəsək, aşağıdakı əmri daxil etməliyik, mkdir qov1:


[ferid@fedora unix]$ 
[ferid@fedora unix]$ ls
test1
[ferid@fedora unix]$ 
[ferid@fedora unix]$ mkdir qov1
[ferid@fedora unix]$ 
[ferid@fedora unix]$ ls
qov1 test1
[ferid@fedora unix]$ 
[ferid@fedora unix]$

Yuxarıda daxil olunan mövzularda biz Unix-də fayl və qovluqlarla işləmək üçün istifadə olunan əmrlərlə tanış olduq. İndi isə, fayl və qovluqlarla işləmək üçün Unix-də istifadə olunan proqramlaşdırma qaydaları ilə tanış olaq.


2.3 Open sistem çağırışı

Yaddaşda mövcud olan hər hansı fayl üzərində, onda olan məlumatları oxumaq, silmək, dəyişmək və s. işlər görmək üçün biz faylla bizim proqram arasında əlaqələndirici vasitə yaratmalıyıq. Unix sistemlərində bu vasitə rolunu sistemin bizə qaytardığı tam tipli ədəd oynayır. Bunun üçün fcntl.h faylında təyin olunmuş standart open sistem çağırışından istifadə edirik. Fayl ilə əlaqə yaratdıqdan sonra readwrite sistem çağırışlarının köməyi ilə faylda olan məlumatları oxuya, yenisini fayla əlavə edə, mövcud məlumatları dəyişə bilərik.

Konkret proqram nümunəsinə keçməzdən əvvəl, bu çağırışların hər biri ilə tanış olaq.


Open sistem funksiyası

open funksiyasından biz yeni fayl yaradarkən və ya mövcud fayllara müraciət edərkən faylla əlaqələndirici almaq üçün istifadə edirik. Əgər funksiya uğurla başa çatarsa, bizə fayl əlaqələndiricisi adlandırılan tam ədəd qaytaracaq, əks halda isə, hər hansı səhvin baş verdiyini bildirmək üçün -1 nəticəsini qaytaracaq.

open funksiyasından istifadə edə bilmək üçün biz fcntl.h başlıq faylını proqrama əlavə etməliyik. Funksiyanın elanı aşağıdakı kimidir:


int open (const char *faylın_adı, int bayraq[, mode_t rejim]);

faylın adı - əlaqə qurmaq və ya yaratmaq istədiyimiz faylın adını bildirir.

bayraq - faylı necə açmaq istədiyimizi bildirir. Bir neçə qiymət ala bilər, bundan əlavə “və ya ” operatoru “|“ (nümunəyə bax) vasitəsilə bu qiymətlərin müxtəlif kombinasiyasınıdan da istifadə etmək olar. Bu qiymətlər aşağıdakılardır:

O_RDONLY - Faylı yalnız oxumaq üçün aç.

O_WRONLY - Faylı yalnız yazmaq üçün aç.

O_RDWR - Faylı həm oxumaq, həm də yazmaq üçün aç.

O_CREAT - Bu bayraq “Əgər mövcud deyilsə yarat!“ şərtini təmin etmək üçündür. Yəni bu bayrağı verməsək və mövcud olmayan faylı yazmaq üçün açmaq istəsək, sistem bizə səhv qaytarar. Bu bayrağı verməklə isə sistemə deyirik ki, əgər açmaq istədiyimiz fayl mövcud deyilsə, onda onu yarat. Yeni fayllar bu qayda ilə yaradılır.

O_EXCL - Əgər faylı O_CREAT bayrağı ilə açarkən fayl artıq mövcud olsa və onda hansısa məlumat olarsa, onda biz bu məlumatı itiririk. Bunun qarşısın almaq üçün, O_EXCL bayrağından istifadə edirik. Bu zaman mövcud faylı O_CREAT ilə açmaq istəsək, sistem icazə verməyəcək.

O_TRUNC - Bu bayrağın seçilməsi yazmaq üçün açılan faylda olan bütün əvvəlki məlumatları silir.

O_APPEND - Əgər bu bayraq seçilərsə, onda fayl yazmaq üçün açılarkən onda olan əvvəlki məlumatlar olduğu kimi qalır və yeni yazılan məlumatlar faylın sonuna əlavə olunur.

rejim – rejim dəyişənindən yalnız faylı ilk dəfə yaratdıqda istıfadə olunur. Çalışmalarda biz bu dəyişən üçün 0666 rəqəmindən istifadə edirik (qabaqdakı 0-a diqqət edin).


2.4 Close sistem çağırışı

Hər bir proqram, hər hansı faylla işləmək üçün əvvəlcə onu open funksiyası ilə açmalıdır ki, nüvə ona müvafiq fayl əlaqələndiricisi yaratsın. Bu zaman nüvə sahəsində həmin fayl, ona müraciət etmiş proqram və s. barədə məlumatlar yadda saxlanılır.

Proqram faylla işini bitirdikdən sonra nüvəyə bu barədə məlumat verməlidir ki, nüvə bu fayldan istifadə üçün məşğul etdiyi resursları azad etsin.

Bunun üçün close sistem çağırışından istifadə olunur. close funksiyasından istifadə etmək üçün unistd.h başlıq faylını proqrama əlavə etmək lazımdır.

Funksiyanın elanı belədir:


int close (int fd);

Burada fd bağlamaq istədiyimiz fayl əlaqələndiricisidir.

Biz qeyd elədik ki, open funksiyası ilə həm yeni fayl yarada, həm də mövcud fayla müraciət edə bilərik. Gəlin, openclose sistem çağrılarının xassələrini öyrənmək və onlarla daha yaxından tanış olmaq üçün proqram nümunələri tərtib edək.

Əvvəlcə yaddaşda mövcud olan hər hansı fayla müraciət edək və nüvənin bizə qaytardığı əlaqələndiricini çap edək (tam ədəd - int tipli). Proqram aşağıdakı kimi olacaq:


/* prg_2_1.c */

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

int main(int argc, char *argv[]){

int fd;

fd = open (argv[1], O_RDONLY);

if (fd < 0) printf("%s faylı açılmır \n",argv[1]);

else printf(" %s faylının əlaqələndiricisi %d \n",argv[1],fd);

close(fd); 

return 0;
}

Proqramı kompilyasiya və icra edək:


[ferid@fedora prog]$ 
[ferid@fedora prog]$ gcc prg_2_1.c -o prg_2_1
[ferid@fedora prog]$ 
[ferid@fedora prog]$ ./prg_2_1 test1
test1 faylının əlaqələndiricisi 3 
[ferid@fedora prog]$ 
[ferid@fedora prog]$ ./prg_2_1 test2
test2 faylı açılmır 
[ferid@fedora prog]$ 
[ferid@fedora prog]$ ls
prg_2_1 prg_2_1.c test test1
[ferid@fedora prog]$ 
[ferid@fedora prog]$
İzahı:

Əvvəlcə proqramın mətn faylının, daha sonra isə, kompilyasiya və icrasının izahını verək. printf, openclose funksiyalarından istifadə edə bilmək üçün, biz proqrama stdio.h, fcntl.hunistd.h fayllarını əlavə etmişik.

Növbəti sətir int main(int argc, char *argv[]){ sətridir. argc və argv proqram yüklənən zaman ona ötürülən parametrlər barədə məlumatı bildirir. argc parametrlərin sayını, argv isə qiymətlərini bildirir.

argv cərgəsinin ilk elementi (argv[0]) özündə proqramın adını saxlayır. Biz proqramı icra edərkən ./prg_2_1 test1 kimi əmr daxil etmişdik. Bu zaman argc-in qiyməti iki, argv[0]-in qiyməti ./prg_2_1 ,argv[1]-in qiyməti isə test1 olmuşdur.

Daha sonra int tipli fd dəyişəni elan edirik və bu dəyişənə open funksiyasının qaytardığı əlaqələndiricini mənimsədirik.


fd = open (argv[1], O_RDONLY);

Burada argv[1], açmaq istədiyimiz faylı, O_RDONLY isə, fayla müraciət məqsədini bildirir - "yalnız oxumaq üçün aç". Əgər qeyd etdiyimiz fayl - argv[1] mövcuddursa və bizim onu oxumaq səlahiyyətimiz varsa, onda open funksiyası hər hansı tam ədəd, əks halda, hər hansı səhvin baş verdiyini bildirmək üçün -1 nəticəsini qaytaracaq.

Sonda biz close funksiyası vasitəsilə müraciət etdiyimiz faylı bağlayırıq.

İndi isə, keçək proqramın kompilyasiyası və icrasına:

Proqramın mətn kodunu biz prg_2_1.c adlı fayla yazırıq. Daha sonra, bu mətn faylından gcc kompilyatoru vasitəsilə icraolunan prg_2_1 proqramını alırıq.gcc kompilyatoru hər hansı proqramı kompilyasiya etmək üçün terminaldan gcc prg.c -o prg əmrini daxil etməliyik.

gcc kompilyatorunun generasiya elədiyi proqram kodunu icra etmək üçün isə, ./proqramın_adı əmrini daxil etməliyik. Nəticədə həmin proqram icra olunacaq.

Biz terminaldan ./prg_2_1 test1 əmrini daxil etmişik. Burada prg_2_1 icraolunan proqramın adı (argv[0]), test1 isə ona ötürülən parametrdir (argv[1]). Proqram icra olunduqda test1 faylına oxumaq üçün müraciət edir və nüvə həmin fayla müraciət etmək üçün əlaqələndirici olaraq 3 qiymətini qaytarır. Sonra biz yenidən proqramı test2 faylına müraciət etmək üçün icra edirik. test2 faylı mövcud olmadığına görə, nüvə bizə səhvin baş verdiyini bildirmək üçün -1 qiymətini qaytarır.


2.5 Yeni faylın yaradılması

Biz open funksiyası ilə mövcud fayla müraciət etdik, indi isə, open funksiyası ilə yeni fayl yaradaq.

Qeyd elədik ki, yeni fayl yaratmaq üçün open funksiyasına bayraq olaraq O_CREAT qiymətini verməliyik.

Proqram aşağıdakı kimi olacaq:


/* prg_2_2.c */

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

int main(int argc, char *argv[]){

int fd;

fd = open (argv[1], O_CREAT, 0666);

if (fd < 0) printf("%s fayl yaradıla bilmir \n",argv[1]);
else printf(" fayl uğurla yaradıldı \n");

close(fd); 

return 0;
}

[ferid@fedora prog]$ 
[ferid@fedora prog]$ gcc prg_2_2.c -o prg_2_2
[ferid@fedora prog]$ 
[ferid@fedora prog]$ ./prg_2_2 test2
fayl uğurla yaradıldı
[ferid@fedora prog]$ 
[ferid@fedora prog]$ ls
prg_2_1 prg_2_1.c prg_2_2 prg_2_2.c test test1 test2
[ferid@fedora prog]$
[ferid@fedora prog]$ ls -l
total 168
-rwxrwxr-x. 1 ferid ferid 6874 Jan 16 17:44 prg_2_1
-rw-rw-r--. 1 ferid ferid 361 Jan 16 17:44 prg_2_1.c
-rwxrwxr-x. 1 ferid ferid 6964 Jan 16 18:18 prg_2_2
-rw-rw-r--. 1 ferid ferid 352 Jan 16 18:18 prg_2_2.c
-rw-rw-r--. 1 ferid ferid 69643 Jan 16 17:44 test
-rw-rw-r--. 1 ferid ferid 69643 Jan 16 17:44 test1
-rw-rw-r--. 1 ferid ferid 0 Jan 16 18:18 test2
[ferid@fedora prog]$ 

İzahı:

open funksiyası vasitəsilə yeni fayl yaratmaq üçün biz open (argv[1], O_CREAT, 0666); əmrini daxil edirik. 0666 parametrini yeni fayl yaradarkən daxil edirik, bu, fayla müraciət səlahiyyətlərini müəyyən edir.


2.6 Fayldan oxuma

Fayldan məlumatları oxumaq üçün read(int fe, char *yer, int say) funksiyasından istifadə olunur. read funksiyası 3 arqument qəbul edir: tam tipli fayl əlaqələndiricisi, fayldan oxunan məlumatları yerləşdirmək üçün yaddaşda yer və fayldan oxunmalı olan məlumatın ölçüsü, baytlarla.

Əgər funksiya uğurla yerinə yetirsə, onda tələb olunan ölçüdə məlumatı fayldan oxuyub, göstərilən yer-ə yazır və nəticə olaraq oxuya bildiyi baytların sayını qaytarır. Qeyd edək ki, əgər read funksiyası hansısa səbəbdən tələb olunan miqdardan az məlumat oxuyursa, bu səhv sayılmır. Əgər faylda oxumağa artıq məlumat yoxdursa (faylın sonu) və ya fayl boşdursa (0bayt), onda readfunksiyası nəticə olaraq 0 qiymətini qaytarır. Oxunmada hər hansı səhv baş verdikdə isə (misal üçün, fe düzgün deyil, bu faylı oxumağa icazə yoxdur və s.), read funksiyası -1 qiymətini qaytarır. read funksiyasıfcntl.h faylında təyin olunub və elanı aşağıdakı kimidir:


int read(int, char *, int);

Gəlin, int funksiyasından istifadə edib, hər hansı faylın ilk 10 baytını oxuyub ekranda çap edən proqrama baxaq.


/* prg_2_3.c */

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>

int main(int argc, char *argv[]){

int fe, k;

char yer[20]={'\0'};

fe = open (argv[1], O_RDONLY);

if (fe < 0){
printf("%s fayl açıla bilmir \n",argv[1]);
exit(1); 
}

k = read(fe, yer, 10); 

if(k<0) {
printf("%s fayl oxunmur \n",argv[1]);
exit(1); 
+}

printf("%s faylından oxunan məlumatlar \n%s\n",argv[1],yer);

close(fe); 

return 0;
}

Proqramı icra etməzdən əvvəl terminaldan echo "Salam bu yeni fayldır" > fayl1əmrini daxil edək. Nəticədə işçi qovluqda fayl1 adlı yeni fayl yaranacaq və onda "Salam bu yeni fayldır" mətni yerləşdiriləcək. Daha sonra, proqramımızı icra edirik və oxumaq üçün fayl1 faylını ona parametr kimi veririk. Nəticədə fayl1 faylının ilk 10 baytı - "Salam bu y"ifadəsi ekranda çap olunacaq. Siz digər faylları da test edə bilərsiniz, hətta obyekt faylları da, ekranda qeyri ASCII simvollar çap olunacaq.


[ferid@fedora prog]$ 
[ferid@fedora prog]$ echo "Salam bu yeni fayldır" > fayl1
[ferid@fedora prog]$ 
[ferid@fedora prog]$ gcc prg_2_3.c -o prg_2_3
[ferid@fedora prog]$ 
[ferid@fedora prog]$ ./prg_2_3 fayl1
Salam bu y
[ferid@fedora prog]$ 
[ferid@fedora prog]$

İzahı:

Əvvəlcə, biz oxumaq istədiyimiz faylın əlaqələndiricisini almaq üçün open funksiyasına müraciət edirik və O_RDONLY arqumenti ilə nüvəyə faylı yalnız oxumaq üçün açdığımızı bildiririk. Daha sonra, open funksiyasının nəticəsini yoxlayırıq, əgər nəticə mənfidirsə, deməli, fayla müraciət xətası baş verib,exit funksiyası vasitəsilə proqramı sona çatdırırıq.

Əks halda, open funksiyasının bizə qaytardığı fayl əlaqələndiricisini read funksiyasına parametr kimi ötürürük. read funksiyası fe-dən 10 bayt məlumat oxuyub yer-ə yazır. Daha sonra, bu məlumatı çap edirik.


2.7 Fayla yazma

Fayla məlumat yazmaq üçün write(int fe, char *yer, int say) funksiyasından istifadə olunur. write funksiyası 3 arqument qəbul edir: tam tipli fayl əlaqələndiricisi, fayla yazılacaq məlumatlar saxladığımız yer buferi və fayla yazılmalı olan məlumatın ölçüsü, baytlarla.

Əgər funksiya uğurla yerinə yetirsə, onda tələb olunan ölçüdə məlumatı fayla yazır və nəticə olaraq uğurla yazılmış baytların sayını qaytarır. Qeyd edək ki, əgər write funksiyası hansısa səbəbdən tələb olunan miqdardan az məlumat yazıbsa, bu səhv sayılmır. Yazmada hər hansı səhv baş verdikdə, write funksiyası -1 qiymətini qaytarır. write funksiyası fcntl.h faylında təyin olunub və elanı aşağıdakı kimidir:


int write(int, char *, int);

write funksiyasına aid proqram nümunəsi tərtib edək. Elə proqram quraq ki, hər hansı yeni fayl yaratsın və bu fayla "Unix-də ilk fayl" məlumatını yerləşdirsin. Proqram aşağıdakı kimi olacaq:


/* prg_2_4.c */ 

#include <stdio.h> 
#include <unistd.h> 
#include <fcntl.h> 
#include <stdlib.h> 
#include <string.h> 

int main(int argc, char *argv[]){ 
int fe, k; 
char yer[20]={'\0'}; 
strcpy(yer,"Unix-də ilk fayl"); 

fe = open (argv[1], O_WRONLY); 
if (fe < 0){ 
printf("%s fayl açılmır \n",argv[1]); 
exit(1); 
} 

k = write(fe, yer, 15); 
if(k<0) { 
printf("%s fayla yazılmır \n",argv[1]); 
exit(1); 
} 

Proqramı kompilyasiya və icra edək:


[ferid@fedora prog]$ 
[ferid@fedora prog]$ gcc prg_2_4.c -o prg_2_4
[ferid@fedora prog]$ 
[ferid@fedora prog]$ echo "11111111111111111111111" > test4
[ferid@fedora prog]$ 
[ferid@fedora prog]$ cat test4
11111111111111111111111
[ferid@fedora prog]$ 
[ferid@fedora prog]$ ./prg_2_4 test4
[ferid@fedora prog]$ 
[ferid@fedora prog]$ cat test4
Unix-də ilk fayl11111111
[ferid@fedora prog]$

Əvvəlcə echo "11111111111111111111111" > test4 əmri ilə işçi qovluqda test4 faylı yaradırıq və ona "11111111111111111111111" məlumatını yerləşdiririk. Daha sonra, cat test4 əmri ilə yeni yaratdığımız faylda olan məlumatı çap edirik. Daha sonra isə, proqramımızı icra edirik. Proqramımız yerinə yetirilir və test4 faylının ilk 15 baytına "Unix-də ilk fayl" məlumatını yerləşdirir. Sonda isə, biz test4 faylında olan məlumatı yenidən cat əmri ilə oxuyuruq və proqramımızın onda etdiyi dəyişikliklərin şahidi oluruq.


2.8 Qovluqlar

Fayllar yaddaşda necə saxlanılır?

Faylda hər hansı ikili məlumat saxlanılır. Qovluqlarda isə fayl və alt qovluqlar. Yəni qovluqlar faylların və alt qovluqların saxlanılması üçün konteyner rolunu oynayır. Bu mövzuda biz qovluğun nə olduğunu başa düşməyə çalışacaq, Unix-də qovluqlarla işləmək üçün bəzi standart C funksiyaları ilə tanış olacağıq.

Hər şeydən əvvəl sərt diskin (daimi yaddaş) strukturu ilə tanış olaq, harada ki, biz bütün fayl və qovluqlarımızı yerləşdiririk.

Sərt diskin ümumi yaddaş sahəsi SEKTOR adlandırılan kiçik hissələrə bölünür. Hər bir sektor eyni ölçüyə malik olur və adətən 1 sektorun ölçüsü 512 bayt olur. Misal üçün, 250 GB-lıq sərt diskdə 250*1024*1024*1024/512 sayda sektor mövcuddur.



Yaddaşda yerləşdirilən bütün məlumatlar bu sektorlara yazılır. Sektorlar ardıcıl yerləşdir və 0-dan başlayaraq sıra ilə nömrələnir.

Misal üçün, 250 GB-lıq sərt diskin ilk sektorunun nömrəsi 0, sonuncu sektorunun nömrəsi isə, 250*1024*1024*1024/512 - 1 olar.

Bütün fayllar və qovluqlar bu sektorlarda yerləşir. Necə? Bu suala cavab tapmağa çalışacağıq.

Bu sualı tam dəqiqliyi ilə izah eləmək üçün ayrı kitab lazımdır. Ona görə, biz müəyyən qədər ümumiləşdirmə aparmağa məcburuq.

Biz sərt diskin ümumi sahəsini bir neçə hissəyə ayıra bilərik və hər bir hissəyə ayrı bir vahid kimi baxa bilərik. Bu yaddaş vahidləri BÖLMƏ (PARTITION) adlanır. Sərt diskin bölmələri barədə məlumat ilk sektora yazılır. Misal üçün? tutaq ki, sərt diskimiz 10 000 sektordan ibarətdir və biz onu 30007000-lik iki bölməyə ayırmışıq. Birinci bölmə 1-2999 sektorlarını, ikinci bölmə 3000-9999 sektorlarını əhatə edir. Bu məlumatlar, yəni bölmələrin sayı, hər bir bölmənin başlanğıc və son sektorlarının nömrəsi ilk sektora yerləşdirilir və ilk sektoru oxumaqla biz sərt diskin xəritəsini öyrənmiş oluruq.



İndi isə, keçək bölmələrə.

Tutaq ki, baxdığımız bölmə özündə sərt diskin k-cı sektoru ilə n-ci (n>k) sektorları arasındakı hissəni (n-k sayda sektor) saxlayır.

İzah edəcəyimiz mövzuda bölmənin başlanğıc və son sektorlarının nömrələrinin fərqi olmadığından, sadəlik üçün onları 1n qəbul edəcəyik. Yəni sərt diskin 1-ci sektoru ilə n-ci sektoru arasında qalan hissəni nəzərdən keçiririk (n-1 sektor).



Yerdə qalan hər şeyi yaddan çıxara bilərik, sərt diskin digər sektorları, ilk sektor və s. Buradan etibarən diqqətimizi məhz bu hissədə 1-n sektorları üzərində cəmləyəcəyik və bu hissəyə bir vahid bölmə kimi baxacağıq.

Hesab edəcəyik ki, fayl və qovluqlar, qovluqlar ierarxiyası və kök qovluq - hamısı baxdığımız bölmədə yerləşir.

Buraya qədər müxtəlif əməliyyatlar sistemində təxminən eyni olsa da, buradan sonrakı izah müxtəlif ola bilər. Bizim verdiyimiz izah əsasən Unix sistemlərinə xarakterikdir. Gəlin, Unixdə fayl və qovluqların verilmiş bölmədə necə yerləşməsi ilə tanış olaq.


2.9 Bölmənin strukturu

Bölmə səviyyəsində artıq nüvənin tələblərinə uyğun olaraq, yaddaş vahidi kimi sektor yox, bir neçə sektorun misli ölçüsündə olan BLOK terminindən istifadə edirlir. Sadə dillə desək, 1 blok yanaşı yerləşmiş bir neçə sektordan ibarət yaddaş vahididir. Blokun ölçüsü isə, sistemin tələblərinə uyğun olaraq dəyişə bilər. Misal üçün, əgər bölmənin ümumi sektorlarının sayı n-dirsə və sistem blokun ölçüsünü 2 sektor həcmində müəyyən edirsə, onda bölmə n/2 sayda blokdan ibarətdir.



Bloklar da sektorlar kimi 0-dan başlayaraq nömrələnir. Bloklar 3 qrupa bölünür: Superblok, İnod cədvəli, Məlumat blokları.



Superblok yalnız bir blokdan ibarətdir və adətən bölmənin ilk bloku Superblok olur. İnod cədvəliMəlumat bloklarının ölçüləri isə sistem tərəfindən tənzimlənir.

İndi isə, gəlin, bütün bu 3 qrup, onlarda saxlanılan məlumat ilə ayrı-ayrılıqda tanış olaq.


SuperBlok.

Qeyd etdiyimiz kimi, Superblok cəmi 1 blokdan ibarətdir və özündə bölməyə yazılmış fayllar sistemi barədə əhəmiyyətli məlumatları saxlayır. Bu məlumatlara əsasən, İnod Cədvəli və Məlumat Bloklarının başlanğıc və son blok nömrələri, bölməyə yazılmış fayllar sisteminin tipi və ən əsası, kök qovluğun inod nömrəsi (bu barədə daha ətraflı irəlidə) aiddir.


İnode Cədvəli.

Unix-də hər bir faylın xassələri və məlumatları bir-birindən ayrı yerlərdə saxlanılır. Uyğun olaraq, faylın xassələri İnod cədvəlində, faylın məlumatları isə, Məlumat Bloklarında saxlanılır. Faylın xassələri dedikdə, faylın yaradılma tarixi, müraciət bitləri, sahibi, ölçüsü və ən əsası, məlumat bloklarının nömrələri nəzərdə tutulur. Bu məlumatlar inod strukturunun elementləridir. İnod strukturu sistemdə hər bir fayl üçün nüvə tərəfindən yaradılır və İnod Cədvəlinə yerləşdirilir. İnod Cədvəli inod strukturu elementləri cədvəlidir. İnodlar İnod Cədvəlində ardıcıl yerləşdirilir və 0-dan başlayaraq nömrələnir.

Beləliklə, hər hansı faylın xassələrini öyrənmək üçün biz həmin faylın İnod cədvəlindəki müvafiq inodunun nömrəsini - indeksini bilməliyik. ls -i əmri vasitəsilə biz bu məlumatları öyrənə bilərik.


[ferid@fedora prog]$ 
[ferid@fedora prog]$ ls -i
4858043 fayl1 4856252 prg_2_1.c 4856260 prg_2_2.c 4858045 prg_2_3.c 4857646 prg_2_4.c 4856248 test1 4854982 test4
4856027 prg_2_1 4856257 prg_2_2 4858041 prg_2_3 4854849 prg_2_4 4856253 test 4856258 test2
[ferid@fedora prog]$ 
[ferid@fedora prog]$

Burada faylın adının qarşısındakı ədəd onun inod nömrəsidir.

Gəlin, elə proqram tərtib edək ki, verilmiş faylın bəzi xassələrini (ölçüsü, son dəyişiklik tarixi) çap etsin.

Proqram aşağıdakı kimi olar:


/* prg_2_5.c */

#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h> 

int main(int argc, char **argv)
{
if(argc != 2) 
return 1;
struct stat fstat;
if(stat(argv[1],&fstat) < 0) 
return 1;
printf("%s faylının xassələri \n",argv[1]);
printf("faylın ölçüsü: \t\t%d bayt (%d Kb)\n",fstat.st_size, (fstat.st_size / 1024));
printf("Faylda son dəyişiklik edilib: %s",ctime(&fstat.st_mtime));

return 0;
}

Nəticə:


[ferid@fedora prog]$ 
[ferid@fedora prog]$ ls -l test
-rw-rw-r--. 1 ferid ferid 69643 Jan 16 17:44 test
[ferid@fedora prog]$ 
[ferid@fedora prog]$ ./prg_2_5 test
test faylının xassələri 
faylın ölçüsü: 69643 bayt (68 Kb)
Faylda son dəyişiklik edilib: Mon Jan 16 17:44:53 2012
[ferid@fedora prog]$ 

Məlumat blokları

Bölmənin 3-cü hissəsi məlumat bloklarıdır. Bu hissəyə aid bloklarda fayl məlumatları yerləşir.

Tutaq ki, nüvə hər hansı faylın məlumatlarını oxumaq istəyir. Bu zaman ilk olaraq, nüvə həmin faylın inod nömrəsini tapmalıdır.

Bunun qaydası ilə irəlidə tanış olacağıq. İnod nömrəsini tapdıqdan sonra, nüvə inod cədvəlin həmin nömrəli inod strukturunu oxuyur və faylın xassələri ilə tanış olur. Faylın məlumat bloklarının nömrələri fayla məxsus inod strukturunda bloklar adlı long tipindən olan cərgədə yerləşir. Bloklar cərgəsindən nüvə verilmiş faylın məlumatlarının yerləşdiyi blokların nömrələrini əldə edir, daha sonra, həmin nömrəli blokları bölmədən oxuyur.


Qovluqlar

Biz indiyə qədər deyirdik ki, faylın xassələri inod cədvəlində, məlumatları isə, Məlumat bloklarında yerləşir. Bütün bu izahları verəndə yalnız fayl terminindən istifadə edirdik, qovluq terminindən istifadə etmirdik. Bəs qovluqlar harada yerləşir?

Ümumiyyətlə, fayllara aid etdiyimiz xassələr qovluqlara da aiddirmi? Konkret olaraq qovluq nədir?

Qovluq özündə müxtəlif fayl adları ilə, onların müvafiq inod nömrələrini saxlayan xüsusi tipli fayldır. Bəli, bizim gündəlik istifadədə fayl konteyneri kimi qəbul etdiyimiz qovluq, əslində adi bir fayldır. Bütün digər fayllar kimi onun da inod cədvəlində məxsusi inod elementi və bu elementdə yerləşən ölçüsü, dəyişiklik tarixi, sahibi, müraciət bitləri, məlumat bloklarının nömrələri olur. Qovluğun məlumat bloklarında qeyd etdiyimiz kimi, fayl adları və onların inod nömrələri yerləşir. Sadə dillə desək, bayaq bir problemi qeyd etdik ki, fayl verildikdə nüvə onun inod nömrəsini necə təyin edir. Bu izahdan görürük ki, fayl verildikdə nüvə onun yerləşdiyi qovluğun məlumat bloklarını oxuyur, həmin məlumatlarda verilmiş faylın adına uyğun inod nömrəsini tapır.

İndi bir proqram tərtib edək, hansı ki, verilmiş qovluqda yerləşən fayl adlarını və onların müvafiq inod nömrələrini çap etsin.


Faylın adı verildikdə onun yerləşdiyi qovluğun müəyyən edilməsi.

Faylın adı iki üsulla verilə bilər: ya sadəcə faylın adı verilir, ya da kök qovluqdan başlayaraq, fayla qədər olan tam yol. Misal üçün, aşağıdakı kimi:


[ferid@fedora prog]$ 
[ferid@fedora prog]$ ls -l test
-rw-rw-r--. 1 ferid ferid 69643 Jan 16 17:44 test
[ferid@fedora prog]$ 
[ferid@fedora prog]$ pwd
/home/ferid/prg/mytuxnet/unix/prog
[ferid@fedora prog]$ 
[ferid@fedora prog]$ ls -l /home/ferid/prg/mytuxnet/unix/prog/test
-rw-rw-r--. 1 ferid ferid 69643 Jan 16 17:44 /home/ferid/prg/mytuxnet/unix/prog/test
[ferid@fedora prog]$ 
[ferid@fedora prog]$

Əvvəlcə biz işçi qovluqda olan faylın xassələrini çap edirik, daha sonra, pwdəmri vasitəsilə işçi qovluğun tam yolunu çap edirik və ls əmrinə bu dəfə baxdığımız faylı tam yolu ilə birlikdə, adını daxil edirik. Hər ikisində eyni nəticə alınır.

Məsələ burasındadır ki, əgər faylın tam adı verilmirsə, onda nüvə onu hazırki işçi qovluqda axtaracaq.

Faylın adı tam yolu ilə verildiyi hala baxaq: /qovluq1/qovluq2/.../qovluqk/test

Tutaq ki, istifadəçi proqramı nüvədən /qovluq1/qovluq2/.../qovluqk/test faylının məlumatlarını oxumağı istəyir. Bunun üçün nüvə fayllar strukturu ierarxiyasının ən başlanğıcından - kök qovluqdan başlayaraq bir-bir yolda göstərilən ardıcıllıqla adları oxuyur və inod nömrələrini tapır. Baxdığımız misalda nüvə əvvəlcə kök qovluqdan qovluq1-in inod nömrəsin öyrənəcək, daha sonra, qovluq1-dən qovluq2-in və s. Ən sonda qovluqk-dan test faylının inod nömrəsini öyrənəcək.

İndi elə proqram tərtib edək ki, verilmiş qovluqda yerləşən fayl və qovluqların adlarını və müvafiq inod nömrələrini çap etsin.


/* prg_2_6.c */

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>


int main(int argc, char *argv[]){

DIR *qov;

qov = opendir(argv[1]);

struct dirent *dr;

while(( dr = readdir(qov))!=NULL)

printf("%d %s\n",dr->d_ino,dr->d_name);
closedir(qov); 
}

Nəticə:


[ferid@fedora prog]$ 
[ferid@fedora prog]$ ./prg_2_6 qov
4980769 test3
4980770 test1
4856245 ..
4980768 .
4980771 test2
4980772 test4
[ferid@fedora prog]$ 
[ferid@fedora prog]$

İndi isə, gəlin, ls əmri ilə qov-da olan faylların inod nömrələrini və adlarını çap edək:


[ferid@fedora prog]$ 
[ferid@fedora prog]$ ls -i qov
4980770 test1 4980771 test2 4980769 test3 4980772 test4
[ferid@fedora prog]$ 
[ferid@fedora prog]$ 

«« Giriş    Fayllar    Proseslər »»
Share


Muəllif: Əhməd Sadıxov