Linux中如何共享存儲

這篇文章主要為大家展示了“Linux中如何共享存儲”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“Linux中如何共享存儲”這篇文章吧。

創(chuàng)新互聯(lián)成立十余年來,這條路我們正越走越好,積累了技術(shù)與客戶資源,形成了良好的口碑。為客戶提供成都網(wǎng)站建設(shè)、成都做網(wǎng)站、網(wǎng)站策劃、網(wǎng)頁設(shè)計、主機域名、網(wǎng)絡(luò)營銷、VI設(shè)計、網(wǎng)站改版、漏洞修補等服務(wù)。網(wǎng)站是否美觀、功能強大、用戶體驗好、性價比高、打開快等等,這些對于網(wǎng)站建設(shè)都非常重要,創(chuàng)新互聯(lián)通過對建站技術(shù)性的掌握、對創(chuàng)意設(shè)計的研究為客戶提供一站式互聯(lián)網(wǎng)解決方案,攜手廣大客戶,共同發(fā)展進(jìn)步。

核心概念

進(jìn)程是運行著的程序,每個進(jìn)程都有著它自己的地址空間,這些空間由進(jìn)程被允許訪問的內(nèi)存地址組成。進(jìn)程有一個或多個執(zhí)行線程,而線程是一系列執(zhí)行指令的集合:單線程進(jìn)程就只有一個線程,而多線程的進(jìn)程則有多個線程。一個進(jìn)程中的線程共享各種資源,特別是地址空間。另外,一個進(jìn)程中的線程可以直接通過共享內(nèi)存來進(jìn)行通信,盡管某些現(xiàn)代語言(例如 Go)鼓勵一種更有序的方式,例如使用線程安全的通道。當(dāng)然對于不同的進(jìn)程,默認(rèn)情況下,它們能共享內(nèi)存。

有多種方法啟動之后要進(jìn)行通信的進(jìn)程,下面所舉的例子中主要使用了下面的兩種方法:

  • 一個終端被用來啟動一個進(jìn)程,另外一個不同的終端被用來啟動另一個。

  • 在一個進(jìn)程(父進(jìn)程)中調(diào)用系統(tǒng)函數(shù) fork,以此生發(fā)另一個進(jìn)程(子進(jìn)程)。

***個例子采用了上面使用終端的方法。這些代碼示例的 ZIP 壓縮包可以從我的網(wǎng)站下載到。

共享文件

程序員對文件訪問應(yīng)該都已經(jīng)很熟識了,包括許多坑(不存在的文件、文件權(quán)限損壞等等),這些問題困擾著程序?qū)ξ募氖褂?。盡管如此,共享文件可能是最為基礎(chǔ)的 IPC 機制了??紤]一下下面這樣一個相對簡單的例子,其中一個進(jìn)程(生產(chǎn)者 producer)創(chuàng)建和寫入一個文件,然后另一個進(jìn)程(消費者 consumer)從這個相同的文件中進(jìn)行讀取:

          writes +-----------+ readsproducer-------->| disk file |<-------consumer                 +-----------+

在使用這個 IPC 機制時最明顯的挑戰(zhàn)是競爭條件可能會發(fā)生:生產(chǎn)者和消費者可能恰好在同一時間訪問該文件,從而使得輸出結(jié)果不確定。為了避免競爭條件的發(fā)生,該文件在處于狀態(tài)時必須以某種方式處于被鎖狀態(tài),從而阻止在操作執(zhí)行時和其他操作的沖突。在標(biāo)準(zhǔn)系統(tǒng)庫中與鎖相關(guān)的 API 可以被總結(jié)如下:

  • 生產(chǎn)者應(yīng)該在寫入文件時獲得一個文件的排斥鎖。一個排斥鎖最多被一個進(jìn)程所擁有。這樣就可以排除掉競爭條件的發(fā)生,因為在鎖被釋放之前沒有其他的進(jìn)程可以訪問這個文件。

  • 消費者應(yīng)該在從文件中讀取內(nèi)容時得到至少一個共享鎖。多個讀取者可以同時保有一個共享鎖,但是沒有寫入者可以獲取到文件內(nèi)容,甚至在當(dāng)只有一個讀取者保有一個共享鎖時。

共享鎖可以提升效率。假如一個進(jìn)程只是讀入一個文件的內(nèi)容,而不去改變它的內(nèi)容,就沒有什么原因阻止其他進(jìn)程來做同樣的事。但如果需要寫入內(nèi)容,則很顯然需要文件有排斥鎖。

標(biāo)準(zhǔn)的 I/O 庫中包含一個名為 fcntl 的實用函數(shù),它可以被用來檢查或者操作一個文件上的排斥鎖和共享鎖。該函數(shù)通過一個文件描述符(一個在進(jìn)程中的非負(fù)整數(shù)值)來標(biāo)記一個文件(在不同的進(jìn)程中不同的文件描述符可能標(biāo)記同一個物理文件)。對于文件的鎖定, Linux 提供了名為 flock 的庫函數(shù),它是 fcntl 的一個精簡包裝。***個例子中使用 fcntl 函數(shù)來暴露這些 API 細(xì)節(jié)。

示例 1. 生產(chǎn)者程序
#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include <unistd.h> #define FileName "data.dat" void report_and_exit(const char* msg) {  [perror][4](msg);  [exit][5](-1); /* EXIT_FAILURE */} int main() {  struct flock lock;  lock.l_type = F_WRLCK;    /* read/write (exclusive) lock */  lock.l_whence = SEEK_SET; /* base for seek offsets */  lock.l_start = 0;         /* 1st byte in file */  lock.l_len = 0;           /* 0 here means 'until EOF' */  lock.l_pid = getpid();    /* process id */   int fd; /* file descriptor to identify a file within a process */  if ((fd = open(FileName, O_RDONLY)) < 0)  /* -1 signals an error */    report_and_exit("open to read failed...");   /* If the file is write-locked, we can't continue. */  fcntl(fd, F_GETLK, &lock); /* sets lock.l_type to F_UNLCK if no write lock */  if (lock.l_type != F_UNLCK)    report_and_exit("file is still write locked...");   lock.l_type = F_RDLCK; /* prevents any writing during the reading */  if (fcntl(fd, F_SETLK, &lock) < 0)    report_and_exit("can't get a read-only lock...");   /* Read the bytes (they happen to be ASCII codes) one at a time. */  int c; /* buffer for read bytes */  while (read(fd, &c, 1) > 0)    /* 0 signals EOF */    write(STDOUT_FILENO, &c, 1); /* write one byte to the standard output */   /* Release the lock explicitly. */  lock.l_type = F_UNLCK;  if (fcntl(fd, F_SETLK, &lock) < 0)    report_and_exit("explicit unlocking failed...");   close(fd);  return 0;}

上面生產(chǎn)者程序的主要步驟可以總結(jié)如下:

  • 這個程序首先聲明了一個類型為 struct flock 的變量,它代表一個鎖,并對它的 5 個域做了初始化。***個初始化


    使得這個鎖為排斥鎖(read-write)而不是一個共享鎖(read-only)。假如生產(chǎn)者獲得了這個鎖,則其他的進(jìn)程將不能夠?qū)ξ募鲎x或者寫操作,直到生產(chǎn)者釋放了這個鎖,或者顯式地調(diào)用 fcntl,又或者隱式地關(guān)閉這個文件。(當(dāng)進(jìn)程終止時,所有被它打開的文件都會被自動關(guān)閉,從而釋放了鎖)

    1. lock.l_type = F_WRLCK; /* exclusive lock */

  • 上面的程序接著初始化其他的域。主要的效果是整個文件都將被鎖上。但是,有關(guān)鎖的 API 允許特別指定的字節(jié)被上鎖。例如,假如文件包含多個文本記錄,則單個記錄(或者甚至一個記錄的一部分)可以被鎖,而其余部分不被鎖。

  • ***次調(diào)用 fcntl


    嘗試排斥性地將文件鎖住,并檢查調(diào)用是否成功。一般來說, fcntl 函數(shù)返回 -1 (因此小于 0)意味著失敗。第二個參數(shù) F_SETLK 意味著 fcntl 的調(diào)用不是堵塞的;函數(shù)立即做返回,要么獲得鎖,要么顯示失敗了。假如替換地使用 F_SETLKW(末尾的 W 代指等待),那么對 fcntl 的調(diào)用將是阻塞的,直到有可能獲得鎖的時候。在調(diào)用 fcntl 函數(shù)時,它的***個參數(shù) fd 指的是文件描述符,第二個參數(shù)指定了將要采取的動作(在這個例子中,F_SETLK 指代設(shè)置鎖),第三個參數(shù)為鎖結(jié)構(gòu)的地址(在本例中,指的是 &lock)。

    1. if (fcntl(fd, F_SETLK, &lock) < 0)

  • 假如生產(chǎn)者獲得了鎖,這個程序?qū)⑾蛭募懭雰蓚€文本記錄。

  • 在向文件寫入內(nèi)容后,生產(chǎn)者改變鎖結(jié)構(gòu)中的 l_type 域為 unlock 值:


    并調(diào)用 fcntl 來執(zhí)行解鎖操作。***程序關(guān)閉了文件并退出。

    1. lock.l_type = F_UNLCK;

示例 2. 消費者程序
#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include <unistd.h> #define FileName "data.dat" void report_and_exit(const char* msg) {  [perror][4](msg);  [exit][5](-1); /* EXIT_FAILURE */} int main() {  struct flock lock;  lock.l_type = F_WRLCK;    /* read/write (exclusive) lock */  lock.l_whence = SEEK_SET; /* base for seek offsets */  lock.l_start = 0;         /* 1st byte in file */  lock.l_len = 0;           /* 0 here means 'until EOF' */  lock.l_pid = getpid();    /* process id */   int fd; /* file descriptor to identify a file within a process */  if ((fd = open(FileName, O_RDONLY)) < 0)  /* -1 signals an error */    report_and_exit("open to read failed...");   /* If the file is write-locked, we can't continue. */  fcntl(fd, F_GETLK, &lock); /* sets lock.l_type to F_UNLCK if no write lock */  if (lock.l_type != F_UNLCK)    report_and_exit("file is still write locked...");   lock.l_type = F_RDLCK; /* prevents any writing during the reading */  if (fcntl(fd, F_SETLK, &lock) < 0)    report_and_exit("can't get a read-only lock...");   /* Read the bytes (they happen to be ASCII codes) one at a time. */  int c; /* buffer for read bytes */  while (read(fd, &c, 1) > 0)    /* 0 signals EOF */    write(STDOUT_FILENO, &c, 1); /* write one byte to the standard output */   /* Release the lock explicitly. */  lock.l_type = F_UNLCK;  if (fcntl(fd, F_SETLK, &lock) < 0)    report_and_exit("explicit unlocking failed...");   close(fd);  return 0;}

相比于鎖的 API,消費者程序會相對復(fù)雜一點兒。特別的,消費者程序首先檢查文件是否被排斥性的被鎖,然后才嘗試去獲得一個共享鎖。相關(guān)的代碼為:

lock.l_type = F_WRLCK;...fcntl(fd, F_GETLK, &lock); /* sets lock.l_type to F_UNLCK if no write lock */if (lock.l_type != F_UNLCK)  report_and_exit("file is still write locked...");

fcntl 調(diào)用中的 F_GETLK 操作指定檢查一個鎖,在本例中,上面代碼的聲明中給了一個 F_WRLCK 的排斥鎖。假如特指的鎖不存在,那么 fcntl 調(diào)用將會自動地改變鎖類型域為 F_UNLCK 以此來顯示當(dāng)前的狀態(tài)。假如文件是排斥性地被鎖,那么消費者將會終止。(一個更健壯的程序版本或許應(yīng)該讓消費者會兒,然后再嘗試幾次。)

假如當(dāng)前文件沒有被鎖,那么消費者將嘗試獲取一個共享(read-only)鎖(F_RDLCK)。為了縮短程序,fcntl 中的 F_GETLK 調(diào)用可以丟棄,因為假如其他進(jìn)程已經(jīng)保有一個讀寫鎖,F_RDLCK   的調(diào)用就可能會失敗。重新調(diào)用一個只讀鎖能夠阻止其他進(jìn)程向文件進(jìn)行寫的操作,但可以允許其他進(jìn)程對文件進(jìn)行讀取。簡而言之,共享鎖可以被多個進(jìn)程所保有。在獲取了一個共享鎖后,消費者程序?qū)⒘⒓磸奈募凶x取字節(jié)數(shù)據(jù),然后在標(biāo)準(zhǔn)輸出中打印這些字節(jié)的內(nèi)容,接著釋放鎖,關(guān)閉文件并終止。

下面的 % 為命令行提示符,下面展示的是從相同終端開啟這兩個程序的輸出:

% ./producerProcess 29255 has written to data file... % ./consumerNow is the winter of our discontentMade glorious summer by this sun of York

在本次的代碼示例中,通過 IPC  傳輸?shù)臄?shù)據(jù)是文本:它們來自莎士比亞的戲劇《理查三世》中的兩行臺詞。然而,共享文件的內(nèi)容還可以是紛繁復(fù)雜的,任意的字節(jié)數(shù)據(jù)(例如一個電影)都可以,這使得文件共享變成了一個非常靈活的  IPC 機制。但它的缺點是文件獲取速度較慢,因為文件的獲取涉及到讀或者寫。同往常一樣,編程總是伴隨著折中。下面的例子將通過共享內(nèi)存來做  IPC,而不是通過共享文件,在性能上相應(yīng)的有極大的提升。

共享內(nèi)存

對于共享內(nèi)存,Linux 系統(tǒng)提供了兩類不同的 API:傳統(tǒng)的 System V API 和更新一點的 POSIX  API。在單個應(yīng)用中,這些 API 不能混用。但是,POSIX  方式的一個壞處是它的特性仍在發(fā)展中,并且依賴于安裝的內(nèi)核版本,這非常影響代碼的可移植性。例如,默認(rèn)情況下,POSIX API 用內(nèi)存映射文件來實現(xiàn)共享內(nèi)存:對于一個共享的內(nèi)存段,系統(tǒng)為相應(yīng)的內(nèi)容維護一個備份文件。在 POSIX 規(guī)范下共享內(nèi)存可以被配置為不需要備份文件,但這可能會影響可移植性。我的例子中使用的是帶有備份文件的 POSIX API,這既結(jié)合了內(nèi)存獲取的速度優(yōu)勢,又獲得了文件存儲的持久性。

下面的共享內(nèi)存例子中包含兩個程序,分別名為 memwritermemreader,并使用信號量來調(diào)整它們對共享內(nèi)存的獲取。在任何時候當(dāng)共享內(nèi)存進(jìn)入一個寫入者場景時,無論是多進(jìn)程還是多線程,都有遇到基于內(nèi)存的競爭條件的風(fēng)險,所以,需要引入信號量來協(xié)調(diào)(同步)對共享內(nèi)存的獲取。

memwriter 程序應(yīng)當(dāng)在它自己所處的終端首先啟動,然后 memreader 程序才可以在它自己所處的終端啟動(在接著的十幾秒內(nèi))。memreader 的輸出如下:

This is the way the world ends...

在每個源程序的最上方注釋部分都解釋了在編譯它們時需要添加的鏈接參數(shù)。

首先讓我們復(fù)習(xí)一下信號量是如何作為一個同步機制工作的。一般的信號量也被叫做一個計數(shù)信號量,因為帶有一個可以增加的值(通常初始化為  0)。考慮一家租用自行車的商店,在它的庫存中有 100 輛自行車,還有一個供職員用于租賃的程序。每當(dāng)一輛自行車被租出去,信號量就增加  1;當(dāng)一輛自行車被還回來,信號量就減 1。在信號量的值為 100 之前都還可以進(jìn)行租賃業(yè)務(wù),但如果等于 100  時,就必須停止業(yè)務(wù),直到至少有一輛自行車被還回來,從而信號量減為 99。

二元信號量是一個特例,它只有兩個值:0 和 1。在這種情況下,信號量的表現(xiàn)為互斥量(一個互斥的構(gòu)造)。下面的共享內(nèi)存示例將把信號量用作互斥量。當(dāng)信號量的值為 0 時,只有 memwriter 可以獲取共享內(nèi)存,在寫操作完成后,這個進(jìn)程將增加信號量的值,從而允許 memreader 來讀取共享內(nèi)存。

示例 3. memwriter 進(jìn)程的源程序
/** Compilation: gcc -o memwriter memwriter.c -lrt -lpthread **/#include <stdio.h>#include <stdlib.h>#include <sys/mman.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <semaphore.h>#include <string.h>#include "shmem.h" void report_and_exit(const char* msg) {  [perror][4](msg);  [exit][5](-1);} int main() {  int fd = shm_open(BackingFile,      /* name from smem.h */            O_RDWR | O_CREAT, /* read/write, create if needed */            AccessPerms);     /* access permissions (0644) */  if (fd < 0) report_and_exit("Can't open shared mem segment...");   ftruncate(fd, ByteSize); /* get the bytes */   caddr_t memptr = mmap(NULL,       /* let system pick where to put segment */            ByteSize,   /* how many bytes */            PROT_READ | PROT_WRITE, /* access protections */            MAP_SHARED, /* mapping visible to other processes */            fd,         /* file descriptor */            0);         /* offset: start at 1st byte */  if ((caddr_t) -1  == memptr) report_and_exit("Can't get segment...");   [fprintf][7](stderr, "shared mem address: %p [0..%d]\n", memptr, ByteSize - 1);  [fprintf][7](stderr, "backing file:       /dev/shm%s\n", BackingFile );   /* semahore code to lock the shared mem */  sem_t* semptr = sem_open(SemaphoreName, /* name */               O_CREAT,       /* create the semaphore */               AccessPerms,   /* protection perms */               0);            /* initial value */  if (semptr == (void*) -1) report_and_exit("sem_open");   [strcpy][8](memptr, MemContents); /* copy some ASCII bytes to the segment */   /* increment the semaphore so that memreader can read */  if (sem_post(semptr) < 0) report_and_exit("sem_post");   sleep(12); /* give reader a chance */   /* clean up */  munmap(memptr, ByteSize); /* unmap the storage */  close(fd);  sem_close(semptr);  shm_unlink(BackingFile); /* unlink from the backing file */  return 0;}

下面是 memwritermemreader 程序如何通過共享內(nèi)存來通信的一個總結(jié):

  • 上面展示的 memwriter 程序調(diào)用 shm_open 函數(shù)來得到作為系統(tǒng)協(xié)調(diào)共享內(nèi)存的備份文件的文件描述符。此時,并沒有內(nèi)存被分配。接下來調(diào)用的是令人誤解的名為 ftruncate 的函數(shù)


    它將分配 ByteSize 字節(jié)的內(nèi)存,在該情況下,一般為大小適中的 512 字節(jié)。memwritermemreader 程序都只從共享內(nèi)存中獲取數(shù)據(jù),而不是從備份文件。系統(tǒng)將負(fù)責(zé)共享內(nèi)存和備份文件之間數(shù)據(jù)的同步。

    1. ftruncate(fd, ByteSize); /* get the bytes */

  • 接著 memwriter 調(diào)用 mmap 函數(shù):


    來獲得共享內(nèi)存的指針。(memreader 也做一次類似的調(diào)用。) 指針類型 caddr_tc 開頭,它代表 calloc,而這是動態(tài)初始化分配的內(nèi)存為 0 的一個系統(tǒng)函數(shù)。memwriter 通過庫函數(shù) strcpy(字符串復(fù)制)來獲取后續(xù)操作的 memptr。

    1. caddr_t memptr = mmap(NULL, /* let system pick where to put segment */

    2.                  ByteSize, /* how many bytes */

    3.                  PROT_READ | PROT_WRITE, /* access protections */

    4.                  MAP_SHARED, /* mapping visible to other processes */

    5.                  fd, /* file descriptor */

    6.                  0); /* offset: start at 1st byte */

  • 到現(xiàn)在為止,memwriter 已經(jīng)準(zhǔn)備好進(jìn)行寫操作了,但首先它要創(chuàng)建一個信號量來確保共享內(nèi)存的排斥性。假如 memwriter 正在執(zhí)行寫操作而同時 memreader 在執(zhí)行讀操作,則有可能出現(xiàn)競爭條件。假如調(diào)用 sem_open 成功了:


    那么,接著寫操作便可以執(zhí)行。上面的 SemaphoreName(任意一個唯一的非空名稱)用來在 memwritermemreader 識別信號量。初始值 0 將會傳遞給信號量的創(chuàng)建者,在這個例子中指的是 memwriter 賦予它執(zhí)行操作的權(quán)利。

    1. sem_t* semptr = sem_open(SemaphoreName, /* name */

    2.                     O_CREAT, /* create the semaphore */

    3.                     AccessPerms, /* protection perms */

    4.                     0); /* initial value */

  • 在寫操作完成后,memwriter* 通過調(diào)用sem_post` 函數(shù)將信號量的值增加到 1:


    增加信號了將釋放互斥鎖,使得 memreader 可以執(zhí)行它的操作。為了更好地測量,memwriter 也將從它自己的地址空間中取消映射,


    這將使得 memwriter 不能進(jìn)一步地訪問共享內(nèi)存。

    1. munmap(memptr, ByteSize); /* unmap the storage *

    1. if (sem_post(semptr) < 0) ..

示例 4. memreader 進(jìn)程的源代碼
/** Compilation: gcc -o memreader memreader.c -lrt -lpthread **/#include <stdio.h>#include <stdlib.h>#include <sys/mman.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <semaphore.h>#include <string.h>#include "shmem.h" void report_and_exit(const char* msg) {  [perror][4](msg);  [exit][5](-1);} int main() {  int fd = shm_open(BackingFile, O_RDWR, AccessPerms);  /* empty to begin */  if (fd < 0) report_and_exit("Can't get file descriptor...");   /* get a pointer to memory */  caddr_t memptr = mmap(NULL,       /* let system pick where to put segment */            ByteSize,   /* how many bytes */            PROT_READ | PROT_WRITE, /* access protections */            MAP_SHARED, /* mapping visible to other processes */            fd,         /* file descriptor */            0);         /* offset: start at 1st byte */  if ((caddr_t) -1 == memptr) report_and_exit("Can't access segment...");   /* create a semaphore for mutual exclusion */  sem_t* semptr = sem_open(SemaphoreName, /* name */               O_CREAT,       /* create the semaphore */               AccessPerms,   /* protection perms */               0);            /* initial value */  if (semptr == (void*) -1) report_and_exit("sem_open");   /* use semaphore as a mutex (lock) by waiting for writer to increment it */  if (!sem_wait(semptr)) { /* wait until semaphore != 0 */    int i;    for (i = 0; i < [strlen][6](MemContents); i++)      write(STDOUT_FILENO, memptr + i, 1); /* one byte at a time */    sem_post(semptr);  }   /* cleanup */  munmap(memptr, ByteSize);  close(fd);  sem_close(semptr);  unlink(BackingFile);  return 0;}

memwritermemreader 程序中,共享內(nèi)存的主要著重點都在 shm_openmmap 函數(shù)上:在成功時,***個調(diào)用返回一個備份文件的文件描述符,而第二個調(diào)用則使用這個文件描述符從共享內(nèi)存段中獲取一個指針。它們對 shm_open 的調(diào)用都很相似,除了 memwriter 程序創(chuàng)建共享內(nèi)存,而 `memreader 只獲取這個已經(jīng)創(chuàng)建的內(nèi)存:

int fd = shm_open(BackingFile, O_RDWR | O_CREAT, AccessPerms); /* memwriter */int fd = shm_open(BackingFile, O_RDWR, AccessPerms); /* memreader */

有了文件描述符,接著對 mmap 的調(diào)用就是類似的了:

caddr_t memptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

mmap 的***個參數(shù)為 NULL,這意味著讓系統(tǒng)自己決定在虛擬內(nèi)存地址的哪個地方分配內(nèi)存,當(dāng)然也可以指定一個地址(但很有技巧性)。MAP_SHARED 標(biāo)志著被分配的內(nèi)存在進(jìn)程中是共享的,***一個參數(shù)(在這個例子中為 0 ) 意味著共享內(nèi)存的偏移量應(yīng)該為***個字節(jié)。size 參數(shù)特別指定了將要分配的字節(jié)數(shù)目(在這個例子中是 512);另外的保護參數(shù)(AccessPerms)暗示著共享內(nèi)存是可讀可寫的。

當(dāng) memwriter 程序執(zhí)行成功后,系統(tǒng)將創(chuàng)建并維護備份文件,在我的系統(tǒng)中,該文件為 /dev/shm/shMemEx,其中的 shMemEx 是我為共享存儲命名的(在頭文件 shmem.h 中給定)。在當(dāng)前版本的 memwritermemreader 程序中,下面的語句

shm_unlink(BackingFile); /* removes backing file */

將會移除備份文件。假如沒有 unlink 這個語句,則備份文件在程序終止后仍然持久地保存著。

memreadermemwriter 一樣,在調(diào)用 sem_open 函數(shù)時,通過信號量的名字來獲取信號量。但 memreader 隨后將進(jìn)入等待狀態(tài),直到 memwriter 將初始值為 0 的信號量的值增加。

if (!sem_wait(semptr)) { /* wait until semaphore != 0 */

一旦等待結(jié)束,memreader 將從共享內(nèi)存中讀取 ASCII 數(shù)據(jù),然后做些清理工作并終止。

共享內(nèi)存 API 包括顯式地同步共享內(nèi)存段和備份文件。在這次的示例中,這些操作都被省略了,以免文章顯得雜亂,好讓我們專注于內(nèi)存共享和信號量的代碼。

即便在信號量代碼被移除的情況下,memwritermemreader 程序很大幾率也能夠正常執(zhí)行而不會引入競爭條件:memwriter 創(chuàng)建了共享內(nèi)存段,然后立即向它寫入;memreader 不能訪問共享內(nèi)存,直到共享內(nèi)存段被創(chuàng)建好。然而,當(dāng)一個寫操作處于混合狀態(tài)時,***實踐需要共享內(nèi)存被同步。信號量 API 足夠重要,值得在代碼示例中著重強調(diào)。


以上是“Linux中如何共享存儲”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!

標(biāo)題名稱:Linux中如何共享存儲
文章網(wǎng)址:http://www.muchs.cn/article20/ghgejo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供響應(yīng)式網(wǎng)站、建站公司、企業(yè)網(wǎng)站制作、App設(shè)計、網(wǎng)站策劃、外貿(mào)網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站建設(shè)