系統(tǒng)之家 - 系統(tǒng)光盤下載網(wǎng)站!

當(dāng)前位置:系統(tǒng)之家 > 系統(tǒng)教程 > Linux中文件I/O操作

Linux下文件I/O操作的相關(guān)知識(shí)(3)

時(shí)間:2014-12-26 15:58:35 作者:qipeng 來源:系統(tǒng)之家 1. 掃描二維碼隨時(shí)看資訊 2. 請(qǐng)使用手機(jī)瀏覽器訪問: https://m.xitongzhijia.net/xtjc/20141226/33535.html 手機(jī)查看 評(píng)論

  現(xiàn)在對(duì)前一節(jié)文件I/O(1)的幾個(gè)操作進(jìn)一步說明:

  1. 完成write之后,文件中當(dāng)前偏移量即所增加的字節(jié)數(shù)。如果當(dāng)前偏移量大于文件長度,則將i節(jié)點(diǎn)中當(dāng)前文件長度設(shè)為當(dāng)前文件偏移量。

  2. 用O_APPEND打開一個(gè)文件,相應(yīng)標(biāo)志會(huì)被設(shè)置到文件狀態(tài)標(biāo)識(shí)中。每次寫時(shí),當(dāng)前偏移量會(huì)被設(shè)置為i節(jié)點(diǎn)中的文件長度

  3. lseek定位到文件尾端時(shí),則文件當(dāng)前偏移量會(huì)被設(shè)置為當(dāng)前文件長度。

  可能有多個(gè)文件描述符指向同一文件表項(xiàng)。調(diào)用dup和fork時(shí)都能看到這一點(diǎn)。

  多個(gè)進(jìn)程讀同一文件能正確工作。但多個(gè)進(jìn)程寫同一文件時(shí),可能產(chǎn)生預(yù)期不到的后果?梢岳迷硬倏v避免這種情況。

  原子操作

  一般而言,原子操作指的是由多部組成的操作。如果該院自地執(zhí)行,要么執(zhí)行完所以步驟,要么一步也不執(zhí)行。

  1. 添加至一個(gè)文件

  考慮一個(gè)進(jìn)程,它要講數(shù)據(jù)添加到一個(gè)文件尾端。早期UNIX不支持open,所以可以如下實(shí)現(xiàn):

  代碼如下:

  if(lseek(fd, 0L, 2)《0)

  err_sys(“lseekerror”);

  if(write(fd, buf, 100) != 100)

  err_sys(“writeerror”);

  對(duì)于單個(gè)進(jìn)程,這段程序能正常工作。但多個(gè)進(jìn)程就不一定。結(jié)社進(jìn)程A和B都對(duì)同一文件進(jìn)行添加操作。每個(gè)進(jìn)程都打開該文件,此時(shí)數(shù)據(jù)結(jié)構(gòu)之間關(guān)系如圖2中所示。假定A調(diào)用lseek,將A的當(dāng)前偏移量設(shè)置為1500。進(jìn)程B執(zhí)行l(wèi)seek也將其當(dāng)前偏移量設(shè)為1500。然后B調(diào)用write,將當(dāng)前偏移量增至1600。然后內(nèi)核又進(jìn)行進(jìn)程切換使進(jìn)程A恢復(fù)運(yùn)行,當(dāng)A調(diào)用write時(shí),從其當(dāng)前偏移量1500處將數(shù)據(jù)寫入,將替換B剛寫入到該文件中的數(shù)據(jù)。

  問題出在邏輯操作“定位到文件尾端處,然后寫“使用了兩個(gè)分開的函數(shù)調(diào)用。解決辦法是使這兩個(gè)操作成為一個(gè)原子操作。O_APPEND標(biāo)識(shí),使內(nèi)核每次對(duì)文件進(jìn)行寫之前,都將進(jìn)程當(dāng)前偏移量設(shè)置到該文件的尾端處。

  2.pread和pwrite函數(shù)

  原子性地定位搜索和執(zhí)行I/0。

  代碼如下:

  #include 《unistd.h》

  ssize_t pread(int fd, void *buf, size_tcount, off_t offset);

  ssize_t pwrite(int fd, const void *buf,size_t count, off_t offset);

  ssize_t pread(int fd, void *buf, size_tcount, off_t offset);

  ssize_t pwrite(int fd, const void *buf,size_t count, off_t offset);

  dup和dup2函數(shù)

  代碼如下:

  #include 《unistd.h》

  int dup(int oldfd);

  int dup2(int oldfd, int newfd);

  上面兩個(gè)函數(shù)都可用來復(fù)制一個(gè)現(xiàn)存的文件描述符。

  由dup返回的新文件描述符一定是當(dāng)前可用文件描述符中的最小數(shù)值。用dup2則可以用newfd參數(shù)指定新描述符的數(shù)值。如果newfd已經(jīng)打開,則先將其關(guān)閉。如果newfd等于oldfd,則dup2返回newfd而不關(guān)閉它。

  假定我們的進(jìn)程執(zhí)行了:

  newfd = dup(1);

  當(dāng)此函數(shù)執(zhí)行時(shí),假設(shè)下一個(gè)可用的描述符是3。因?yàn)檫@兩個(gè)描述符指向同一個(gè)文件表項(xiàng),所以他們共享文件標(biāo)志以及同一文件偏移量。

  sync、fsync和fdatasync

  代碼如下:

  #include 《unistd.h》

  void sync(void);

  int fsync(int fd);

  int fdatasync(int fd);

  當(dāng)將數(shù)據(jù)寫入文件時(shí),內(nèi)核通常將數(shù)據(jù)復(fù)制到一個(gè)緩沖區(qū),直到緩沖區(qū)寫滿,再將緩沖區(qū)排路輸出隊(duì)列,然后等待其到達(dá)隊(duì)首,才進(jìn)行實(shí)際的I/O操作。這種輸出防暑被稱為延遲寫。延遲寫減少了磁盤的讀寫次數(shù),但卻降低了文件內(nèi)容的跟新速度。當(dāng)系統(tǒng)發(fā)生故障時(shí),延遲寫可能造成文件跟新內(nèi)容的丟失。為了保證磁盤上實(shí)際文件系統(tǒng)與緩沖區(qū)高速緩存中內(nèi)容一致性,UNIX系統(tǒng)提供了sync、fsync和fdatasync 三個(gè)函數(shù)。

  fcntl函數(shù)

  代碼如下:

  #include 《unistd.h》

  #include 《fcntl.h》

  int fcntl(int fd, int cmd, 。。。 /* arg */ );

  可以改變已經(jīng)打開文件的性質(zhì)。

  復(fù)制一個(gè)現(xiàn)有的描述符(cmd=F_DUPFD)

  獲得或設(shè)置文件描述符(cmd=F_GETFD|F_SETFD)

  獲得或設(shè)置文件狀態(tài)標(biāo)志(cmd=F_GETFL|F_SETFL)

  獲得或設(shè)置異步I/O所有權(quán)(cmd=F_GETOWN|F_SETOWN)

  獲得或設(shè)置記錄鎖(cmd=F_GETLK|F_SETLK、F_SETLKW)

  可以用fcntl函數(shù)設(shè)置文件狀態(tài),常用設(shè)置套接字描述符為非阻塞O_NONBLOCK

  ioctl函數(shù)

  #include 《sys/ioctl.h》

  int ioctl(int d, int request, 。。。);

  提供了一個(gè)用于控制設(shè)備及其描述符行為和配置底層服務(wù)的接口。

  /dev/fd

  打開文件/dev/fd/n等效于復(fù)制描述符n。

  上面就是Linux文件I/O的相關(guān)介紹了,通過這些介紹相信你已經(jīng)對(duì)文件I/O有了進(jìn)一步的了解,如果你還想了解更多的相關(guān)知識(shí)的話,不妨多多關(guān)注本網(wǎng)站吧。

標(biāo)簽 文件I/O

發(fā)表評(píng)論

0

沒有更多評(píng)論了

評(píng)論就這些咯,讓大家也知道你的獨(dú)特見解

立即評(píng)論

以上留言僅代表用戶個(gè)人觀點(diǎn),不代表系統(tǒng)之家立場(chǎng)

其他版本軟件

熱門教程

人氣教程排行

Linux系統(tǒng)推薦

官方交流群 軟件收錄