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

Linux知識(shí)點(diǎn) -- 進(jìn)程間通信(二)

這篇具有很好參考價(jià)值的文章主要介紹了Linux知識(shí)點(diǎn) -- 進(jìn)程間通信(二)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

Linux知識(shí)點(diǎn) – 進(jìn)程間通信(二)


一、System V共享內(nèi)存

1.原理

Linux知識(shí)點(diǎn) -- 進(jìn)程間通信(二),Linux,linux,chrome,運(yùn)維
先在內(nèi)存中申請(qǐng)空間,然后將這段空間映射到不同進(jìn)程的地址空間中,這就叫做共享內(nèi)存;
一般都是映射在進(jìn)程的堆棧之間的共享區(qū);
共享內(nèi)存不屬于任何一個(gè)進(jìn)程,它屬于操作系統(tǒng);
操作系統(tǒng)對(duì)共享內(nèi)存的管理,是先描述再組織,先通過內(nèi)核數(shù)據(jù)結(jié)構(gòu)描述共享內(nèi)存的屬性信息,再將它們組織起來;
共享內(nèi)存 = 共享內(nèi)存塊 + 對(duì)應(yīng)的共享內(nèi)存的內(nèi)核數(shù)據(jù)結(jié)構(gòu);
共享區(qū)屬于用戶空間,不用經(jīng)過系統(tǒng)調(diào)用,直接可以訪問;
雙方進(jìn)程如果要通信,直接進(jìn)行內(nèi)存級(jí)的讀寫即可;
之前的管道是一種文件。是OS中的一種數(shù)據(jù)結(jié)構(gòu),所以用戶無權(quán)直接訪問,需要進(jìn)行系統(tǒng)調(diào)用;

2.申請(qǐng)共享內(nèi)存

Linux知識(shí)點(diǎn) -- 進(jìn)程間通信(二),Linux,linux,chrome,運(yùn)維
shmget接口能夠申請(qǐng)共享內(nèi)存;

  • 參數(shù):
    key:通信雙方的進(jìn)程,通過key值來保證是通信的雙方來創(chuàng)建的共享內(nèi)存,相當(dāng)于一個(gè)驗(yàn)證值,需要在系統(tǒng)內(nèi)是唯一的,通信雙方使用同一個(gè)key;
    size:內(nèi)存大小,一般是頁(4byte)的整數(shù)倍;
    shmflag:有兩個(gè)選項(xiàng):IPC_CREAT和IPC_EXCL;
    IPC_CREAT能單獨(dú)出現(xiàn),代表如果共享內(nèi)存已存在,則獲取之;如果不存在,就創(chuàng)建之,并返回;
    IPC_EXCL必須和IPC_CREAT組合使用,代表如果共享內(nèi)存不存在,就創(chuàng)建之,并返回;如果已存在,出錯(cuò)并返回;
    0就代表IPC_CREAT;

    返回值:成功會(huì)返回共享內(nèi)存id,失敗返回-1;

ftok函數(shù):生成唯一的key
Linux知識(shí)點(diǎn) -- 進(jìn)程間通信(二),Linux,linux,chrome,運(yùn)維

  • 參數(shù):
    ==pathname:==文件路徑,一定要保證用戶有權(quán)限;
    ==id:==項(xiàng)目id,隨便給,一般是0 - 255;
    返回值:成功,返回key值;失敗,返回-1;
    ftok會(huì)拿路徑文件的inode,和id形成一個(gè)唯一的key,生成結(jié)果是有可能重復(fù)的;

3.System V共享內(nèi)存的使用

  • Makefile:
.PHONY:all
all:shmClient shmServer

shmServer:shmServer.cc
	g++ -o $@ $^ -std=c++11 
shmClient:shmClient.cc
	g++ -o $@ $^ -std=c++11 

.PHONY:clean
claen:
	rm -f shmServer shmClient
  • Log.hpp
#ifndef _LOG_H_
#define _LOG_H_

#include<iostream>
#include<ctime>

#define DeBug   0
#define Notice  1
#define Waring  2
#define Error   3

const std::string msg[] = {
    "DeBug",
    "Notice",
    "Waring",
    "Error"
};

std::ostream &Log(std::string message, int level)
{
    std::cout << " | " << (unsigned)time(nullptr) << " | " << msg[level] << " | " << message;
    return std::cout;
}
#endif
  • comm.hpp
#ifndef _COMM_H_
#define _COMM_H_

#include<iostream>
#include<cstdio>
#include<unistd.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<cassert>
#include "Log.hpp"

using namespace std;

#define PATH_NAME "/usr/lmx" //路徑,一定保證有權(quán)限
#define PROJ_ID 0X66   
#define SHM_SIZE 4096 //共享內(nèi)存大小,最好是頁(4byte)的整數(shù)倍

#endif
  • shmServer.cc
    #include “comm.hpp”

string TransToHex(key_t k)
{
char buffer[32];
snprintf(buffer, sizeof(buffer), “0x%x”, k);
return buffer;
}

int main()
{
// 1.創(chuàng)建公共的key值
key_t key = ftok(PATH_NAME, PROJ_ID);
if (key == -1)
{
perror(“ftok”);
exit(1);
}

Log("creat key done", DeBug) << "server key : " << TransToHex(key) << endl;

// 2.創(chuàng)建共享內(nèi)存 -- 建議創(chuàng)建一個(gè)全新的共享內(nèi)存 -- 通信的發(fā)起者
int shmid = shmget(key, SHM_SIZE, IPC_CREAT | IPC_EXCL | 0666);
if (shmid == -1)
{
    perror("shmget");
    exit(2);
}
Log("shm creat done", DeBug) << "shmid : " << shmid << endl;

//3.將指定的共享內(nèi)存,掛接到自己的地址空間
char* shmaddr = (char*)shmat(shmid, nullptr, 0);
Log("attach shm done", DeBug) << "shmid : " << shmid << endl;

//這里就是通信邏輯了
//將共享內(nèi)存看作一個(gè)大字符串
//shmaddr就是這個(gè)字符串的起始地址
for(;;)
{
    printf("%s\n", shmaddr);//不斷打印這個(gè)字符串的內(nèi)容
    if(strcmp(shmaddr, "quit") == 0)
    {
        break;
    }
    sleep(1);
}

//4.將指定的共享內(nèi)存,從自己的地址空間中去關(guān)聯(lián)
int n = shmdt(shmaddr);
if(n == -1)
{
    perror("shmdt");
    exit(3);
}
Log("detach shm done", DeBug) << "shmid : " << shmid << endl;

//5.刪除共享內(nèi)存,IPC_RMID即便是有進(jìn)程和當(dāng)下的shm掛接,依舊刪除共享內(nèi)存
n = shmctl(shmid, IPC_RMID, nullptr);
if(n == -1)
{
    perror("shmctl");
    exit(4);
}
Log("delete shm done", DeBug) << "shmid : " << shmid << endl;

return 0;

}


注意:
(1)
Linux知識(shí)點(diǎn) -- 進(jìn)程間通信(二),Linux,linux,chrome,運(yùn)維
要保證創(chuàng)建出唯一的key;*
(2)
Linux知識(shí)點(diǎn) -- 進(jìn)程間通信(二),Linux,linux,chrome,運(yùn)維
創(chuàng)建全新的共享內(nèi)存,0666代表共享內(nèi)存的權(quán)限;
共享內(nèi)存的大小最好是頁的整數(shù)倍,否則會(huì)造成空間浪費(fèi),多開空間,但是沒有權(quán)限訪問;
Linux知識(shí)點(diǎn) -- 進(jìn)程間通信(二),Linux,linux,chrome,運(yùn)維
第二次創(chuàng)建的時(shí)候,提示共享內(nèi)存已存在;
Linux知識(shí)點(diǎn) -- 進(jìn)程間通信(二),Linux,linux,chrome,運(yùn)維
(3)ipcs -m:查看共享內(nèi)存信息;
Linux知識(shí)點(diǎn) -- 進(jìn)程間通信(二),Linux,linux,chrome,運(yùn)維
ipcrm -m shmid:刪除共享內(nèi)存(不能用key刪除)
共享內(nèi)存的生命周期隨內(nèi)核;
與文件不一樣,文件的生命周期,如果進(jìn)程退出,沒有其他進(jìn)程再關(guān)聯(lián)這個(gè)文件,那么就會(huì)被回收;

Linux知識(shí)點(diǎn) -- 進(jìn)程間通信(二),Linux,linux,chrome,運(yùn)維
Linux知識(shí)點(diǎn) -- 進(jìn)程間通信(二),Linux,linux,chrome,運(yùn)維
perms屬性就是共享內(nèi)存的權(quán)限,

(4)因此,當(dāng)進(jìn)程結(jié)束后,共享內(nèi)存還存在,我們繼續(xù)要?jiǎng)h除它,使用系統(tǒng)接口:
shmctl:刪除共享內(nèi)存
Linux知識(shí)點(diǎn) -- 進(jìn)程間通信(二),Linux,linux,chrome,運(yùn)維
Linux知識(shí)點(diǎn) -- 進(jìn)程間通信(二),Linux,linux,chrome,運(yùn)維
(5)nattch屬性是掛接的共享內(nèi)存?zhèn)€數(shù),共享內(nèi)存創(chuàng)建好之后,需要掛接在自己的進(jìn)程地址空間;
shmat:掛接共享內(nèi)存
Linux知識(shí)點(diǎn) -- 進(jìn)程間通信(二),Linux,linux,chrome,運(yùn)維
參數(shù):
shmid:共享內(nèi)存id
shmaddr:掛接虛擬地址,直接設(shè)為0,讓os掛接
shmflg:掛接方式
返回值:成功返回共享內(nèi)存addr虛擬地址,失敗返回-1

使用:
將返回值作為共享內(nèi)存的起始地址;
Linux知識(shí)點(diǎn) -- 進(jìn)程間通信(二),Linux,linux,chrome,運(yùn)維
shmdt:去關(guān)聯(lián)
Linux知識(shí)點(diǎn) -- 進(jìn)程間通信(二),Linux,linux,chrome,運(yùn)維
參數(shù):
shmaddr:共享內(nèi)存地址
返回值:成功返回0,失敗返回-1

  • shmClient.cc
#include "comm.hpp"

int main()
{
    // 客戶端也獲取key
    key_t key = ftok(PATH_NAME, PROJ_ID);
    if (key < 0)
    {
        Log("creat key failed", Error) << "client key : " << key << endl;
        exit(1);
    }
    Log("creat key done", DeBug) << "client key : " << key << endl;

    // 獲取共享內(nèi)存
    int shmid = shmget(key, SHM_SIZE, 0);
    if (shmid == -1)
    {
        Log("creat shm failed", Error) << "client key : " << key << endl;
        exit(2);
    }
    Log("creat shm done", DeBug) << "client key : " << key << endl;


    // 掛接共享內(nèi)存
    char *shmaddr = (char *)shmat(shmid, nullptr, 0);
    if (shmaddr == nullptr)
    {
        Log("attach shm failed", Error) << "client key : " << key << endl;
    }
    Log("attach shm done", DeBug) << "client key : " << key << endl;
    
    // 使用
    //client將共享內(nèi)存看作一個(gè)char類型的buffer
    //客戶端從鍵盤讀取消息,直接讀到共享內(nèi)存中
    while (true)
    {
        ssize_t s = read(0, shmaddr, SHM_SIZE - 1);
        if(s > 0)
        {
            shmaddr[s - 1] = 0;
            if(strcmp(shmaddr, "quit") == 0)//讀到quit,客戶端退出
            {
                break;
            }
        }
    }
    
    // char a = 'a';
    // for(; a <= 'z'; a++)
    // {
    //     //每一次都向shmaddr(共享內(nèi)存的起始地址)寫入
    //     snprintf(shmaddr, SHM_SIZE - 1, 
    //             "hello server, 我是其他進(jìn)程,我的pid: %d, inc: %c\n", 
    //             getpid(), a);
    //     sleep(2);
    // }

    // 去關(guān)聯(lián)
    int n = shmdt(shmaddr);
    if (n == -1)
    {
        perror("shmdt");
        exit(3);
    }
    Log("detach shm done", DeBug) << "client key : " << key << endl;

    // client不需要?jiǎng)h除shm

    return 0;
}

注意:
(1)共享內(nèi)存的使用,直接將共享內(nèi)存看作一個(gè)char類型的buffer,直接向里面寫入數(shù)據(jù)
Linux知識(shí)點(diǎn) -- 進(jìn)程間通信(二),Linux,linux,chrome,運(yùn)維
從stdin中鍵盤讀取消息,直接讀取到shmaddr這個(gè)地址,即共享內(nèi)存的起始地址;

運(yùn)行結(jié)果:
服務(wù)端:
Linux知識(shí)點(diǎn) -- 進(jìn)程間通信(二),Linux,linux,chrome,運(yùn)維
客戶端:
Linux知識(shí)點(diǎn) -- 進(jìn)程間通信(二),Linux,linux,chrome,運(yùn)維

  • 注:
    (1)只要是通信雙方使用shm,一方直接向共享內(nèi)存中寫入數(shù)據(jù),另一方就可以立馬看到對(duì)方寫入的數(shù)據(jù);共享內(nèi)存是所有進(jìn)程間通信中最快的,不需要過多的拷貝;
    (2)管道通信中,一次通信需要多次拷貝,用戶從鍵盤輸入數(shù)據(jù)到緩沖區(qū)是一次拷貝,從緩沖區(qū)向管道文件寫入數(shù)據(jù)又是一次拷貝,從管道文件向緩沖區(qū)讀取數(shù)據(jù)是一次拷貝,從緩沖區(qū)將數(shù)據(jù)打印又是一次拷貝;

    Linux知識(shí)點(diǎn) -- 進(jìn)程間通信(二),Linux,linux,chrome,運(yùn)維

(3)共享內(nèi)存只需要兩次拷貝,從鍵盤輸入的數(shù)據(jù)直接寫入shm,這是一次拷貝,直接將shm的數(shù)據(jù)打印出來,這是第二次拷貝;
Linux知識(shí)點(diǎn) -- 進(jìn)程間通信(二),Linux,linux,chrome,運(yùn)維

4.為共享內(nèi)存添加訪問控制

從上面的結(jié)果可以看出,即便是客戶端還沒有掛接共享內(nèi)存,服務(wù)端就已經(jīng)開始不停讀取數(shù)據(jù)了,這就表明共享內(nèi)存是不帶訪問控制的,會(huì)帶來一定的并發(fā)問題;
然而,管道是自帶訪問控制的,我們可以利用管道通信來為共享內(nèi)存添加訪問控制;
comm.hpp

#ifndef _COMM_H_
#define _COMM_H_

#include <iostream>
#include <cstdio>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <cassert>
#include <cstring>
#include <sys/stat.h>
#include <fcntl.h>
#include "Log.hpp"

using namespace std;

#define PATH_NAME "/home/lmx" // 路徑,一定保證有權(quán)限
#define PROJ_ID 0X66
#define SHM_SIZE 4096 // 共享內(nèi)存大小,最好是頁(4byte)的整數(shù)倍

#define FIFO_NAME "./fifo"

class Init
{
public:
    Init()
    {
        umask(0);
        int n = mkfifo(FIFO_NAME, 0666);
        assert(n == 0);
        (void)n;
        Log("creat fifo succsee", Notice) << "\n";
    }

    ~Init()
    {
        unlink(FIFO_NAME);
        Log("remove fifo succsee", Notice) << "\n";
    }
};


#define READ O_RDONLY
#define WRITE O_WRONLY

int OpenFIFO(std::string pathname, int flags)
{
    int fd = open(pathname.c_str(), flags);
    assert(fd >= 0);
    return fd;
}

void Wait(int fd)
{
    Log("waiting...", Notice) << "\n";
    uint32_t temp = 0;
    ssize_t s = read(fd, &temp, sizeof(uint32_t));
    assert(s == sizeof(uint32_t));
    (void)s;
}

void Signal(int fd)
{
    uint32_t temp = 1;
    ssize_t s = write(fd, &temp, sizeof(uint32_t));
    assert(s == sizeof(uint32_t));
    (void)s;
    Log("aweaking...", Notice) << "\n";
}

void CloseFIFO(int fd)
{
    close(fd);
}

#endif

注:
(1)創(chuàng)建了一個(gè)類,類的構(gòu)造函數(shù)有創(chuàng)建管道文件,一旦類實(shí)例化出對(duì)象,調(diào)用構(gòu)造函數(shù),就能夠創(chuàng)建一個(gè)管道文件,后面就是對(duì)管道文件的讀寫控制了;
Linux知識(shí)點(diǎn) -- 進(jìn)程間通信(二),Linux,linux,chrome,運(yùn)維
shmServer.cc

#include "comm.hpp"

string TransToHex(key_t k)
{
    char buffer[32];
    snprintf(buffer, sizeof(buffer), "0x%x", k);
    return buffer;
}

int main()
{
    Init init;
    // 對(duì)應(yīng)的程序在加載的時(shí)候,會(huì)自動(dòng)構(gòu)建全局變量,就要調(diào)用該類構(gòu)造函數(shù) -- 創(chuàng)建管道文件
    // 程序退出的時(shí)候,全局變量會(huì)被析構(gòu),會(huì)自動(dòng)刪除管道文件

    // 1.創(chuàng)建公共的key值
    key_t key = ftok(PATH_NAME, PROJ_ID);
    if (key == -1)
    {
        perror("ftok");
        exit(1);
    }

    Log("creat key done", DeBug) << "server key : " << TransToHex(key) << endl;

    // 2.創(chuàng)建共享內(nèi)存 -- 建議創(chuàng)建一個(gè)全新的共享內(nèi)存 -- 通信的發(fā)起者
    int shmid = shmget(key, SHM_SIZE, IPC_CREAT | IPC_EXCL | 0666);
    if (shmid == -1)
    {
        perror("shmget");
        exit(2);
    }
    Log("shm creat done", DeBug) << "shmid : " << shmid << endl;

    // 3.將指定的共享內(nèi)存,掛接到自己的地址空間
    char *shmaddr = (char *)shmat(shmid, nullptr, 0);
    Log("attach shm done", DeBug) << "shmid : " << shmid << endl;

    // 這里就是通信邏輯了
    // 將共享內(nèi)存看作一個(gè)大字符串
    // shmaddr就是這個(gè)字符串的起始地址

    //使用管道進(jìn)行訪問控制
    int fd = OpenFIFO(FIFO_NAME, READ);

    for (;;)
    {
        Wait(fd);//等待客戶端響應(yīng),
                    //使用管道文件的訪問控制,如果客戶端沒有向管道內(nèi)寫入數(shù)據(jù),那么該進(jìn)程會(huì)一直阻塞
        printf("%s\n", shmaddr); // 不斷打印這個(gè)字符串的內(nèi)容
        if (strcmp(shmaddr, "quit") == 0)
        {
            break;
        }
        sleep(1);
    }

    CloseFIFO(fd);

    // 4.將指定的共享內(nèi)存,從自己的地址空間中去關(guān)聯(lián)
    int n = shmdt(shmaddr);
    if (n == -1)
    {
        perror("shmdt");
        exit(3);
    }
    Log("detach shm done", DeBug) << "shmid : " << shmid << endl;

    // 5.刪除共享內(nèi)存,IPC_RMID即便是有進(jìn)程和當(dāng)下的shm掛接,依舊刪除共享內(nèi)存
    n = shmctl(shmid, IPC_RMID, nullptr);
    if (n == -1)
    {
        perror("shmctl");
        exit(4);
    }
    Log("delete shm done", DeBug) << "shmid : " << shmid << endl;

    return 0;
}

注:
(1)在服務(wù)端先創(chuàng)建一個(gè)管道文件
Linux知識(shí)點(diǎn) -- 進(jìn)程間通信(二),Linux,linux,chrome,運(yùn)維
(2)在讀取共享內(nèi)存中的數(shù)據(jù)前,先讀取管道數(shù)據(jù),看客戶端是否響應(yīng);
Linux知識(shí)點(diǎn) -- 進(jìn)程間通信(二),Linux,linux,chrome,運(yùn)維
shmClient.cc

#include "comm.hpp"

int main()
{
    // 客戶端也獲取key
    key_t key = ftok(PATH_NAME, PROJ_ID);
    if (key < 0)
    {
        Log("creat key failed", Error) << "client key : " << key << endl;
        exit(1);
    }
    Log("creat key done", DeBug) << "client key : " << key << endl;

    // 獲取共享內(nèi)存
    int shmid = shmget(key, SHM_SIZE, 0);
    if (shmid == -1)
    {
        Log("creat shm failed", Error) << "client key : " << key << endl;
        exit(2);
    }
    Log("creat shm done", DeBug) << "client key : " << key << endl;


    // 掛接共享內(nèi)存
    char *shmaddr = (char *)shmat(shmid, nullptr, 0);
    if (shmaddr == nullptr)
    {
        Log("attach shm failed", Error) << "client key : " << key << endl;
    }
    Log("attach shm done", DeBug) << "client key : " << key << endl;
    
    // 使用
    //client將共享內(nèi)存看作一個(gè)char類型的buffer
    //客戶端從鍵盤讀取消息,直接讀到共享內(nèi)存中

    //使用管道進(jìn)行訪問控制
    int fd = OpenFIFO(FIFO_NAME, WRITE);

    while (true)
    {
        ssize_t s = read(0, shmaddr, SHM_SIZE - 1);
        if(s > 0)
        {
            shmaddr[s - 1] = 0;
            Signal(fd);//向管道寫入數(shù)據(jù)
            if(strcmp(shmaddr, "quit") == 0)//讀到quit,客戶端退出
            {
                break;
            }
        }
    }

    CloseFIFO(fd);
    
    // 去關(guān)聯(lián)
    int n = shmdt(shmaddr);
    if (n == -1)
    {
        perror("shmdt");
        exit(3);
    }
    Log("detach shm done", DeBug) << "client key : " << key << endl;

    // client不需要?jiǎng)h除shm

    return 0;
}

注:
(1)在向共享內(nèi)存寫入數(shù)據(jù)前,先向管道寫入信號(hào),表明客戶端準(zhǔn)備寫入數(shù)據(jù),喚醒服務(wù)端:
Linux知識(shí)點(diǎn) -- 進(jìn)程間通信(二),Linux,linux,chrome,運(yùn)維

運(yùn)行結(jié)果:
當(dāng)運(yùn)行服務(wù)端,但是客戶端未響應(yīng)時(shí),服務(wù)端會(huì)等待客戶端響應(yīng),進(jìn)程阻塞;
Linux知識(shí)點(diǎn) -- 進(jìn)程間通信(二),Linux,linux,chrome,運(yùn)維
當(dāng)客戶端響應(yīng)時(shí),服務(wù)端會(huì)被喚醒,讀取共享內(nèi)存中的數(shù)據(jù):
Linux知識(shí)點(diǎn) -- 進(jìn)程間通信(二),Linux,linux,chrome,運(yùn)維
退出:
Linux知識(shí)點(diǎn) -- 進(jìn)程間通信(二),Linux,linux,chrome,運(yùn)維

二、信號(hào)量(概念理解)

1.概念

  • 基于對(duì)共享內(nèi)存的理解:
    為了讓進(jìn)程間通信,讓不同的進(jìn)程之間,看到同一份資源,我們之前講的所有的進(jìn)程間通信都是基于這種方式;
    而讓不同的進(jìn)程看到同一份資源,比如共享內(nèi)存,也帶來了一些時(shí)序問題,會(huì)造成數(shù)據(jù)的不一致

  • 概念
    (1)臨界資源:多個(gè)進(jìn)程(執(zhí)行流)看到的公共的一份資源;
    (2)臨界區(qū):自己的進(jìn)程,訪問臨界資源的代碼;
    (3)互斥:為了更好的進(jìn)行臨界區(qū)的維護(hù),可以讓多執(zhí)行流在任何時(shí)刻,都只能有一個(gè)進(jìn)程進(jìn)入臨界區(qū);
    (4)原子性:要么不做,要么做完,沒有中間狀態(tài);

2.信號(hào)量

我們平??措娪扒?,會(huì)先買票,電影院中的座位就相當(dāng)于資源,當(dāng)你買了票,這個(gè)座位就真正屬于你,買票的本質(zhì)就是對(duì)座位的預(yù)定機(jī)制;
對(duì)于進(jìn)程來說,訪問臨界資源中的一部分,不能讓進(jìn)程直接去使用臨界資源,需要先申請(qǐng)信號(hào)量;
信號(hào)量的本質(zhì)是一個(gè)計(jì)數(shù)器

  • 申請(qǐng)信號(hào)量:
    (1)申請(qǐng)信號(hào)量的本質(zhì),就是讓信號(hào)量技術(shù)器 - -;
    (2)申請(qǐng)信號(hào)量成功,臨界資源內(nèi)部,一定給進(jìn)程預(yù)留了需要的資源,申請(qǐng)信號(hào)量的本質(zhì)就是對(duì)臨界資源的一種預(yù)定機(jī)制;

  • 釋放信號(hào)量:
    釋放信號(hào)量就是將計(jì)數(shù)器++;

如果將信號(hào)量計(jì)數(shù)器設(shè)為全局變量(整數(shù)n,存放在共享內(nèi)存),讓多個(gè)進(jìn)程看到同一個(gè)全局變量,大家都能夠進(jìn)行信號(hào)量的申請(qǐng),這樣是不行的;
因?yàn)镃PU在執(zhí)行n++這個(gè)指令的時(shí)候,其實(shí)執(zhí)行了三條語句:
(1)將內(nèi)存中的數(shù)據(jù)加載到CPU內(nèi)的寄存器(讀指令);
(2)n–(執(zhí)行指令);
(3)將CPU修改完畢的值再寫入內(nèi)存(寫指令);

而執(zhí)行流在執(zhí)行的時(shí)候,在任何時(shí)刻都是能被切換的;
例如:
如果信號(hào)量剛開始是5,client在申請(qǐng)信號(hào)量的時(shí)候,第一步就被切換了,寄存器里的數(shù)據(jù)保存為上下文數(shù)據(jù),
由server申請(qǐng)信號(hào)量,如果server將信號(hào)量減到2了,此時(shí)server被切換,client回來
client回來的時(shí)候就會(huì)將上下文數(shù)據(jù)恢復(fù),將信號(hào)量恢復(fù)為5,再申請(qǐng)信號(hào)量,這時(shí)信號(hào)量就變?yōu)榱?;

寄存器只有一套,被所有執(zhí)行流共享,但是寄存器內(nèi)的數(shù)據(jù),屬于每一個(gè)執(zhí)行流,屬于該執(zhí)行流的上下文數(shù)據(jù);
這樣設(shè)計(jì),會(huì)導(dǎo)致信號(hào)量是不安全的;
因此,申請(qǐng)和釋放信號(hào)量這兩個(gè)操作,必須是原子的
Linux知識(shí)點(diǎn) -- 進(jìn)程間通信(二),Linux,linux,chrome,運(yùn)維文章來源地址http://www.zghlxwxcb.cn/news/detail-631405.html

到了這里,關(guān)于Linux知識(shí)點(diǎn) -- 進(jìn)程間通信(二)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(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】馮諾依曼體系結(jié)構(gòu)與進(jìn)程的基礎(chǔ)知識(shí)點(diǎn)

    【Linux】馮諾依曼體系結(jié)構(gòu)與進(jìn)程的基礎(chǔ)知識(shí)點(diǎn)

    計(jì)算器、筆記本、服務(wù)器大都遵循馮諾依曼體系結(jié)構(gòu)。 結(jié)構(gòu)如下圖所示: 外設(shè):速度相對(duì)慢,價(jià)格相對(duì)較低(輸入輸出設(shè)備都屬于外設(shè)) 內(nèi)存:速度相對(duì)快,價(jià)格相對(duì)較高,數(shù)據(jù)掉電易失 CPU:速度最快,價(jià)格高 1.那么是否可以不通過存儲(chǔ)器,直接使用輸入設(shè)備將數(shù)據(jù)傳給

    2023年04月24日
    瀏覽(24)
  • 【Linux-14】進(jìn)程地址空間&虛擬空間&頁表——原理&知識(shí)點(diǎn)詳解

    【Linux-14】進(jìn)程地址空間&虛擬空間&頁表——原理&知識(shí)點(diǎn)詳解

    前言 大家好吖,歡迎來到 YY 滴 系列 ,熱烈歡迎! 本章主要內(nèi)容面向接觸過Linux的老鐵 主要內(nèi)容含: 歡迎訂閱 YY 滴C++專欄!更多干貨持續(xù)更新!以下是傳送門! YY的《C++》專欄 YY的《C++11》專欄 YY的《Linux》專欄 YY的《數(shù)據(jù)結(jié)構(gòu)》專欄 YY的《C語言基礎(chǔ)》專欄 YY的《初學(xué)者易

    2024年04月29日
    瀏覽(31)
  • C#知識(shí)點(diǎn)-13(進(jìn)程、多線程、使用Socket實(shí)現(xiàn)服務(wù)器與客戶端通信)

    C#知識(shí)點(diǎn)-13(進(jìn)程、多線程、使用Socket實(shí)現(xiàn)服務(wù)器與客戶端通信)

    進(jìn)程 定義:每一個(gè)正在運(yùn)行的應(yīng)用程序,都是一個(gè)進(jìn)程? 進(jìn)程不等于正在運(yùn)行的應(yīng)用程序。而是為應(yīng)用程序的運(yùn)行構(gòu)建一個(gè)運(yùn)行環(huán)境 多線程 這段代碼在執(zhí)行完成之前,程序會(huì)被卡死(不能操作程序,包括關(guān)閉窗口)。因?yàn)槲覀兂绦蛟谧鲆恍┖臅r(shí)操作的時(shí)候,如果主線程去執(zhí)

    2024年02月22日
    瀏覽(229)
  • Linux知識(shí)點(diǎn) -- Linux多線程(三)

    Linux知識(shí)點(diǎn) -- Linux多線程(三)

    持有鎖的線程會(huì)頻繁進(jìn)入臨界區(qū)申請(qǐng)臨界資源,造成其他進(jìn)程饑餓的問題; 這本身是沒有錯(cuò)的,但是不合理; 線程同步:就是線程按照一定的順序,進(jìn)行臨界資源的訪問;主要就是為了解決訪問臨界資源和理性的問題;在保證數(shù)據(jù)安全的前提下,讓線程能夠按照某種特定的

    2024年02月11日
    瀏覽(20)
  • Linux知識(shí)點(diǎn) -- Linux多線程(四)

    Linux知識(shí)點(diǎn) -- Linux多線程(四)

    一種線程使用模式。線程過多會(huì)帶來調(diào)度開銷,進(jìn)而影響緩存局部性和整體性能。而線程池維護(hù)著多個(gè)線程,等待著監(jiān)督管理者分配可并發(fā)執(zhí)行的任務(wù)。這避免了在處理短時(shí)間任務(wù)時(shí)創(chuàng)建與銷毀線程的代價(jià)。線程池不僅能夠保證內(nèi)核的充分利用,還能防止過分調(diào)度。可用線程

    2024年02月10日
    瀏覽(29)
  • Linux相關(guān)知識(shí)點(diǎn)

    Linux是一套免費(fèi)使用和自由傳播的類Unix操作系統(tǒng),是一個(gè)基于POSIX和UNIX的多用戶、多任務(wù)、支持多線程和多CPU的操作系統(tǒng)。它能運(yùn)行主要的UNIX工具軟件、應(yīng)用程序和網(wǎng)絡(luò)協(xié)議。它支持32位和64位硬件。 Linux內(nèi)核 是一個(gè)Linux系統(tǒng)的內(nèi)核,而不是一個(gè)操作系統(tǒng) Linux操作系統(tǒng) 紅帽操

    2024年02月11日
    瀏覽(22)
  • Linux基礎(chǔ)知識(shí)點(diǎn)2

    Linux基礎(chǔ)知識(shí)點(diǎn)2

    Linux基礎(chǔ)知識(shí)?適合有Linux基礎(chǔ)的人群進(jìn)行復(fù)習(xí)。 禁止轉(zhuǎn)載! 文件管理與常用命令 Linux的文件的組成部分: ?????? 文件名 、 inode (i節(jié)點(diǎn))和 block (真正存數(shù)據(jù)的區(qū)域)。 查看某個(gè)文件的屬性: ?????????? ls -lh???? #可看到有類似”-rw-r--r--”的屬性符號(hào)?????? ??? 第

    2024年02月09日
    瀏覽(26)
  • Linux知識(shí)點(diǎn) -- 網(wǎng)絡(luò)基礎(chǔ)(一)

    Linux知識(shí)點(diǎn) -- 網(wǎng)絡(luò)基礎(chǔ)(一)

    獨(dú)立模式:計(jì)算機(jī)之間相互獨(dú)立 網(wǎng)絡(luò)互聯(lián):多臺(tái)計(jì)算機(jī)連接在一起,完成數(shù)據(jù)共享 局域網(wǎng)LAN:計(jì)算機(jī)數(shù)量更多了,通過交換機(jī)和路由器連接在一起: 廣域網(wǎng)WAN:將遠(yuǎn)隔千里的計(jì)算機(jī)都連接在一起 注:局域網(wǎng)和廣域網(wǎng)只有規(guī)模上的差別; OSI (Open System Interconnection,開放系統(tǒng)互

    2024年02月11日
    瀏覽(23)
  • 【知識(shí)點(diǎn)】linux下啟動(dòng)tomcat

    切換到tomcat安裝目錄下的bin目錄。 如不知安裝目錄,可以使用: 查找。 進(jìn)入bin目錄,通過命令啟動(dòng)。 (該方式是直接后臺(tái)啟動(dòng)。當(dāng)關(guān)閉linux會(huì)話窗口,tomcat服務(wù)也隨之關(guān)閉。) (該方式啟動(dòng),會(huì)顯示日志,不能輸入linux命令。當(dāng)關(guān)閉linux會(huì)話窗口,tomcat服務(wù)也隨之關(guān)閉。)

    2024年02月08日
    瀏覽(22)
  • 關(guān)于Linux同步機(jī)制知識(shí)點(diǎn)整理

    關(guān)于Linux同步機(jī)制知識(shí)點(diǎn)整理

    在Linux系統(tǒng)中,同步機(jī)制是操作系統(tǒng)中非常重要的一部分,以下是一些基本要點(diǎn): 互斥鎖 互斥鎖是一種「獨(dú)占鎖」,比如當(dāng)線程 A 加鎖成功后,此時(shí)互斥鎖已經(jīng)被線程 A 獨(dú)占了,只要線程 A 沒有釋放手中的鎖,線程 B 加鎖就會(huì)失敗,失敗的線程B于是就會(huì)釋放 CPU 讓給其他線程

    2024年02月11日
    瀏覽(21)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包