国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【Linux】System V 共享內(nèi)存、消息隊(duì)列、信號(hào)量

這篇具有很好參考價(jià)值的文章主要介紹了【Linux】System V 共享內(nèi)存、消息隊(duì)列、信號(hào)量。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

??作者:阿潤(rùn)菜菜
??專欄:Linux系統(tǒng)編程


system V共享內(nèi)存介紹

  1. System V 共享內(nèi)存是一種進(jìn)程間通信的機(jī)制,它允許多個(gè)進(jìn)程共享一塊物理內(nèi)存區(qū)域(稱為“段”)。System V 共享內(nèi)存的優(yōu)點(diǎn)是效率高,因?yàn)檫M(jìn)程之間不需要復(fù)制數(shù)據(jù);缺點(diǎn)是需要進(jìn)程之間進(jìn)行同步,以避免數(shù)據(jù)的不一致性
  2. 共享內(nèi)存區(qū)是最快的IPC形式。一旦這樣的內(nèi)存映射到共享它的進(jìn)程的地址空間,這些進(jìn)程間數(shù)據(jù)傳遞不再涉及到
    內(nèi)核,換句話說(shuō)是進(jìn)程不再通過(guò)執(zhí)行進(jìn)入內(nèi)核的系統(tǒng)調(diào)用來(lái)傳遞彼此的數(shù)據(jù)

示意圖:
【Linux】System V 共享內(nèi)存、消息隊(duì)列、信號(hào)量

理解共享內(nèi)存IPC

  1. 進(jìn)程憑什么獨(dú)立?每個(gè)進(jìn)程擁有自己獨(dú)立的進(jìn)程地址空間mm_struct,自己獨(dú)立的映射的物理內(nèi)存空間。進(jìn)程獨(dú)立性的實(shí)現(xiàn)主要依賴于操作系統(tǒng)和硬件的支持。操作系統(tǒng)通過(guò)為每個(gè)進(jìn)程分配獨(dú)立的虛擬地址空間,使得每個(gè)進(jìn)程都有自己的代碼和數(shù)據(jù)空間,這樣不會(huì)被其他進(jìn)程干擾。硬件通過(guò)內(nèi)存管理單元(MMU)來(lái)實(shí)現(xiàn)虛擬地址到物理地址的映射,以及分頁(yè)或分段的方式來(lái)劃分內(nèi)存空間。
  2. 操作系統(tǒng)還通過(guò)進(jìn)程調(diào)度算法來(lái)控制每個(gè)進(jìn)程的執(zhí)行順序和時(shí)間片,以及通過(guò)進(jìn)程同步和通信機(jī)制來(lái)協(xié)調(diào)多個(gè)進(jìn)程之間的關(guān)系。
  3. 實(shí)現(xiàn)進(jìn)程間通信的第一個(gè)前提就是如何讓不同的進(jìn)程看到同一份資源,匿名管道我們是通過(guò)子進(jìn)程繼承父進(jìn)程打開的資源,命名管道是通過(guò)兩個(gè)進(jìn)程都打開具有唯一性標(biāo)識(shí)的命名管道文件,而共享內(nèi)存其實(shí)是通過(guò)OS創(chuàng)建一塊shm(共享內(nèi)存塊),然后通過(guò)MMU將shm的地址分別映射到兩個(gè)進(jìn)程的各自地址空間當(dāng)中,那么兩個(gè)進(jìn)程就可以通過(guò)這份虛擬起始地址來(lái)進(jìn)行進(jìn)程間通信。
    在應(yīng)用層也就是用戶層,我們只能操作虛擬地址,但內(nèi)核中會(huì)有MMU進(jìn)行虛擬地址的映射,所以進(jìn)程在IPC時(shí),只需要操縱虛擬地址即可,從虛擬地址中讀取或向虛擬地址中進(jìn)行寫入,這樣就完成了共享內(nèi)存式的IPC。
  4. 所以通過(guò)讓不同的進(jìn)程,看到同一份物理內(nèi)存塊的方式,就叫做共享內(nèi)存!
  5. 為什么說(shuō)共享內(nèi)存是最快的IPC形式?
    共享內(nèi)存是一種進(jìn)程間通信(IPC)的方式,它允許多個(gè)進(jìn)程訪問(wèn)同一塊邏輯內(nèi)存,從而實(shí)現(xiàn)數(shù)據(jù)的快速交換共享內(nèi)存是最快的IPC形式,因?yàn)樗苊饬藬?shù)據(jù)在進(jìn)程間的復(fù)制,而是直接在內(nèi)存中讀寫。要使用共享內(nèi)存,需要用到一些函數(shù),如shmget, shmat, shmdt, shmctl等。這些函數(shù)可以創(chuàng)建、映射、分離、控制共享內(nèi)存段。共享內(nèi)存的優(yōu)點(diǎn)是高效和靈活,缺點(diǎn)是沒(méi)有提供同步機(jī)制,需要借助其他手段來(lái)實(shí)現(xiàn)進(jìn)程間的同步訪問(wèn),而且共享內(nèi)存沒(méi)有任何保護(hù)機(jī)制 那管道呢?系統(tǒng)接口有封裝。
    【Linux】System V 共享內(nèi)存、消息隊(duì)列、信號(hào)量

實(shí)現(xiàn)共享內(nèi)存IPC

認(rèn)識(shí)接口

命令查看 共享內(nèi)存是否已經(jīng)存在
ipcs -m 查看共享內(nèi)存
ipcrm -m 用于刪除共享內(nèi)存 — 注意使用shmid進(jìn)行刪除 類比于文件描述符

System V 共享內(nèi)存的API包括以下幾個(gè)系統(tǒng)調(diào)用:

  • shmget(2):創(chuàng)建一個(gè)新的段或獲取一個(gè)已存在的段的標(biāo)識(shí)符(ID)。這個(gè)ID是用來(lái)在其他API中引用段的。
  • shmat(2):將一個(gè)已存在的段映射到調(diào)用進(jìn)程的虛擬地址空間中。這樣,進(jìn)程就可以通過(guò)指針來(lái)訪問(wèn)共享內(nèi)存中的數(shù)據(jù)。
  • shmdt(2):將一個(gè)段從調(diào)用進(jìn)程的虛擬地址空間中解除映射。這樣,進(jìn)程就不能再訪問(wèn)共享內(nèi)存中的數(shù)據(jù)。
  • shmctl(2):對(duì)一個(gè)段進(jìn)行控制操作,例如修改它的權(quán)限、獲取它的狀態(tài)信息、刪除它等。

1.shmget()函數(shù)是用來(lái)創(chuàng)建或打開一塊共享內(nèi)存的,它的原型是int shmget (key_t key, size_t size, int shmflg);

第一個(gè)參數(shù)key是一個(gè)非零整數(shù),它為共享內(nèi)存段提供一個(gè)外部名,可以用IPC_PRIVATE或ftok()函數(shù)生成。shmget()函數(shù)成功時(shí)返回一個(gè)與key相關(guān)的共享內(nèi)存標(biāo)識(shí)符(非負(fù)整數(shù)),用于后續(xù)的共享內(nèi)存函數(shù)。調(diào)用失敗返回-1。

第二個(gè)參數(shù)size是以字節(jié)為單位指定需要共享的內(nèi)存容量。所有的內(nèi)存分配操作都是以頁(yè)為單位的,所以如果申請(qǐng)的內(nèi)存大小不是頁(yè)的整數(shù)倍,會(huì)被向上取整到最近的頁(yè)大小。

第三個(gè)參數(shù)shmflg是一組標(biāo)志位,它可以指定權(quán)限標(biāo)志、創(chuàng)建標(biāo)志和排他標(biāo)志。權(quán)限標(biāo)志與文件的讀寫權(quán)限一樣,如0644表示允許創(chuàng)建者讀寫,其他用戶只讀。創(chuàng)建標(biāo)志IPC_CREAT表示如果共享內(nèi)存不存在,則創(chuàng)建一個(gè)新的共享內(nèi)存,否則打開已有的共享內(nèi)存。排他標(biāo)志IPC_EXCL表示只有在共享內(nèi)存不存在時(shí),才創(chuàng)建新的共享內(nèi)存,否則返回錯(cuò)誤。

共享內(nèi)存的大小是以4kb為單位的,這是巧合嗎?是這樣的(對(duì)應(yīng)磁盤文件系統(tǒng)):這里第二個(gè)參數(shù)是共享內(nèi)存的大小,一般建議將開辟的共享內(nèi)存大小設(shè)置為4KB的整數(shù)倍,內(nèi)存劃分內(nèi)存塊的基本單位是Page,大小剛好是4KB,所以建議將大小設(shè)置為4KB的整數(shù)倍,如果你設(shè)置成4097什么的,有點(diǎn)浪費(fèi)內(nèi)存,因?yàn)閷?shí)際內(nèi)核會(huì)開辟8KB大小的空間。

2.shmat()函數(shù)用來(lái)將共享內(nèi)存段連接到進(jìn)程的地址空間,它的原型是void * shmat (int shmid, const void *shmaddr, int shmflg);

第一個(gè)參數(shù)shmid是由shmget()函數(shù)返回的共享內(nèi)存標(biāo)識(shí)符。第二個(gè)參數(shù)shmaddr指定共享內(nèi)存連接到當(dāng)前進(jìn)程中的地址位置,通常為NULL,表示讓系統(tǒng)來(lái)選擇共享內(nèi)存的地址。第三個(gè)參數(shù)shmflg是一組標(biāo)志位,可以指定SHM_RDONLY表示共享內(nèi)存只讀,或者默認(rèn)為0表示可讀可寫。調(diào)用成功時(shí)返回一個(gè)指向共享內(nèi)存第一個(gè)字節(jié)的指針,如果調(diào)用失敗返回-1。

3.shmdt()函數(shù)用來(lái)將共享內(nèi)存從當(dāng)前進(jìn)程中分離,它的原型是int shmdt (const void *shmaddr);

參數(shù)shmaddr是shmat()函數(shù)返回的地址指針,調(diào)用成功時(shí)返回0,失敗時(shí)返回-1。注意,將共享內(nèi)存分離并不是刪除它,只是使該共享內(nèi)存對(duì)當(dāng)前進(jìn)程不再可用。

4.shmctl()函數(shù)用來(lái)控制共享內(nèi)存的狀態(tài),它的原型是int shmctl (int shmid, int command, struct shmid_ds *buf);

第一個(gè)參數(shù)shmid是shmget()函數(shù)返回的共享內(nèi)存標(biāo)識(shí)符。第二個(gè)參數(shù)command是要采取的操作,可以取以下三個(gè)值:

IPC_STAT:把shmid_ds結(jié)構(gòu)中的數(shù)據(jù)設(shè)置為共享內(nèi)存的當(dāng)前關(guān)聯(lián)值,即用共享內(nèi)存的當(dāng)前關(guān)聯(lián)值覆蓋shmid_ds的值。

IPC_SET:如果進(jìn)程有足夠的權(quán)限,就把共享內(nèi)存的當(dāng)前關(guān)聯(lián)值設(shè)置為shmid_ds結(jié)構(gòu)中給出的值。

IPC_RMID:刪除共享內(nèi)存段。

第三個(gè)參數(shù)buf是一個(gè)結(jié)構(gòu)指針,它指向共享內(nèi)存模式和訪問(wèn)權(quán)限的結(jié)構(gòu)。調(diào)用成功時(shí)返回0,失敗時(shí)返回-1。

代碼實(shí)現(xiàn)

下面是一個(gè)使用System V 共享內(nèi)存的示例程序,它由兩個(gè)部分組成:writer.c和reader.c。writer.c負(fù)責(zé)創(chuàng)建一個(gè)共享內(nèi)存段,并向其中寫入一些字符串;reader.c負(fù)責(zé)讀取共享內(nèi)存段中的字符串,并打印出來(lái)。

writer.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>

#define SHM_SIZE 1024 // size of shared memory

int main() {
    int shmid; // shared memory ID
    key_t key; // key to locate shared memory
    char *shm; // pointer to shared memory

    // create a key using a file name and a char
    if ((key = ftok("writer.c", 'A')) == -1) {
        perror("ftok");
        exit(1);
    }

    // create a shared memory segment
    if ((shmid = shmget(key, SHM_SIZE, IPC_CREAT | 0666)) == -1) {
        perror("shmget");
        exit(1);
    }

    // attach the shared memory segment to the process
    if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
        perror("shmat");
        exit(1);
    }

    // write some strings to the shared memory
    strcpy(shm, "Hello, world!");
    shm += strlen("Hello, world!");
    strcpy(shm, "This is an example of System V shared memory.");
    shm += strlen("This is an example of System V shared memory.");
    strcpy(shm, "Goodbye!");

    // wait until reader finishes reading
    while (*shm != '*')
        sleep(1);

    // detach the shared memory segment from the process
    if (shmdt(shm) == -1) {
        perror("shmdt");
        exit(1);
    }

    return 0;
}

reader.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>

#define SHM_SIZE 1024 // size of shared memory

int main() {
    int shmid; // shared memory ID
    key_t key; // key to locate shared memory
    char *shm; // pointer to shared memory
    char *s;   // pointer to traverse shared memory

    // create a key using a file name and a char
    if ((key = ftok("writer.c", 'A')) == -1) {
        perror("ftok");
        exit(1);
    }

    // get the shared memory segment
    if ((shmid = shmget(key, SHM_SIZE, 0)) == -1) {
        perror("shmget");
        exit(1);
    }

    // attach the shared memory segment to the process
    if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
        perror("shmat");
        exit(1);
    }

    // read the strings from the shared memory
    s = shm;
    while (*s != '\0') {
        printf("%s\n", s);
        s += strlen(s) + 1;
    }

    // write a '*' to the shared memory to indicate reading is done
    *shm = '*';

    // detach the shared memory segment from the process
    if (shmdt(shm) == -1) {
        perror("shmdt");
        exit(1);
    }

    return 0;
}

為了運(yùn)行這個(gè)示例程序,我們需要先編譯writer.c和reader.c,然后先運(yùn)行writer,再運(yùn)行reader。運(yùn)行結(jié)果如下:

$ gcc writer.c -o writer
$ gcc reader.c -o reader
$ ./writer &
[1] 1234
$ ./reader
Hello, world!
This is an example of System V shared memory.
Goodbye!
[1]+  Done                    ./writer
$

實(shí)現(xiàn)共享內(nèi)存服務(wù)端和客戶端的通信:查看我的代碼倉(cāng)庫(kù)

補(bǔ)充知識(shí) — 命令操作

ipcs 查看進(jìn)程間通信資源/ipcrm 刪除進(jìn)程間通信資源

  -m 針對(duì)共享內(nèi)存的操作

 -q	針對(duì)消息隊(duì)列的操作
 
-s	針對(duì)信號(hào)量的操作

-a	針對(duì)所有資源的操作

深入理解

什么是同步與互斥

  • 同步是指協(xié)調(diào)多個(gè)進(jìn)程的執(zhí)行順序,使得某些進(jìn)程在執(zhí)行某些操作之前必須等待其他進(jìn)程完成一些操作。例如,一個(gè)進(jìn)程要讀取一個(gè)文件,必須等待另一個(gè)進(jìn)程寫入該文件。
  • 互斥是指保證多個(gè)進(jìn)程對(duì)共享資源的訪問(wèn)不會(huì)發(fā)生沖突,使得某些資源在一個(gè)時(shí)間段內(nèi)只能被一個(gè)進(jìn)程使用。例如,一個(gè)進(jìn)程要打印一份文檔,必須等待打印機(jī)空閑。

OS中常用的同步與互斥機(jī)制有:

  • 信號(hào)量與PV操作:信號(hào)量是一個(gè)整數(shù)變量,表示可用資源的數(shù)量。PV操作是兩個(gè)原子操作,用于對(duì)信號(hào)量進(jìn)行加減操作。P操作表示申請(qǐng)一個(gè)資源,如果資源不足則阻塞;V操作表示釋放一個(gè)資源,如果有等待的進(jìn)程則喚醒。
  • 管程:管程是一種高級(jí)的同步機(jī)制,它是一種封裝了共享數(shù)據(jù)和對(duì)數(shù)據(jù)操作的過(guò)程的數(shù)據(jù)結(jié)構(gòu)。管程內(nèi)部有一個(gè)互斥鎖和若干條件變量,用于實(shí)現(xiàn)對(duì)共享數(shù)據(jù)的互斥訪問(wèn)和同步控制。

本節(jié)介紹互斥的四個(gè)相關(guān)概念 :

【Linux】System V 共享內(nèi)存、消息隊(duì)列、信號(hào)量

  1. 什么是臨界資源?
  • 臨界資源是指一次僅允許一個(gè)進(jìn)程使用的共享資源,如打印機(jī)、磁帶機(jī)等。臨界資源需要互斥訪問(wèn),即同一時(shí)間只能有一個(gè)進(jìn)程訪問(wèn),否則會(huì)導(dǎo)致數(shù)據(jù)不一致或資源沖突。
  • 臨界區(qū)是指每個(gè)進(jìn)程中訪問(wèn)臨界資源的那段代碼,如對(duì)打印機(jī)的操作。臨界區(qū)需要設(shè)置進(jìn)入?yún)^(qū)和退出區(qū),以檢查和控制對(duì)臨界資源的訪問(wèn)。進(jìn)入?yún)^(qū)要判斷是否可以進(jìn)入臨界區(qū),如果可以則設(shè)置標(biāo)志或鎖;退出區(qū)要釋放標(biāo)志或鎖,以便其他進(jìn)程可以進(jìn)入。

2.什么是原子性?

  • 原子性是指一個(gè)操作或一組操作要么全部執(zhí)行成功,要么全部不執(zhí)行,不會(huì)被其他進(jìn)程或中斷打斷。原子性是實(shí)現(xiàn)臨界區(qū)互斥的一個(gè)重要條件,因?yàn)槿绻谶M(jìn)入?yún)^(qū)或退出區(qū)被打斷,就會(huì)導(dǎo)致死鎖或饑餓等問(wèn)題。原子性可以通過(guò)硬件指令或軟件方法來(lái)實(shí)現(xiàn)。

共享內(nèi)存的內(nèi)核數(shù)據(jù)結(jié)構(gòu)

下面是OS給用戶暴露的一部分shm的內(nèi)核數(shù)據(jù)結(jié)構(gòu),因?yàn)镺S要進(jìn)行管理,所以實(shí)際在底層中其結(jié)構(gòu)更為復(fù)雜,里面的key被封裝到ipc_perm結(jié)構(gòu)體里面,ipc_perm又被封裝到shmid_ds{}結(jié)構(gòu)體內(nèi)部。

【Linux】System V 共享內(nèi)存、消息隊(duì)列、信號(hào)量
內(nèi)核中的ipc_perm結(jié)構(gòu)體是用來(lái)描述IPC對(duì)象的權(quán)限和所有者的
它的定義如下:

struct ipc_perm {
    key_t key; // 調(diào)用shmget()時(shí)給出的關(guān)鍵字
    uid_t uid; // 共享內(nèi)存所有者的有效用戶ID
    gid_t gid; // 共享內(nèi)存所有者所屬組的有效組ID
    uid_t cuid; // 共享內(nèi)存創(chuàng)建者的有效用戶ID
    gid_t cgid; // 共享內(nèi)存創(chuàng)建者所屬組的有效組ID
    unsigned short mode; // 權(quán)限 + SHM_DEST和SHM_LOCKED標(biāo)志
    unsigned short seq; // 序列號(hào)
};

結(jié)構(gòu)中的mode域類似于文件的stat結(jié)構(gòu)的mode域,但是不可以有執(zhí)行權(quán)限。mode值描述如下:

操作者 寫(更改 更新)
用戶 0400 0200
0040 0020
其他 0004 0002

IPC對(duì)象包括共享內(nèi)存、消息隊(duì)列和信號(hào)量,它們都是用來(lái)進(jìn)行進(jìn)程通信的一些資源。
IPC對(duì)象的創(chuàng)建、訪問(wèn)和控制都需要使用ipc_perm結(jié)構(gòu)體中信息

IPC資源的組織方式(多態(tài))

對(duì)于System V標(biāo)準(zhǔn)的IPC資源組織方式來(lái)說(shuō),資源的獲取與釋放操作,他們的接口相似度非常高,
所以O(shè)S要對(duì)這些同一標(biāo)準(zhǔn)的各個(gè)通信機(jī)制進(jìn)行管理,他們都有各自的內(nèi)核數(shù)據(jù)結(jié)構(gòu),但都非常的相似,OS系統(tǒng)可以通過(guò)數(shù)組的方式對(duì)這些System V標(biāo)準(zhǔn)的IPC資源進(jìn)行管理。

結(jié)構(gòu)體的第一個(gè)成員地址,在數(shù)字上和結(jié)構(gòu)體對(duì)象本身的地址是相同的。雖然他們類型不同,但是地址的字面值是相同的,所以我們可以只存儲(chǔ)這些內(nèi)核數(shù)據(jù)結(jié)構(gòu)的第一個(gè)字段的地址,用一個(gè)指針數(shù)組來(lái)進(jìn)行存儲(chǔ),因?yàn)殡m然這些IPC資源的內(nèi)核數(shù)據(jù)結(jié)構(gòu)不同,但是他們的第一個(gè)字段的類型都是相同的,都是struct ipc_perm,所以我們可以用指針數(shù)組來(lái)進(jìn)行管理。
當(dāng)要訪問(wèn)具體的某個(gè)IPC資源的內(nèi)核數(shù)據(jù)結(jié)構(gòu)時(shí),我們可以將數(shù)組中的內(nèi)容拿出來(lái),將其強(qiáng)轉(zhuǎn)成對(duì)應(yīng)的IPC資源內(nèi)核數(shù)據(jù)結(jié)構(gòu)的類型,也就是轉(zhuǎn)成結(jié)構(gòu)體類型,那么此時(shí)這個(gè)指針指向的就不再是struct ipc_perm類型的結(jié)構(gòu)體了,而是變?yōu)閟truct shmid_ds或struct semid_ds或struct msqid_ds這幾種IPC內(nèi)核數(shù)據(jù)結(jié)構(gòu)類型的結(jié)構(gòu)體,此時(shí)我們就可以具體的訪問(wèn)某個(gè)IPC資源了。
上面能夠這么做的原因其實(shí)是因?yàn)?,結(jié)構(gòu)體的地址和結(jié)構(gòu)體中第一個(gè)字段的地址 在字面值上是相同的,只是他們類型不同罷了,我們可以通過(guò)類型強(qiáng)轉(zhuǎn)的方式,讓指針指向不同的結(jié)構(gòu)體。
3.
下面組織IPC資源的方式不就是多態(tài)嗎?右邊三個(gè)資源就是派生類,左邊是存儲(chǔ)基類指針的指針數(shù)組,基類指針指向哪個(gè)派生類結(jié)構(gòu)體,就調(diào)用哪個(gè)派生類結(jié)構(gòu)體里的方法成員,只不過(guò)在Linux這里是通過(guò)指針類型強(qiáng)轉(zhuǎn)的方式來(lái)實(shí)現(xiàn)的。
【Linux】System V 共享內(nèi)存、消息隊(duì)列、信號(hào)量

共享內(nèi)存的優(yōu)點(diǎn)和缺點(diǎn)(管道和shm分別數(shù)據(jù)拷貝次數(shù))

共享內(nèi)存的優(yōu)點(diǎn):所有進(jìn)程間通信中速度最快的,只要向shmat返回的虛擬地址寫入數(shù)據(jù),另一個(gè)進(jìn)程直接就可以通過(guò)他自己的shmat返回的虛擬地址讀取到共享內(nèi)存中的數(shù)據(jù),效率非常的高,因?yàn)楣蚕韮?nèi)存能大大減少數(shù)據(jù)的拷貝次數(shù)。

綜合考慮管道和共享內(nèi)存,考慮鍵盤輸入和顯示器輸出,管道和共享內(nèi)存分別有幾次數(shù)據(jù)拷貝呢?如果細(xì)算的話其實(shí)是6次和4次,如果不細(xì)算的話是4次和2次。
有一種說(shuō)法,喜歡把緩沖區(qū)分為內(nèi)核緩沖區(qū)和程序緩沖區(qū),程序緩沖區(qū)指的是語(yǔ)言級(jí)別你所能見到的所有能夠存放數(shù)據(jù)的空間,這些都可以叫做程序緩沖區(qū),是一種籠統(tǒng)的叫法。
管道由于要調(diào)用read和write接口,則必須定義buffer,在讀端和寫端分別都定義出一個(gè)buffer,實(shí)際數(shù)據(jù)會(huì)先從stdin到buffer里面,再?gòu)腷uffer到pipe的內(nèi)核級(jí)緩沖區(qū)中,然后再?gòu)膬?nèi)核級(jí)緩沖區(qū)到讀端的buffer中,最后再?gòu)淖x端的buffer拷貝到stdout的用戶級(jí)緩沖區(qū),這樣算就是4次。
共享內(nèi)存無(wú)須調(diào)用read或write接口,shmat會(huì)直接返回虛擬地址,所以只需將stdin的數(shù)據(jù)拷貝到虛擬地址里面,然后MMU會(huì)將虛擬地址進(jìn)行映射,另一端的進(jìn)程可以直接通過(guò)虛擬地址看到左邊進(jìn)程映射到shm的數(shù)據(jù),所以另一端進(jìn)程也只需要將虛擬地址的數(shù)據(jù)拷貝到stdout的緩沖區(qū)即可,這樣算就是2次。
但我們知道鍵盤輸入的緩沖區(qū)實(shí)際上是先到內(nèi)核標(biāo)準(zhǔn)輸入緩沖區(qū)中的,cin或scanf等標(biāo)準(zhǔn)輸入都是從內(nèi)核標(biāo)準(zhǔn)輸入緩沖區(qū)中拿數(shù)據(jù)的。并且在輸出時(shí),printf或cout等標(biāo)準(zhǔn)輸出其實(shí)是先將數(shù)據(jù)輸出到內(nèi)核標(biāo)準(zhǔn)輸出緩沖區(qū)的,然后才是將數(shù)據(jù)輸出到stdout也就是顯示器文件內(nèi)部的用戶級(jí)緩沖區(qū)。所以如果把這兩步考慮上,那么管道和共享內(nèi)存將各自增加兩次的數(shù)據(jù)拷貝。
【Linux】System V 共享內(nèi)存、消息隊(duì)列、信號(hào)量

認(rèn)識(shí)信號(hào)量

現(xiàn)實(shí)生活中,我們?cè)诳措娪爸?,一定要先買票,看電影,看完走人。
在OS內(nèi)部訪問(wèn)臨界資源:一定要先申請(qǐng)信號(hào)量資源,在使用,然后釋放信號(hào)量資源 。
信號(hào)量的本質(zhì)是一個(gè)計(jì)數(shù)器,通常用來(lái)表示公共資源中,資源數(shù)量多少的問(wèn)題。當(dāng)訪問(wèn)沒(méi)有保護(hù)的公共資源時(shí),會(huì)產(chǎn)生數(shù)據(jù)不一致的問(wèn)題,我們將被保護(hù)起來(lái)的公共資源稱為臨界資源,但大部分資源其實(shí)都是獨(dú)立的。公共資源(內(nèi)存,文件,網(wǎng)絡(luò)等)都是要通過(guò)代碼來(lái)進(jìn)行訪問(wèn)的,這些代碼我們稱為臨界區(qū),其余未訪問(wèn)公共資源的代碼稱為非臨界區(qū)。

當(dāng)信號(hào)量為0時(shí)(count),OS掛起阻塞進(jìn)程。那么是誰(shuí)在申請(qǐng)信號(hào)量? 進(jìn)程在申請(qǐng)!那前提就是 所有進(jìn)程都要看到同一塊信號(hào)量?。?那就得是共享資源,必須保證自己的++ 操作 — 是原子性的

只要訪問(wèn)公共資源,我們就必須對(duì)公共資源進(jìn)行保護(hù)。所有的進(jìn)程在訪問(wèn)公共資源之前,都必須申請(qǐng)sem信號(hào)量,申請(qǐng)sem信號(hào)量不就需要先看到同一份sem信號(hào)量嗎?那么其實(shí)sem信號(hào)量本身就是公共資源,所以信號(hào)量也必須保證自身操作的安全性,那么信號(hào)量的++或- -等操作也都必須得是原子性的,要么做成功,要么就回到最初狀態(tài)
【Linux】System V 共享內(nèi)存、消息隊(duì)列、信號(hào)量

System V 消息隊(duì)列

1.消息隊(duì)列提供了一個(gè)從一個(gè)進(jìn)程向另外一個(gè)進(jìn)程發(fā)送一塊數(shù)據(jù)的方法

2.每個(gè)數(shù)據(jù)塊都被認(rèn)為是有一個(gè)類型,接收者進(jìn)程接收的數(shù)據(jù)塊可以有不同的類型值

3.IPC資源必須刪除,否則不會(huì)自動(dòng)清除,除非重啟,所以system V IPC資源的生命周期隨內(nèi)核

內(nèi)核也給我們提供了獲取消息隊(duì)列和控制消息隊(duì)列的系統(tǒng)接口
【Linux】System V 共享內(nèi)存、消息隊(duì)列、信號(hào)量文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-444833.html

到了這里,關(guān)于【Linux】System V 共享內(nèi)存、消息隊(duì)列、信號(hào)量的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【Linux】進(jìn)程間通信 --- 管道 共享內(nèi)存 消息隊(duì)列 信號(hào)量

    【Linux】進(jìn)程間通信 --- 管道 共享內(nèi)存 消息隊(duì)列 信號(hào)量

    等明年國(guó)慶去西藏洗滌靈魂,laozi不伺候這無(wú)聊的生活了 1. 通過(guò)之前的學(xué)習(xí)我們知道,每個(gè)進(jìn)程都有自己獨(dú)立的內(nèi)核數(shù)據(jù)結(jié)構(gòu),例如PCB,頁(yè)表,物理內(nèi)存塊,mm_struct,所以具有獨(dú)立性的進(jìn)程之間如果想要通信的話,成本一定是不低的。 2. a.數(shù)據(jù)傳輸:一個(gè)進(jìn)程需要將它的數(shù)據(jù)

    2023年04月17日
    瀏覽(27)
  • Linux進(jìn)程間通信【消息隊(duì)列、信號(hào)量】

    Linux進(jìn)程間通信【消息隊(duì)列、信號(hào)量】

    ?個(gè)人主頁(yè): 北 海 ??所屬專欄: Linux學(xué)習(xí)之旅 ??操作環(huán)境: CentOS 7.6 阿里云遠(yuǎn)程服務(wù)器 在 System V 通信標(biāo)準(zhǔn)中,還有一種通信方式: 消息隊(duì)列 ,以及一種實(shí)現(xiàn)互斥的工具: 信號(hào)量 ;隨著時(shí)代的發(fā)展,這些陳舊的標(biāo)準(zhǔn)都已經(jīng)較少使用了,但作為 IPC 中的經(jīng)典知識(shí),我們可

    2024年02月08日
    瀏覽(31)
  • linux中互斥鎖,自旋鎖,條件變量,信號(hào)量,與freeRTOS中的消息隊(duì)列,信號(hào)量,互斥量,事件的區(qū)別

    linux中互斥鎖,自旋鎖,條件變量,信號(hào)量,與freeRTOS中的消息隊(duì)列,信號(hào)量,互斥量,事件的區(qū)別

    對(duì)于目前主流的RTOS的任務(wù),大部分都屬于并發(fā)的線程。 因?yàn)镸CU上的資源每個(gè)任務(wù)都是共享的,可以認(rèn)為是單進(jìn)程多線程模型。 【freertos】003-任務(wù)基礎(chǔ)知識(shí) 在沒(méi)有操作系統(tǒng)的時(shí)候兩個(gè)應(yīng)用程序進(jìn)行消息傳遞一般使用全局變量的方式,但是如果在使用操作系統(tǒng)的應(yīng)用中用全局變

    2024年02月11日
    瀏覽(26)
  • 【STM32】FreeRTOS消息隊(duì)列和信號(hào)量學(xué)習(xí)

    【STM32】FreeRTOS消息隊(duì)列和信號(hào)量學(xué)習(xí)

    一、消息隊(duì)列(queue) 隊(duì)列是一種用于實(shí)現(xiàn)任務(wù)與任務(wù)之間,任務(wù)與中斷之間消息交流的機(jī)制。 注意:1.數(shù)據(jù)的操作是FIFO模式。 2.隊(duì)列需要明確數(shù)據(jù)的大小和隊(duì)列的長(zhǎng)度。 3.寫和讀都會(huì)出現(xiàn)堵塞。 實(shí)驗(yàn):創(chuàng)建一個(gè)消息隊(duì)列,兩個(gè)發(fā)送任務(wù),一個(gè)接收任務(wù)。 其中任務(wù)一任務(wù)三

    2024年02月13日
    瀏覽(17)
  • 學(xué)習(xí)系統(tǒng)編程N(yùn)o.22【消息隊(duì)列和信號(hào)量】

    學(xué)習(xí)系統(tǒng)編程N(yùn)o.22【消息隊(duì)列和信號(hào)量】

    北京時(shí)間:2023/4/20/7:48,鬧鐘6點(diǎn)和6點(diǎn)30,全部錯(cuò)過(guò),根本起不來(lái),可能是因?yàn)楦忻斑€沒(méi)好,睡不夠吧!并且今天是星期四,這個(gè)星期這是第二篇博客,作為一個(gè)日更選手,少些了兩篇博客,充分?jǐn)[爛,但是擺爛具體也是有原因的,星期一的時(shí)候莫名高燒,頭昏腦漲的感覺(jué),睡

    2023年04月27日
    瀏覽(16)
  • linux(system V標(biāo)準(zhǔn))信號(hào)量

    linux(system V標(biāo)準(zhǔn))信號(hào)量

    目錄: ??????????? 1.什么是信號(hào)量 ??????????? 2.信號(hào)量的本質(zhì) 1.什么是信號(hào)量 ? 2.信號(hào)量的本質(zhì) ?什么是臨界資源呢?? 凡是倍多個(gè)執(zhí)行流同時(shí)訪問(wèn)的資源就是臨界資源?。?! 我們看一個(gè)問(wèn)題,我們fork()之后創(chuàng)建一個(gè)子進(jìn)程,那么我們的全局變量,是不是我們父

    2024年02月07日
    瀏覽(28)
  • 【C++】Windows下共享內(nèi)存加信號(hào)量實(shí)現(xiàn)進(jìn)程間同步通信

    【C++】Windows下共享內(nèi)存加信號(hào)量實(shí)現(xiàn)進(jìn)程間同步通信

    目錄 一,函數(shù)清單 1.CreateFileMapping?方法 2.OpenFileMapping?方法 3.MapViewOfFile?方法 4.UnmapViewOfFile?方法 5.CreateSemaphore?方法 6.?OpenSemaphore?方法 7.WaitForSingleObject?方法 8.ReleaseSemaphore?方法 9.CloseHandle?方法 10.GetLastError?方法 二,單共享內(nèi)存單信號(hào)量-進(jìn)程間單向通信 共享內(nèi)存管理文

    2024年02月08日
    瀏覽(24)
  • 【Linux】進(jìn)程間通信——System V信號(hào)量

    【Linux】進(jìn)程間通信——System V信號(hào)量

    目錄 寫在前面的話 一些概念的理解 信號(hào)量的引入 信號(hào)量的概念及使用 ? ???????? System V信號(hào)量是一種較低級(jí)的IPC機(jī)制 ,使用的時(shí)候需要手動(dòng)進(jìn)行操作和同步。在現(xiàn)代操作系統(tǒng)中,更常用的是 POSIX信號(hào)量 (通過(guò) sem_* 系列的函數(shù)進(jìn)行操作)或更高級(jí)的同步原語(yǔ)(如互斥鎖

    2024年02月11日
    瀏覽(20)
  • 【設(shè)計(jì)模式】C語(yǔ)言使用共享內(nèi)存和信號(hào)量,完美實(shí)現(xiàn)生產(chǎn)者與消費(fèi)者模式

    生產(chǎn)者和消費(fèi)者模式適用于生產(chǎn)者和消費(fèi)者之間存在數(shù)據(jù)交換的場(chǎng)景。在這種模式中,生產(chǎn)者負(fù)責(zé)生產(chǎn)數(shù)據(jù)并將其放入緩沖區(qū),而消費(fèi)者負(fù)責(zé)從緩沖區(qū)中取出數(shù)據(jù)并進(jìn)行處理。這種模式的優(yōu)點(diǎn)是可以實(shí)現(xiàn)生產(chǎn)者和消費(fèi)者之間的解耦,使得它們可以獨(dú)立地進(jìn)行操作,從而提高了

    2024年02月03日
    瀏覽(20)
  • 【linux】POSIX信號(hào)量+基于環(huán)形隊(duì)列的生產(chǎn)消費(fèi)模型

    【linux】POSIX信號(hào)量+基于環(huán)形隊(duì)列的生產(chǎn)消費(fèi)模型

    喜歡的點(diǎn)贊,收藏,關(guān)注一下把! 上篇文章最后我們基于BlockQueue生產(chǎn)者消費(fèi)者模型寫了代碼,測(cè)試什么的都通過(guò)了。最后我們說(shuō)代碼還有一些不足的地方,由這些不足從而引入了我們接下來(lái)要學(xué)的信號(hào)量! 我們?cè)诳匆豢床蛔愕牡胤?1.一個(gè)線程,在操作臨界資源的時(shí)候,必須

    2024年02月01日
    瀏覽(24)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包