Linux — Strace Sistem Çağrısı Çıktılarının Anlamlandırılması

Bu yazımda bir programın strace ile çıktısını aldığımız sistem çağrılarının bulunduğu kayıtların derinlemesine incelemesini yapacağız.

SİSTEM ÇAĞRILARI (SYSTEM CALLS)
Sistem çağrıları bir yazılımın çalıştığı işletim sisteminin alt katmanında bulunan çekirdeğinden (kernel) talep ettiği hizmetlerdir. Bir programın işletim sistemiyle etkileşime girebilmesinin yolu sistem çağrılarıdır. Detaylı bilgi için tıklayınız.

STRACE
Bir programın sistem çağrılarını izleyebilmemizi sağlar. Bir program strace ile başlatılır ya da strace bir processe bağlanırsa ilgili programın yaptığı tüm sistem çağrılarını görebiliriz. Bu yöntem bize bir çok senaryoda hata tespiti yapmak ya da ilgili programın çalışma şekli hakkında bilgi sahibi olabilmemize yardımcı olacaktır. Örnek olarak kaynak kodları elimizde olmayan binary halde olan programı çalıştırırken geçirdiği tüm süreçleri görebilir ya da hata alınan bir programın hatayı tam olarak hangi aşamada, ne sebeple aldığını tespit edebiliriz.

STRACE ÇIKTILARINI ANLAMLANDIRMAK
Bu örneğimizde echo “Hello World” komutunu strace ile çalıştırıp, tüm çıktıyı sıfırdan anlamlandıracağız.

Aşağıdaki komutumuz strace çıktısını “-o” parametresini kullanarak strace_output dosyasına gönderiyor ve program çıktısı olan Hello World çıktısını stdout olarak bize veriyor.

⚡ root@marf ~ strace -o strace_output echo “Hello World”
Hello World

strace_output dosyasını okuduğumuzda korkutucu bir output bizi karşıladı. Bu gördüğümüz çıktı ekrana Hello World yazdıran programımızın arka planda yaptığı tüm sistem çağrılarının sürecini içeriyor.

⚡ root@marf  ~  cat -n strace_output
1  execve("/usr/bin/echo", ["echo", "Hello World"], 0x7fff43afb0c8 /* 24 vars */) = 0
2  brk(NULL)                               = 0x556665943000
3  access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
4  openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
5  fstat(3, {st_mode=S_IFREG|0644, st_size=34879, ...}) = 0
6  mmap(NULL, 34879, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fe05a99f000
7  close(3)                                = 0
8  openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
9  read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\360A\2\0\0\0\0\0"..., 832) = 832
10  pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
11  pread64(3, "\4\0\0\0\20\0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0", 32, 848) = 32
12  pread64(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0\237\333t\347\262\27\320l\223\27*\202C\370T\177"..., 68, 880) = 68
13  fstat(3, {st_mode=S_IFREG|0755, st_size=2029560, ...}) = 0
14  mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fe05a99d000
15  pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
16  pread64(3, "\4\0\0\0\20\0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0", 32, 848) = 32
17  pread64(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0\237\333t\347\262\27\320l\223\27*\202C\370T\177"..., 68, 880) = 68
18  mmap(NULL, 2037344, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fe05a7ab000
19  mmap(0x7fe05a7cd000, 1540096, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x22000) = 0x7fe05a7cd000
20  mmap(0x7fe05a945000, 319488, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x19a000) = 0x7fe05a945000
21  mmap(0x7fe05a993000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1e7000) = 0x7fe05a993000
22  mmap(0x7fe05a999000, 13920, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fe05a999000
23  close(3)                                = 0
24  arch_prctl(ARCH_SET_FS, 0x7fe05a99e580) = 0
25  mprotect(0x7fe05a993000, 16384, PROT_READ) = 0
26  mprotect(0x556664fb3000, 4096, PROT_READ) = 0
27  mprotect(0x7fe05a9d5000, 4096, PROT_READ) = 0
28  munmap(0x7fe05a99f000, 34879)           = 0
29  brk(NULL)                               = 0x556665943000
30  brk(0x556665964000)                     = 0x556665964000
31  openat(AT_FDCWD, "/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
32  fstat(3, {st_mode=S_IFREG|0644, st_size=3035952, ...}) = 0
33  mmap(NULL, 3035952, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fe05a4c5000
34  close(3)                                = 0
35  openat(AT_FDCWD, "/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 3
36  fstat(3, {st_mode=S_IFREG|0644, st_size=2996, ...}) = 0
37  read(3, "# Locale name alias data base.\n#"..., 4096) = 2996
38  read(3, "", 4096)                       = 0
39  close(3)                                = 0
40  openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_IDENTIFICATION", O_RDONLY|O_CLOEXEC) = 3
41  fstat(3, {st_mode=S_IFREG|0644, st_size=252, ...}) = 0
42  mmap(NULL, 252, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fe05a9d4000
43  close(3)                                = 0
44  openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache", O_RDONLY) = 3
45  fstat(3, {st_mode=S_IFREG|0644, st_size=27002, ...}) = 0
46  mmap(NULL, 27002, PROT_READ, MAP_SHARED, 3, 0) = 0x7fe05a9a1000
47  close(3)                                = 0
48  openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_MEASUREMENT", O_RDONLY|O_CLOEXEC) = 3
49  fstat(3, {st_mode=S_IFREG|0644, st_size=23, ...}) = 0
50  mmap(NULL, 23, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fe05a9a0000
51  close(3)                                = 0
52  openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_TELEPHONE", O_RDONLY|O_CLOEXEC) = 3
53  fstat(3, {st_mode=S_IFREG|0644, st_size=47, ...}) = 0
54  mmap(NULL, 47, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fe05a99f000
55  close(3)                                = 0
56  openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_ADDRESS", O_RDONLY|O_CLOEXEC) = 3
57  fstat(3, {st_mode=S_IFREG|0644, st_size=131, ...}) = 0
58  mmap(NULL, 131, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fe05a4c4000
59  close(3)                                = 0
60  openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_NAME", O_RDONLY|O_CLOEXEC) = 3
61  fstat(3, {st_mode=S_IFREG|0644, st_size=62, ...}) = 0
62  mmap(NULL, 62, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fe05a4c3000
63  close(3)                                = 0
64  openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_PAPER", O_RDONLY|O_CLOEXEC) = 3
65  fstat(3, {st_mode=S_IFREG|0644, st_size=34, ...}) = 0
66  mmap(NULL, 34, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fe05a4c2000
67  close(3)                                = 0
68  openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_MESSAGES", O_RDONLY|O_CLOEXEC) = 3
69  fstat(3, {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
70  close(3)                                = 0
71  openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_MESSAGES/SYS_LC_MESSAGES", O_RDONLY|O_CLOEXEC) = 3
72  fstat(3, {st_mode=S_IFREG|0644, st_size=48, ...}) = 0
73  mmap(NULL, 48, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fe05a4c1000
74  close(3)                                = 0
75  openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_MONETARY", O_RDONLY|O_CLOEXEC) = 3
76  fstat(3, {st_mode=S_IFREG|0644, st_size=270, ...}) = 0
77  mmap(NULL, 270, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fe05a4c0000
78  close(3)                                = 0
79  openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_COLLATE", O_RDONLY|O_CLOEXEC) = 3
80  fstat(3, {st_mode=S_IFREG|0644, st_size=1518110, ...}) = 0
81  mmap(NULL, 1518110, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fe05a34d000
82  close(3)                                = 0
83  openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_TIME", O_RDONLY|O_CLOEXEC) = 3
84  fstat(3, {st_mode=S_IFREG|0644, st_size=3360, ...}) = 0
85  mmap(NULL, 3360, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fe05a34c000
86  close(3)                                = 0
87  openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_NUMERIC", O_RDONLY|O_CLOEXEC) = 3
88  fstat(3, {st_mode=S_IFREG|0644, st_size=50, ...}) = 0
89  mmap(NULL, 50, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fe05a34b000
90  close(3)                                = 0
91  openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_CTYPE", O_RDONLY|O_CLOEXEC) = 3
92  fstat(3, {st_mode=S_IFREG|0644, st_size=201272, ...}) = 0
93  mmap(NULL, 201272, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fe05a319000
94  close(3)                                = 0
95  fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0), ...}) = 0
96  write(1, "Hello World\n", 12)           = 12
97  close(1)                                = 0
98  close(2)                                = 0
99  exit_group(0)                           = ?
100  +++ exited with 0 +++

Yukarıdaki çıktıyı parçalayarak yorumlamaya başlayalım.

Önemli not : Bir kere açıklamasını yaptığım sistem çağrısının tekrar açıklamasını yapmadan, sadece ilgili çağrıda yaptığı işlemi anlatmaya çalışacağım.

execve() sistem çağrısı hali hazırda olan process imajını verdiğimiz imaj ile yeniden düzenliyor ve path ile belirttiğimiz programı yeni bir child process ile çalıştırıyor. Köşeli parantez olarak verdiğimiz argüman vektörleri ise bir işaretçi dizisi. Buradaki ilk dize çalıştırılarak dosyanın ismini içermelidir ve son dize ise ‘NULL’ olmalıdır. Basitçe ilk (0.) dize olan echo programına, ikinci (1.) dizemiz olan ‘Hello World’ argümanını ilettik.

brk(NULL) ise heap memory’nin bitişini sorgulayan işlem. Çalıştırdığımız program ya da ilgili kütüphanesinin malloc() sistem çağrısını kullanması gerekmediğinde kullanılır.

1  execve("/usr/bin/echo", ["echo", "Hello World"], 0x7fff43afb0c8 /* 24 vars */) = 0
2  brk(NULL)                               = 0x556665943000

access() sistem çağrısı çağrılan işlemin path şeklinde verilen dosyaya erişip/erişemediğini kontrol eder.

Çalıştırılan tüm programlar Glibc talimatıyla /etc/ld.so.preload dosyasını açmaya çalışır. Eğer bu dosya ilgili path yok ise olumsuz bir cevap alır herhangi bir durumu tetiklemeden çağrı sonlanır.

3 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)

openat() path ile verilen dosya sisteminde barınan bir dosyaya erişmesini sağlar. Burada kullanılan AT_FDCWD değeri ise path ismi çalıştırılacak işlemin pathine göre yorumlanacaktır. /etc/ld.so.cache dosyası ise belirtilen dizinde bulunan kütüphanelerin sıralı bir listesini verir.

fstat() ise dosyanın boyutunu, oluşturulma/değiştirilme tarihini, inode numarasını, hard link sayısını, dosya sahibinin user/group ID’si gibi bilgileri döndüren bir sistem çağrısıdır. S_IFREG normal bir dosya türü olduğunu belirtiyor. (Örnek olarak burada bir symlink kullanılsaydı burada göreceğimiz değer S_IFLNK olacaktı.) Ayrıca dosyamız stdin olduğu için 0 değerini döndürdü.

mmap() Bir process’in adres alanıyla, dosya/aygıt arasında bağlantı kurmak için kullanılır. mmap() birden fazla processin aynı fiziksel bellek sayfalarını paylaşmasına izin verir ve bu sayede bellek tüketim tasarrufu da sağlar. Bu çağrıda mmap fstat tarafından read edilen 34879 dosya boyutunu kulanıcaktır. Tüm bu dosyayı processin sanal belleğine işler ve ilgili bellek adresi olan 0x7fe05a99f000 adresini bize döndürür.

close() belirtilen dosya tanıtıcısını serbest bırakacaktır. Bu işlem sayesinde serbest bırakılan alan bir sonraki open() ya da başka işlemler tarafından döndürülebilecek şekilde kullanılabilir hale getirecektir.

4  openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
5  fstat(3, {st_mode=S_IFREG|0644, st_size=34879, ...}) = 0
6  mmap(NULL, 34879, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fe05a99f000
7  close(3)                                = 0

openat() /lib/x86_64-linux-gnu/libc.so.6 dosyasını açtı ve dosya tanımlayıcı değeri olan ‘3’ sayısını döndürdü. Bu sayı GNU C Kütüphanesi üzerinde çalışmak için kullanılacak.

read() dosya tanımlayıcısından memory’e baytları saymak için okuma yapar. libc.so.6 üzerinden 832 byte’ı okudu ve ikinci parametre Executable and Linkable Format dosyasının başlık bilgisini, ayrıca Executable and Linkable Format dosyasının doğrulanması için kullanılan 832 baytı okudu.

pread64() read ile aynı işi yapar tek farkı read gibi I/O başlangıcını file offset yerine belirtilen offset üzerinden okumaya başlar.

fstat() ile dosya tanımlayıcımız olan ‘3’ değerli dosyamızın normal bir dosya türü (S_IFREG) olduğunu gösterdi.

mmap() dosya(ları) sanal belleklere eşleştirdi.

close() Eşleşmenin başarılı gerçekleşmesinden ötürü dosya tanıtıcısını serbest bıraktı. Serbest bırakılan alan bir sonraki open() ya da başka işlemler tarafından döndürülebilecek şekilde kullanılabilir hale getirildi.


8  openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
9  read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\360A\2\0\0\0\0\0"..., 832) = 832
10  pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
11  pread64(3, "\4\0\0\0\20\0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0", 32, 848) = 32
12  pread64(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0\237\333t\347\262\27\320l\223\27*\202C\370T\177"..., 68, 880) = 68
13  fstat(3, {st_mode=S_IFREG|0755, st_size=2029560, ...}) = 0
14  mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fe05a99d000
15  pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
16  pread64(3, "\4\0\0\0\20\0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0", 32, 848) = 32
17  pread64(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0\237\333t\347\262\27\320l\223\27*\202C\370T\177"..., 68, 880) = 68
18  mmap(NULL, 2037344, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fe05a7ab000
19  mmap(0x7fe05a7cd000, 1540096, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x22000) = 0x7fe05a7cd000
20  mmap(0x7fe05a945000, 319488, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x19a000) = 0x7fe05a945000
21  mmap(0x7fe05a993000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1e7000) = 0x7fe05a993000
22  mmap(0x7fe05a999000, 13920, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fe05a999000
23  close(3)                                = 0

arch_prctl () sistem çağrısı mimariye özgü süreci ya da processin durumunu ayarlar. Burada kod bir subfunction seçerek argümanını addr olarakiletir. ARCH_SET_FS addr argümanının 64 bit olarak ayarlanmasını sağladı ve FS kayıt adresini bize verdi ‘0x7fe05a99e580’.

mprotect() addr ile çağrılan işlemin bellek sayfalarının erişim korumasını değiştirmek için kullanılır. PROD_READ ilgili adresin okunulabilir olmasını sağlar.

munmap() sanal bellek ile eşleştirdiğimiz dosyanın eşleştirmesini kaldırır. /etc/ld.so.cache dosyasını 0x7fe05a99f000 adresiyle eşleştirmiştik 6.satırda görebileceğiniz üzere ve bu eşleştirmeyi kaldırdı.

brk(NULL) ile heap memory bitişi sorgulandı.

openat() /usr/lib/locale/locale-archive dosyasını açtı ve dosya tanımlayıcı değeri olarak ‘3’ değerini döndürdü. Local Archive dosyası sistem tarafından sağlanan tüm yerel ayarları içeren bellek ile eşleştirilmiş bir dosyadır. LOCPATH env ayarlanmadığında tüm local programlar tarafından kullanılır.

fstat() ile dosya tanımlayıcımız olan ‘3’ değerli dosyamızın normal bir dosya türü (S_IFREG) olduğunu gösterdi.

mmap() dosya sanal bellek ile eşleştirdi.

close() Eşleşmenin başarılı gerçekleşmesinden ötürü dosya tanıtıcısını serbest bıraktı. Serbest bırakılan alan bir sonraki open() ya da başka işlemler tarafından döndürülebilecek şekilde kullanılabilir hale gertirildi.

24  arch_prctl(ARCH_SET_FS, 0x7fe05a99e580) = 0
25  mprotect(0x7fe05a993000, 16384, PROT_READ) = 0
26  mprotect(0x556664fb3000, 4096, PROT_READ) = 0
27  mprotect(0x7fe05a9d5000, 4096, PROT_READ) = 0
28  munmap(0x7fe05a99f000, 34879)           = 0
29  brk(NULL)                               = 0x556665943000
30  brk(0x556665964000)                     = 0x556665964000
31  openat(AT_FDCWD, "/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
32  fstat(3, {st_mode=S_IFREG|0644, st_size=3035952, ...}) = 0
33  mmap(NULL, 3035952, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fe05a4c5000
34  close(3)

Yukarıdaki bilgiler eşliğinde yorumlayabileceğiniz aşağıdaki sistem çağrıları bir çok path’i açtı, dosyayı sanal bellek ile eşleştirdi ve eşleştirme sonrasında dosya tanıtıcısını serbest bıraktı. Örnek olarak maplenen locale alias ; yerel ayarlar, dil, ülke ve karakter kodlama ayarlarını tanımlayan locale için değerlerin barındığı databasedir. Ya da UTF-8 encode/decode işlemlerini görebilirsiniz.

35  openat(AT_FDCWD, "/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 3
36  fstat(3, {st_mode=S_IFREG|0644, st_size=2996, ...}) = 0
37  read(3, "# Locale name alias data base.\n#"..., 4096) = 2996
38  read(3, "", 4096)                       = 0
39  close(3)                                = 0
40  openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_IDENTIFICATION", O_RDONLY|O_CLOEXEC) = 3
41  fstat(3, {st_mode=S_IFREG|0644, st_size=252, ...}) = 0
42  mmap(NULL, 252, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fe05a9d4000
43  close(3)                                = 0
44  openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache", O_RDONLY) = 3
45  fstat(3, {st_mode=S_IFREG|0644, st_size=27002, ...}) = 0
46  mmap(NULL, 27002, PROT_READ, MAP_SHARED, 3, 0) = 0x7fe05a9a1000
47  close(3)                                = 0
48  openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_MEASUREMENT", O_RDONLY|O_CLOEXEC) = 3
49  fstat(3, {st_mode=S_IFREG|0644, st_size=23, ...}) = 0
50  mmap(NULL, 23, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fe05a9a0000
51  close(3)                                = 0
52  openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_TELEPHONE", O_RDONLY|O_CLOEXEC) = 3
53  fstat(3, {st_mode=S_IFREG|0644, st_size=47, ...}) = 0
54  mmap(NULL, 47, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fe05a99f000
55  close(3)                                = 0
56  openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_ADDRESS", O_RDONLY|O_CLOEXEC) = 3
57  fstat(3, {st_mode=S_IFREG|0644, st_size=131, ...}) = 0
58  mmap(NULL, 131, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fe05a4c4000
59  close(3)                                = 0
60  openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_NAME", O_RDONLY|O_CLOEXEC) = 3
61  fstat(3, {st_mode=S_IFREG|0644, st_size=62, ...}) = 0
62  mmap(NULL, 62, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fe05a4c3000
63  close(3)                                = 0
64  openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_PAPER", O_RDONLY|O_CLOEXEC) = 3
65  fstat(3, {st_mode=S_IFREG|0644, st_size=34, ...}) = 0
66  mmap(NULL, 34, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fe05a4c2000
67  close(3)                                = 0
68  openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_MESSAGES", O_RDONLY|O_CLOEXEC) = 3
69  fstat(3, {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
70  close(3)                                = 0
71  openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_MESSAGES/SYS_LC_MESSAGES", O_RDONLY|O_CLOEXEC) = 3
72  fstat(3, {st_mode=S_IFREG|0644, st_size=48, ...}) = 0
73  mmap(NULL, 48, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fe05a4c1000
74  close(3)                                = 0
75  openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_MONETARY", O_RDONLY|O_CLOEXEC) = 3
76  fstat(3, {st_mode=S_IFREG|0644, st_size=270, ...}) = 0
77  mmap(NULL, 270, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fe05a4c0000
78  close(3)                                = 0
79  openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_COLLATE", O_RDONLY|O_CLOEXEC) = 3
80  fstat(3, {st_mode=S_IFREG|0644, st_size=1518110, ...}) = 0
81  mmap(NULL, 1518110, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fe05a34d000
82  close(3)                                = 0
83  openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_TIME", O_RDONLY|O_CLOEXEC) = 3
84  fstat(3, {st_mode=S_IFREG|0644, st_size=3360, ...}) = 0
85  mmap(NULL, 3360, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fe05a34c000
86  close(3)                                = 0
87  openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_NUMERIC", O_RDONLY|O_CLOEXEC) = 3
88  fstat(3, {st_mode=S_IFREG|0644, st_size=50, ...}) = 0
89  mmap(NULL, 50, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fe05a34b000
90  close(3)                                = 0
91  openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_CTYPE", O_RDONLY|O_CLOEXEC) = 3
92  fstat(3, {st_mode=S_IFREG|0644, st_size=201272, ...}) = 0
93  mmap(NULL, 201272, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fe05a319000
94  close(3)                                = 0

fstat() değeri 1i olan stdout dosya tanımlaycısını kullanıyor çünkü echo programı çıktıyı stdout olarak vermektedir. fstat ayrıca stdin için ‘0’ değerini, stderr için ‘2’ değerini kullanıyor. Neden tüm openat() sistem çağrılarının 3 ile başladığını da anlamış olduk.:slightly_smiling_face:

write() buffer ile gösterilen arabellekten baytları açık dosya tanıtıcısına yazar. Dosya tanıtıcımız ‘1’ stdout olduğu için, ekrana Hello World çıktısını yazdı.

close() stdout olan 1 ve stderr olan ‘2’ değerine sahip dosya taımlayıcılarını serbest bıraktı.

exit_group() bir process’in barındığı tüm threadlerden çıkılmasını sağlar. Burada 0 değerinin dönmesi işlemimizin başarılı olduğu anlamına geliyor. Genel olarak sistem çağrılarında 0 cevabı işlemin başarılı olduğuna delalet eder.

95  fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0), ...}) = 0
96  write(1, "Hello World\n", 12)           = 12
97  close(1)                                = 0
98  close(2)                                = 0
99  exit_group(0)                           = ?
100  +++ exited with 0 +++
6 Likes

Ellerine sağlık hocam.

1 Like