Bir dosyayı açmak aslında ne yapar?


266

Tüm programlama dillerinde (en azından kullandığım), okuyabilmeniz veya yazabilmeniz için bir dosyayı açmanız gerekir.

Peki bu açık operasyon aslında ne yapıyor?

Tipik işlevler için manuel sayfalar size aslında 'okuma / yazma için bir dosya açar' dışında bir şey söylemez:

http://www.cplusplus.com/reference/cstdio/fopen/

https://docs.python.org/3/library/functions.html#open

Açıkçası, fonksiyonun kullanımı yoluyla, bir dosyaya erişmeyi kolaylaştıran bir tür nesnenin yaratılmasını içerdiğini söyleyebilirsiniz.

Bunu söylemenin başka bir yolu, eğer bir openişlevi yerine getirseydim, Linux'ta ne yapması gerekirdi?


13
Bu soruyu CLinux ve Linux'a odaklanacak şekilde düzenleme ; çünkü Linux ve Windows'un yaptıkları farklı. Aksi takdirde, biraz fazla geniş. Ayrıca, herhangi bir üst düzey dil, sistem için bir C API'sini çağırır veya yürütmek için C'ye derler, böylece "C" düzeyinde bırakmak bunu En Az Ortak Payda'ya yerleştirir.
George Stocker

1
Tüm programlama dillerinin bu tesise sahip olmadığını veya çevreye oldukça bağımlı bir tesis olduğunu belirtmiyoruz. Kuşkusuz bu günlerde elbette nadirdir, ancak bu güne kadar dosya işleme ANSI Forth'ın tamamen isteğe bağlı bir parçasıdır ve geçmişte bazı uygulamalarda bile mevcut değildi.

Yanıtlar:


184

Hemen hemen her üst düzey dilde, bir dosyayı açan işlev, karşılık gelen çekirdek sistem çağrısının etrafına sarılır. Başka süslü şeyler de yapabilir, ancak çağdaş işletim sistemlerinde, bir dosyayı açmak her zaman çekirdekten geçmelidir.

Bu nedenle fopenkütüphane işlevinin veya Python'un openargümanları open(2)sistem çağrısının argümanlarına çok benzemektedir .

Dosyayı açmaya ek olarak, bu işlevler genellikle okuma / yazma işlemleriyle sonuç olarak kullanılacak bir tampon oluşturur. Bu tamponun amacı, N bayt okumak istediğinizde, ilgili kütüphane çağrısının, temel sistem çağrılarına yapılan çağrıların daha az geri dönüp dönmediğine bakılmaksızın N bayt döndürmesini sağlamaktır.

Aslında kendi işlevimi uygulamakla ilgilenmiyorum; sadece neler olduğunu anlamak için ... isterseniz 'dilin ötesinde'.

Unix benzeri işletim sistemlerinde, openkullanıcı işlemi bağlamında yalnızca bir tamsayı olan bir "dosya tanımlayıcı" döndürmek için başarılı bir çağrı . Sonuç olarak bu tanımlayıcı, açılan dosyayla etkileşime giren tüm çağrılara aktarılır ve çağrıldıktan sonra closetanımlayıcı geçersiz hale gelir.

Dikkat opençekilmesi, çeşitli kontrollerin yapıldığı bir doğrulama noktası gibi hareket ettiğine dikkat etmek önemlidir . Koşulların tümü karşılanmazsa, -1tanımlayıcı yerine geri dönerek çağrı başarısız olur ve hata türü olarak gösterilir errno. Gerekli kontroller:

  • Dosyanın var olup olmadığı;
  • Çağıran işlemin bu dosyayı belirtilen modda açma ayrıcalığına sahip olup olmadığı. Bu, dosya izinleri, sahip kimliği ve grup kimliğini çağıran işlemin ilgili kimlikleriyle eşleştirerek belirlenir.

Çekirdek bağlamında, işlemin dosya tanımlayıcıları ile fiziksel olarak açılan dosyalar arasında bir tür eşleme olmalıdır. Tanımlayıcıya eşlenen dahili veri yapısı, blok tabanlı aygıtlarla ilgilenen başka bir arabellek veya geçerli okuma / yazma konumuna işaret eden dahili bir işaretçi içerebilir.


2
Unix benzeri işletim sistemlerinde çekirdek içi yapı dosya tanımlayıcılarının eşlendiğine "açık dosya açıklaması" adı verildiğini belirtmek gerekir. Böylece süreç FD'leri çekirdek OFD'lere eşlenir. Bu, dokümantasyonu anlamak için önemlidir. Örneğin, açık bir dosya tanımlayıcı ( açık olan bir FD) ve açık bir dosya açıklaması (OFD) man dup2arasındaki inceliği görün ve kontrol edin .
rodrigo

1
Evet, izinler açık zamanda kontrol edilir. Çekirdeğin "açık" uygulaması için kaynak okuyabilirsiniz: lxr.free-electrons.com/source/fs/open.c Çalışmanın çoğunu belirli bir dosya sistemi sürücüsüne devretmesine rağmen.
pjc50

1
(ext2 sistemlerinde bu, hangi inode'un metadata içerdiğini belirlemek için dizin girişlerinin okunmasını ve daha sonra bu inode'u inode önbelleğine yüklemesini içerir. Bir dosyayı açtığınızda)
pjc50

1
Dosyadaki denetimlerin açık olduğunu - dosyanın var olduğunu, izninizin olduğunu - pratikte yeterli olmadığını unutmayın. Dosya kaybolabilir veya izinleri ayaklarınızın altında değişebilir. Bazı dosya sistemleri bunu engellemeye çalışır, ancak işletim sisteminiz ağ depolamasını desteklediği sürece önlenmesi imkansızdır (yerel dosya sistemi yanlış davranırsa ve mantıklıysa bir işletim sistemi "panik yapabilir": bir ağ paylaşımı olmadığında bunu yapar uygulanabilir bir işletim sistemi). Bu kontroller dosya açıkken de yapılır, ancak diğer tüm dosya erişimlerinde de (etkin olarak) yapılmalıdır.
Yakk - Adam Nevraumont

2
Kilitlerin değerlendirilmesini ve / veya oluşturulmasını unutmamak. Bunlar paylaşılabilir veya özel olabilir ve tüm dosyayı veya yalnızca bir kısmını etkileyebilir.
Thinkeye

83

Sistem çağrısının basitleştirilmiş bir sürümü aracılığıyla bu kılavuza göz atmanızı öneririmopen() . Bir dosyayı açtığınızda perde arkasında neler olduğunu gösteren aşağıdaki kod snippet'ini kullanır.

0  int sys_open(const char *filename, int flags, int mode) {
1      char *tmp = getname(filename);
2      int fd = get_unused_fd();
3      struct file *f = filp_open(tmp, flags, mode);
4      fd_install(fd, f);
5      putname(tmp);
6      return fd;
7  }

Kısaca, bu kodun satır satır yaptığı şey:

  1. Bir çekirdek kontrollü bellek bloğu tahsis edin ve dosya adını kullanıcı kontrollü bellekten kopyalayın.
  2. Şu anda açık olan dosyaların büyütülebilir bir listesine tamsayı dizini olarak düşünebileceğiniz kullanılmayan bir dosya tanımlayıcı seçin. Her işlemin kendi listesi vardır, ancak çekirdek tarafından korunur; kodunuz doğrudan erişemiyor. Listedeki bir girdi, inode numarası, işlem izinleri, açık bayraklar vb. Gibi baytları diskten çıkarmak için temel dosya sisteminin kullanacağı bilgileri içerir.
  3. filp_openİşlevi uygulama vardır

    struct file *filp_open(const char *filename, int flags, int mode) {
            struct nameidata nd;
            open_namei(filename, flags, mode, &nd);
            return dentry_open(nd.dentry, nd.mnt, flags);
    }

    ki bu iki şey yapar:

    1. Aktarılan dosya adına veya yola karşılık gelen inode (veya daha genel olarak, dosya sisteminin kullandığı her türlü iç tanımlayıcı) aramak için dosya sistemini kullanın.
    2. struct fileİnode hakkında gerekli bilgileri içeren bir a oluşturun ve geri gönderin. Bu yapı, daha önce bahsettiğim açık dosyalar listesindeki girdi haline gelir.
  4. Döndürülen yapıyı işlemin açık dosyalar listesine kaydedin ("install").

  5. Çekirdek kontrollü belleğin ayrılmış bloğunu boşaltın.
  6. Sonra gibi dosya işlem fonksiyonlarına geçirilebilir dosya tanıtıcı İade read(), write()ve close(). Bunların her biri denetimi işlem listesindeki ilgili dosya işaretçisini aramak için dosya tanımlayıcıyı kullanabilen ve bu dosya işaretçisindeki bilgileri gerçekten okuma, yazma veya kapatma işlemini gerçekleştirmek için kullanabilen çekirdeğe dağıtacaktır.

Hırslı hissediyorsanız, bu basitleştirilmiş örneği open(), çağrılan bir işlev olan Linux çekirdeğindeki sistem çağrısının uygulanmasıyla karşılaştırabilirsiniz do_sys_open(). Benzerlikleri bulmakta sorun yaşamamanız gerekir.


Tabii ki, bu yalnızca aradığınızda gerçekleşen şeyin "üst katmanı" dır open()- veya daha doğrusu, bir dosyayı açma sürecinde çağrılan en üst düzey çekirdek kodu parçasıdır. Üst düzey bir programlama dili bunun üzerine ek katmanlar ekleyebilir. Daha düşük seviyelerde devam eden çok şey var. ( Açıklamak için Ruslan ve pjc50'ye teşekkürler .) Kabaca, yukarıdan aşağıya:

  • open_namei()ve dentry_open()çekirdeğin bir parçası olan dosya sistemi kodunu, dosya ve dizinlerin meta verilerine ve içeriğine erişmeye çağırır. Dosya sistemi diskten ham bayt okur ve dosya ve dizin bir ağaç olarak bu bayt desenlerini yorumlar.
  • Dosya sistemi, bu ham baytları sürücüden elde etmek için yine çekirdeğin bir parçası olan blok aygıt katmanını kullanır . (Eğlenceli gerçek: Linux, aşağıdakileri kullanarak blok cihaz katmanından ham verilere erişmenizi sağlar/dev/sda ve benzeri .)
  • Blok aygıt katmanı, aynı zamanda çekirdek kodu olan bir depolama aygıtı sürücüsünü, "okuma sektörü X" gibi orta düzeyli bir talimattan makine kodundaki bireysel giriş / çıkış komutlarına çevirmek için çağırır . Bir sürücünün kullanabileceği farklı iletişim standartlarına karşılık gelen IDE , (S) ATA , SCSI , Firewire vb. Gibi çeşitli depolama aygıtı sürücüleri vardır . (Adlandırmanın dağınık olduğunu unutmayın.)
  • G / Ç talimatları, fiziksel sürücüye giden kablo üzerinde elektrik sinyalleri göndermek ve almak için işlemci yongasının ve anakart denetleyicisinin yerleşik özelliklerini kullanır. Bu yazılım değil, donanımdır.
  • Telin diğer ucunda, diskin bellenimi (gömülü kontrol kodu), plakaları döndürmek ve kafaları (HDD) hareket ettirmek veya bir flash ROM hücresini (SSD) okumak için gerekli olan elektrik sinyallerini veya bu tür bir depolama aygıtı.

Bu ayrıca önbellekleme nedeniyle biraz yanlış olabilir . :-P Cidden, dışarıda bıraktığım birçok detay var - bir kişi (ben değil), tüm sürecin nasıl çalıştığını açıklayan birden fazla kitap yazabilir. Ama bu size bir fikir vermeli.


67

Konuşmak istediğiniz herhangi bir dosya sistemi veya işletim sistemi benim için iyi. Güzel!


Bir ZX Spektrumunda, bir LOADkomutun başlatılması sistemi Ses Girişi satırını okuyarak sıkı bir döngüye sokacaktır.

Verilerin başlangıcı sabit bir tonla gösterilir ve bundan sonra bir kısa / uzun darbe ikili 0ve daha uzun bir ikili 1( ikili) için bir dizi uzun / kısa darbe izler ( https://en.wikipedia.org/ wiki / ZX_Spectrum_software ). Sıkı yük döngüsü, bir baytı (8 bit) doldurana kadar bitleri toplar, bunu belleğe kaydeder, bellek işaretçisini artırır, sonra daha fazla bit taramak için geri döner.

Tipik olarak, bir yükleyicinin okuyacağı ilk şey , en azından beklenecek bayt sayısını ve muhtemelen dosya adı, dosya türü ve yükleme adresi gibi ek bilgileri gösteren kısa, sabit bir format üstbilgisidir . Bu kısa başlığı okuduktan sonra, program verilerin ana yığınını yüklemeye devam etmeye veya yükleme rutininden çıkıp kullanıcı için uygun bir mesaj görüntülemeye karar verebilir.

Dosya sonu durumu, beklendiği kadar bayt alınarak tanınabilir (sabit sayıda bayt, yazılımda kablolu veya bir başlıkta belirtildiği gibi değişken bir sayı). Yükleme döngüsü belirli bir süre için beklenen frekans aralığında bir darbe almadıysa bir hata atılır.


Bu cevapta biraz arka plan

Açıklanan prosedür düzenli bir ses kasetinden veri yükler - bu nedenle Ses Girişini tarama ihtiyacı (standart bir fişe bant kaydedicilere bağlanır). Bir LOADkomut teknik olarak openbir dosya ile aynıdır - ancak dosyayı gerçekten yüklemek için fiziksel olarak bağlıdır . Bunun nedeni, ses kayıt cihazının bilgisayar tarafından kontrol edilmemesi ve bir dosyayı (başarıyla) açamamanız ancak yükleyememenizdir.

"Sıkı döngü" denir, çünkü (1) CPU, bir Z80-A (bellek çalışıyorsa), gerçekten yavaştı: 3.5 MHz ve (2) Spectrum'un dahili saati yoktu! Bu, her biri için T durumlarını (talimat süreleri) doğru bir şekilde tutması gerektiği anlamına gelir . tek. talimat. Doğru bip zamanlamasını korumak için bu döngü içinde.
Neyse ki, bu düşük CPU hızı, bir kağıt parçasındaki döngü sayısını ve dolayısıyla alacakları gerçek dünya zamanını hesaplayabileceğiniz belirgin bir avantaja sahipti.


10
@ BillWoodger: evet. Ama bu adil bir soru (yani seninki). "Çok geniş" olarak kapanmaya oy verdim ve cevabım sorunun aslında ne kadar geniş olduğunu göstermek anlamına geliyor.
usr2564301

8
Cevabı biraz fazla genişlettiğinizi düşünüyorum. ZX Spectrum'un OPEN komutu vardı ve bu LOAD'dan tamamen farklıydı. Ve anlaşılması daha zor.
rodrigo

3
Soruyu kapatma konusunda da aynı fikirde değilim, ama cevabınızı gerçekten çok seviyorum.
Enzo Ferber

23
Sorumu açık tutmak amacıyla linux / windows OS ile kısıtlamak için düzenlesem de, bu cevap tamamen geçerli ve kullanışlıdır. Sorumda belirtildiği gibi, bir şey uygulamak ya da başkalarının işimi yapmasını istemiyorum, öğrenmek istiyorum. Öğrenmek için 'büyük' ​​sorular sormalısınız. SO hakkında 'çok geniş' olduğu için soruları sürekli kapatırsak, insanların neyi, nerede veya neden hakkında herhangi bir açıklama yapmadan sadece kodunuzu sizin için yazmasını sağlayan bir yer haline gelme riski vardır. Bunu öğrenmeye gelebileceğim bir yer olarak tutmayı tercih ederim.
jramm

14
Bu cevap , sorunun kendi yorumunun çok geniş olmaktansa, sorunuzu yorumlamanızın çok geniş olduğunu kanıtlamaktadır .
jwg

17

Bir dosyayı açtığınızda tam olarak ne olacağı işletim sistemine bağlıdır. Aşağıda, bir dosyayı açtığınızda ne olacağına dair bir fikir verdiği için Linux'ta neler olduğunu açıklıyorum ve daha ayrıntılı olarak ilgileniyorsanız kaynak kodunu kontrol edebilirsiniz. Bu cevabı çok uzun süre alacağı için izinleri kapsamıyorum.

Linux'ta her dosya inode adı verilen bir yapı tarafından tanınır. Her yapının benzersiz bir numarası vardır ve her dosya sadece bir inode numarası alır. Bu yapı, bir dosya için meta verileri, örneğin dosya boyutu, dosya izinleri, zaman damgaları ve disk bloklarına işaretçi olarak saklar, ancak gerçek dosya adının kendisini saklamaz. Her dosya (ve dizin), bir dosya adı girişi ve arama için inode numarasını içerir. Bir dosyayı açtığınızda, ilgili izinlere sahip olduğunuzu varsayarsak, dosya adıyla ilişkili benzersiz inode numarası kullanılarak bir dosya tanımlayıcı oluşturulur. Birçok işlem / uygulama aynı dosyayı gösterebildiğinden, inode, dosyaya toplam bağlantı sayısını koruyan bir bağlantı alanına sahiptir. Bir dosya bir dizinde mevcutsa, bağlantı sayısı birdir, eğer sabit bir bağlantı varsa, bağlantı sayısı iki olur ve bir dosya bir işlem tarafından açılırsa, bağlantı sayısı 1 artar.


6
Bunun asıl soru ile ne ilgisi var?
Bill Woodger

1
Linux'ta bir dosyayı açtığınızda düşük seviyede neler olduğunu açıklar. Sorunun oldukça geniş olduğunu kabul ediyorum, bu yüzden jramm'ın aradığı cevap bu olmayabilir.
Alex

1
Yine, izinleri kontrol etmek yok mu?
Bill Woodger

11

Defter tutma, çoğunlukla. Bu, "Dosya var mı?" ve "Bu dosyayı yazmak için açma iznim var mı?".

Ama hepsi çekirdek şeyler - kendi oyuncak işletim sisteminizi uygulamadığınız sürece, araştırılacak çok şey yok (eğer eğleniyorsanız - bu harika bir öğrenme deneyimidir). Tabii ki, bir dosyayı açarken alabileceğiniz tüm olası hata kodlarını hala öğrenmelisiniz, böylece bunları düzgün bir şekilde işleyebilirsiniz - ancak bunlar genellikle güzel küçük soyutlamalar.

Kod seviyesindeki en önemli kısım, bir dosya ile yaptığınız diğer tüm işlemler için kullandığınız açık dosyaya bir tanıtıcı sağlamasıdır. Bu rastgele tanıtıcı yerine dosya adını kullanamaz mısınız? Elbette - ancak bir kulp kullanmak size bazı avantajlar sağlar:

  • Sistem şu anda açık olan tüm dosyaları izleyebilir ve silinmelerini önleyebilir (örneğin).
  • Modern işletim sistemleri kulplar etrafında inşa edilmiştir - kulplarla yapabileceğiniz tonlarca yararlı şey vardır ve her türlü kulp neredeyse aynı şekilde davranır. Örneğin, bir Windows dosya tanıtıcısında eşzamansız bir G / Ç işlemi tamamlandığında, tanıtıcı işaretlenir - bu, işaretlenene kadar tanıtıcıyı engellemenizi veya işlemi tamamen eşzamansız olarak tamamlamanızı sağlar. Bir dosya tanıtıcısında beklemek, bir iplik tanıtıcısında (örn. İplik bittiğinde sinyal verilir), bir işlem tanıtıcısında (yine, işlem sona erdiğinde sinyal verilir) veya bir sokette (bazı eşzamansız işlemler tamamlandığında) beklemekle tamamen aynıdır. En önemlisi, tutamaçlar ilgili işlemlerine aittir, bu nedenle bir işlem beklenmedik bir şekilde sonlandırıldığında (veya uygulama kötü yazılmışsa), OS hangi tutamaçları serbest bırakabileceğini bilir.
  • Çoğu işlem konumlandırılmıştır - readdosyanızdaki son konumdan itibaren. Bir dosyanın belirli bir "açılışını" tanımlamak için bir tutamaç kullanarak, her biri kendi yerlerinden okuyan aynı dosya için birden çok eşzamanlı tutamağa sahip olabilirsiniz. Bir şekilde, tanıtıcı dosyaya taşınabilir bir pencere görevi görür (ve çok kullanışlı olan eşzamansız G / Ç isteklerini yayınlamanın bir yolu).
  • Tanıtıcılar dosya adlarından çok daha küçüktür. Tanıtıcı genellikle bir işaretçinin boyutudur, tipik olarak 4 veya 8 bayttır. Öte yandan, dosya adlarında yüzlerce bayt olabilir.
  • Tutamaçlar , uygulamalar açık olsa bile işletim sisteminin dosyayı taşımasına izin verir - tanıtıcı hala geçerli ve dosya adı değişmiş olsa bile aynı dosyayı gösteriyor.

Örneğin (yapabileceği diğer bazı hileler de var, süreçler arasındaki payı kolları bir iletişim kanalı olması olmadan fiziksel bir dosya kullanarak; unix sistemlerde, dosyaları da cihazlar ve diğer çeşitli sanal kanallar için kullanılır, bu kesinlikle gerekli değildir bu yüzden ), ancak openoperasyonun kendisine gerçekten bağlı değiller , bu yüzden bunu araştırmayacağım.


7

Bunun özünde hiçbir şey fantezi aslında okumak için açılırken ihtiyacı gerçekleşmesi. Tek yapması gereken dosyanın var olduğunu kontrol etmek ve uygulamanın dosyayı okumak ve dosyaya okuma komutları verebileceğiniz bir tanıtıcı oluşturmak için yeterli ayrıcalığa sahip olması.

Gerçek okumanın gönderileceği komutlar üzerinde.

İşletim sistemi, genellikle tutamaçla ilişkili arabelleği doldurmak için bir okuma işlemi başlatarak okumaya bir başlangıç ​​yapar. Daha sonra gerçekten okuma yaptığınızda, disk IO beklemek yerine hemen tampon içeriğini döndürebilir.

Yazma için yeni bir dosya açmak için işletim sisteminin yeni (şu anda boş) dosyanın dizinine bir giriş eklemesi gerekir. Ve yine, üzerinde yazma komutlarını verebileceğiniz bir tanıtıcı oluşturulur.


5

Temel olarak, bir açma çağrısının dosyayı bulması ve daha sonra G / Ç işlemlerinin tekrar bulabilmesi için gereken her şeyi kaydetmesi gerekir. Bu oldukça belirsiz, ama hemen düşünebildiğim tüm işletim sistemlerinde geçerli olacak. Ayrıntılar platformdan platforma değişir. Burada zaten birçok cevap günümüz masaüstü işletim sistemleri hakkında konuşuyor. CP / M üzerinde küçük bir programlama yaptım, bu yüzden CP / M üzerinde nasıl çalıştığı hakkında bilgimi sunacağım (MS-DOS muhtemelen aynı şekilde çalışır, ancak güvenlik nedeniyle, bugün böyle yapılmaz. ).

CP / M'de FCB denilen bir şey var (C'den bahsettiğiniz gibi, ona bir yapı diyebilirsiniz; gerçekten RAM'de çeşitli alanları içeren 35 baytlık bitişik bir alandır). FCB, dosya adını yazmak için alanlara ve disk sürücüsünü tanımlayan bir (4 bit) tamsayıya sahiptir. Ardından, çekirdeğin Açık Dosyasını çağırdığınızda, CPU'nun kayıtlarından birine yerleştirerek bu yapıya bir işaretçi iletirsiniz. Bir süre sonra, işletim sistemi yapı biraz değiştiğinde geri döner. Bu dosyaya yaptığınız G / Ç ne olursa olsun, sistem çağrısına bu yapıya bir işaretçi iletirsiniz.

CP / M bu FCB ile ne yapar? Belirli alanları kendi kullanımı için ayırır ve bunları dosyayı takip etmek için kullanır, böylece programınızın içinden hiç dokunmamanız daha iyi olur. Dosya Aç işlemi, diskin başındaki tablodan FCB'de bulunanla aynı ada sahip bir dosya arar ('?' Joker karakteri herhangi bir karakterle eşleşir). Bir dosya bulursa, dosyanın diskteki fiziksel konumları da dahil olmak üzere bazı bilgileri FCB'ye kopyalar, böylece sonraki G / Ç çağrıları bu konumları disk sürücüsüne geçirebilecek BIOS'u çağırır. Bu seviyede, özellikler değişiklik gösterir.


-7

Basit bir ifadeyle, bir dosyayı açtığınızda işletim sisteminden istenen dosyayı (dosyanın içeriğini kopyala) ikincil depodan işlemek için ram'a yüklemesini istersiniz. Bunun arkasındaki sebep (Dosya yükleme) Ram ile karşılaştırıldığında son derece düşük hızı nedeniyle dosyayı doğrudan Sabit diskten işleyememenizdir.

Open komutu, dosyanın içeriğini ikincil depolamadan (Sabit disk) Birincil depolama alanına (Ram) kopyalayan bir sistem çağrısı oluşturur.

Bir dosyayı 'Kapatıyoruz' çünkü dosyanın değiştirilmiş içerikleri sabit diskteki orijinal dosyaya yansıtılmalıdır. :)

Umarım yardımcı olur.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.