国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當前位置: 首頁 > news >正文

網站建設 天津國內軍事新聞最新消息

網站建設 天津,國內軍事新聞最新消息,安論壇網站建設,wordpress默認域名system V一、system V介紹二 、共享內存2.1 共享內存的原理2.2 共享內存接口2.2.1 創(chuàng)建共享內存shmget2.2.2 查看IPC資源2.2.3 共享內存的控制shmctl2.2.4 共享內存的關聯shmat2.2.5 共享內存的去關聯shmdt2.3 進程間通信2.4 共享內存的特性2.5 共享內存的大小三、消息隊列3.1 …

system V

  • 一、system V介紹
  • 二 、共享內存
    • 2.1 共享內存的原理
    • 2.2 共享內存接口
      • 2.2.1 創(chuàng)建共享內存shmget
      • 2.2.2 查看IPC資源
      • 2.2.3 共享內存的控制shmctl
      • 2.2.4 共享內存的關聯shmat
      • 2.2.5 共享內存的去關聯shmdt
    • 2.3 進程間通信
    • 2.4 共享內存的特性
    • 2.5 共享內存的大小
  • 三、消息隊列
    • 3.1 消息隊列的概念
    • 3.2 消息隊列接口
      • 3.2.1 消息隊列的獲取msgget
      • 3.2.2 消息隊列的控制msgctl
      • 3.2.3 消息隊列發(fā)送數據msgsnd
      • 3.2.4 消息隊列獲取msgrcv
  • 四、信號量
    • 4.1 信號量概念
    • 4.2 信號量的用處
    • 4.3 信號量的pv操作
    • 4.4 信號量接口
      • 4.4.1 信號量申請semget
      • 4.4.2 信號量控制semctl
      • 4.4.3 信號量操作semop
  • 五、總結

一、system V介紹

進程間通信除了通過管道,都是基于文件的通信方式,還有一種方式是:SystemV標準的進程間通信方式。SystemV是一個在OS層面專門為進程通信設計的一個方案。這些都是由計算機科學家和程序員設計的,并且需要給用戶使用。

如果要給用戶用,是以什么方式給用戶使用的呢?在操作系統(tǒng)層面上,SystemV是OS內核的一部分,是為OS中多進程提供的一種通信方案。但是OS不相信任何用戶,給用戶提供功能的時候,采用系統(tǒng)調用。所以System V進程間通信,一定會存在專門用來通信的接口:system call。

因為在早期由很多的方案,但是我們需要統(tǒng)一使用一個方案,所以現在誕生了在統(tǒng)一主機內的進程間通信方案:system V方案。

system V IPC提供的通信方式有三種: 共享內存、消息隊列、信號量

二 、共享內存

2.1 共享內存的原理

前面說過兩個進程要通信就需要看到同一塊資源。

而我們知道進程之間具有獨立性,物理內存當中代碼和數據也互相獨立。
那么現在我們可以在物理內存中創(chuàng)建一個內存塊,讓不同的進程都能看到這個內存塊,具體的做法如下:

1?? 通過某種調用,在內存中創(chuàng)建一份內存空間。
2?? 通過某種調用,讓進程”掛接“到這份內存空間上。(將創(chuàng)建好的內存映射進進程地址空間)
在后面可能不會共享內存了。所以在不用共享內存的時候
3?? 去關聯(去掛接)。
4?? 釋放共享內存。

對于共享內存的理解:
OS內可能存在多個進程同時使用不同的共享內存來進行進程間通信,既然有多份共享內存,那么操作系統(tǒng)就要管理它們,按照前面學習的經驗,先描述后組織,描述就是對共享內存的一系列屬性進行描述,而后用數據結構組織起來,這樣對共享內存的管理變成了對數據結構的操作。

2.2 共享內存接口

2.2.1 創(chuàng)建共享內存shmget

shmget:用來創(chuàng)建共享內存

 #include <sys/ipc.h>#include <sys/shm.h>int shmget(key_t key, size_t size, int shmflg);RETURN VALUEOn success, a valid shared memory identifier is returned.  On errir, -1 is returned, and errno is set to indicate the error.

參數說明:

size:共享內存的大小。
shmflag:通常有兩種選項:IPC_CREAT、IPC_EXCL。
IPC_CREAT: 共享內存如果不存在,則創(chuàng)建,不存在則獲取。
IPC_EXCL: 無法單獨使用
IPC_CREAT | IPC_EXCL: 如果不存在就創(chuàng)建,如果存在就出錯返回(保證共享內存是新創(chuàng)建的)。
如果shmflag是0默認就是IPC_CREAT。
key:保證看到同一份共享內存,能進行唯一性標識(就像省份證號碼一樣,數字不重要,只用來標識唯一性)。通過ftok函數轉化。
如果創(chuàng)建成功返回共享內存的標識符,如果失敗則返回-1。

ftok:用來形成key

#include <sys/types.h>
#include <sys/ipc.h>key_t ftok(const char *pathname, int proj_id);
RETURN VALUE
On success, the generated key_t value is returned.  
On failure -1 is returned, with errno indicating the error as for the stat(2) system call.

ftok第一個參數是自定義路徑名,第二個參數是自定義的項目ID。最后唯一的共享內存ID就是通過路徑名+項目ID來標識。最后生成的返回值并不重要,只要它能生成一個值來唯一標識這塊共享內存就可以。
只要參數不變,生成的返回值就不會變。 這樣就可以讓兩個進程擁有同一個key,就可以用key找到同一份共享內存。

key_t GetKey()
{key_t n = ftok(PATHNAME, PROJ_ID);if(n == -1){std::cerr << errno << ":" << strerror(errno) << std::endl;assert(false);}return n;
}int Creatshm(key_t key)
{int shmid = shmget(key, SIZE, IPC_CREAT | IPC_EXCL | 0666);if(shmid == -1){std::cerr << errno << ":" << strerror(errno) << std::endl;assert(false);}return shmid;
}int Getshm(key_t key)
{int shmid = shmget(key, SIZE, IPC_CREAT | 0666);if(shmid == -1){std::cerr << errno << ":" << strerror(errno) << std::endl;assert(false);}return shmid;
}

key的理解:
上面也說過了OS會把內存塊管理起來,共享內存=物理內存塊+共享內存的相關屬性。描述共享內存時就有一個字段struct shm中有key。 一個進程創(chuàng)建內存塊后把key值寫進相關屬性中,而另一個進程拿著key值遍歷相關屬性查找。這樣就完成了兩個進程共享一塊內存塊。
我們發(fā)現key和shmid都是標識內存塊的:key是在內核標識唯一性,而shmid是在用戶層標識唯一性,這樣即使操作系統(tǒng)有什么變化也不會影響用戶使用,充分的解耦。他們的關系就類似于fd與inode。

2.2.2 查看IPC資源

共享內存的生命周期不是隨著進程的,而是隨著OS的,這也是所有system V進程間通信的特征。

ipcs -m 查看共享內存
在這里插入圖片描述
ipcs -q 查看消息隊列
ipcs -s 查看信號量
在這里插入圖片描述

ipcs 三個一起查看
在這里插入圖片描述
ipcrm -m shmid 刪除共享內存
在這里插入圖片描述

2.2.3 共享內存的控制shmctl

shmctl:控制共享內存

#include <sys/ipc.h>
#include <sys/shm.h>int shmctl(int shmid, int cmd, struct shmid_ds *buf);

它的作用是對共享內存的控制。
參數介紹:
shmid:控制共享內存的標識符。
cmd:控制的種類,主要用的是IPC_RMID(立即移除共享內存)。
buf:控制共享內存的數據結構,設置為空即可。
返回值:0表示返回成功,-1表示失敗。

void Delshm(int shmid)
{if(shmctl(shmid, IPC_RMID, nullptr) == -1){std::cerr << errno << ":" << strerror(errno) << std::endl;assert(false);}
}

2.2.4 共享內存的關聯shmat

#include <sys/types.h>
#include <sys/shm.h>void *shmat(int shmid, const void *shmaddr, int shmflg);

參數介紹:
shmaddr:可以指定虛擬內存,設置為nullptr即可。
shmflg:讀取權限,默認為0。
返回值:返回共享內存的起始地址。

void* Attachshm(int shmid)
{void* mem = shmat(shmid, nullptr, 0);if((long long)mem == -1L)// 64位指針8字節(jié){std::cerr << errno << ":" << strerror(errno) << std::endl;assert(false);}return mem;
}

2.2.5 共享內存的去關聯shmdt

去關聯是指把進程和共享內存之間的映射關系刪掉(修改頁表),并不是刪除共享內存。

#include <sys/types.h>
#include <sys/shm.h>int shmdt(const void *shmaddr);

它的參數就是在shmat返回的參數。
成功返回0,失敗返回-1。

void Detachshm(void* start)
{if(shmdt(start) == -1){std::cerr << errno << ":" << strerror(errno) << std::endl;assert(false);}
}

2.3 進程間通信

comm.hpp

#ifndef _COMM_HPP_
#define _COMM_HPP_#include <iostream>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <cstring>
#include <cerrno>
#include <cassert>
#include <cstdlib>
#include <cstdio>
#include <unistd.h>#define PATHNAME ".."
#define PROJ_ID 12345
#define SIZE 4096key_t GetKey()
{key_t n = ftok(PATHNAME, PROJ_ID);if(n == -1){std::cerr << errno << ":" << strerror(errno) << std::endl;assert(false);}return n;
}int Creatshm(key_t key)
{int shmid = shmget(key, SIZE, IPC_CREAT | IPC_EXCL | 0666);if(shmid == -1){std::cerr << errno << ":" << strerror(errno) << std::endl;assert(false);}return shmid;
}int Getshm(key_t key)
{int shmid = shmget(key, SIZE, IPC_CREAT | 0666);if(shmid == -1){std::cerr << errno << ":" << strerror(errno) << std::endl;assert(false);}return shmid;
}void Delshm(int shmid)
{if(shmctl(shmid, IPC_RMID, nullptr) == -1){std::cerr << errno << ":" << strerror(errno) << std::endl;assert(false);}
}void* Attachshm(int shmid)
{void* mem = shmat(shmid, nullptr, 0);if((long long)mem == -1L)// 64位指針8字節(jié){std::cerr << errno << ":" << strerror(errno) << std::endl;assert(false);}return mem;
}void Detachshm(void* start)
{if(shmdt(start) == -1){std::cerr << errno << ":" << strerror(errno) << std::endl;assert(false);}
}#endif

shm_a.cc

#include "comm.hpp"int main()
{key_t k = GetKey();// 創(chuàng)建共享內存int shmid = Creatshm(k);// 掛接char* start = (char*)Attachshm(shmid);//使用while(true){if(strlen(start) > 4){printf("%s\n", start);}if(strlen(start) == 4){break;}sleep(1);}// 去關聯Detachshm(start);// 刪除共享內存Delshm(shmid);return 0;
}

shm_b.cc

#include "comm.hpp"int main()
{key_t k = GetKey();// 獲取共享內存int shmid = Getshm(k);// 掛接char* start = (char*)Attachshm(shmid);// 使用std::string str = "hello shm";int cnt = 0;while(cnt != 8){snprintf(start, SIZE, "%s[%d]", str.c_str(),  cnt);cnt++;sleep(1);}std::string cmd = "stop";snprintf(start, SIZE, "%s", cmd.c_str());// 去關聯Detachshm(start);return 0;
}

2.4 共享內存的特性

1?? 共享內存是所有的進程間通信速度最快的。(優(yōu)點)
2?? 共享內存不提供任何同步或者互斥機制,不提供不代表不需要,所以需要程序員自行保證數據的安全!這也造成了共享內存在多進程中是不太安全的。(缺點)
3?? 共享內存的生命周期是隨OS的,而不是隨進程的,這是所有System V進程間通信的共性。

為什么速度快呢?
管道和共享內存:考慮鍵盤輸入,和顯示器輸出,對于同一份數據,共享內存有幾次數據拷貝,管道有幾次數據拷貝

管道:在這里插入圖片描述
可以看到寫到管道需要拷貝兩次,而另一個進程讀也需要兩次,所以一共四次。如果考慮到輸入輸出外設,那么就是六次。

共享內存:
直接寫入共享內存,直接從共享內存輸出,所以是兩次。考慮到輸入輸出的話就是四次。

2.5 共享內存的大小

這里講的是shget的第二個參數,一般建議設置成4096(4KB)的整數倍,因為系統(tǒng)分享內存是以4KB為單位,假如我們申請的是4097,那么系統(tǒng)就會直接向上取整,也就是4096*2,但是我們只能使用其中的4097大小。

三、消息隊列

3.1 消息隊列的概念

消息隊列提供了一個從一個進程向另外一個進程發(fā)送一塊數據的方法,讀端和寫端公用一個隊列,每個數據塊就是隊列的一個節(jié)點,每個數據塊都會有個記錄類型的數據,來判斷該數據塊該被哪個進程讀取。

3.2 消息隊列接口

3.2.1 消息隊列的獲取msgget

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>int msgget(key_t key, int msgflg);

這里的msgflg跟共享內存的兩個參數一摸一樣(IPC_CREAT、IPC_EXCL)。

返回值:msgget函數返回的一個有效的消息隊列標識符

3.2.2 消息隊列的控制msgctl

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>int msgctl(int msqid, int cmd, struct msqid_ds *buf);

參數說明:
msqid:消息隊列的標識符。
其他的參數跟shmctl一樣。

3.2.3 消息隊列發(fā)送數據msgsnd

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

參數說明:
msqid:消息隊列的用戶級標識符。
msgp:表示待發(fā)送的數據塊(輸出型參數)。
在這里插入圖片描述

msgsz:表示所發(fā)送數據塊的大小
msgflg:表示發(fā)送數據塊的方式,一般默認為0即可
成功返回0,失敗返回-1

3.2.4 消息隊列獲取msgrcv

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg)

參數跟上面msgsnd一致。

四、信號量

4.1 信號量概念

信號量本質上就是個計數器,它統(tǒng)計的是公共資源資源還剩多少。

公共資源:可以被多個進程同時訪問的資源,而如果訪問沒有被保護的公共資源,就會導致數據不一致問題(一個進程還在寫的時候另一個進程就開始讀)。所以公共資源需要保護,被保護起來的資源稱為臨界資源。而訪問這些臨界資源的那部分代碼稱為臨界區(qū)。其他的代碼就稱為非臨界區(qū)

保護公共資源:同步和互斥

互斥:當有多個進程想要訪問同一份資源的時候,我們只允許一個進程訪問,當這個進程訪問完了,下一個進程才能訪問。

原子性:要么不做,要么做完,只有這兩種狀態(tài)的情況。

既然我們想讓多個進程看到同一個計數器,那么信號量也是個公共資源

4.2 信號量的用處

舉個例子,假設我們要去看電影,而里面的座位只有我們買了票才能擁有,這里的票就是信號量,我們買了一張后,信號量就--。

所以當我們想要某種資源的時候,我們可以進行預定(買票成功)。
共享資源可以作為一個整體使用或者劃分成多個子資源部分。大部分都是整體使用,比如果管道。

如果我們申請成功,相當于我們預定了共享內存中的一小部分資源。如果不成功,就不能訪問共享資源,以達到保護其他進程的目的。

在訪問公共資源前要先申請信號量,而信號量本身就是個公共資源,那么信號量也帶保護自己的安全。那么如何保證呢?

4.3 信號量的pv操作

信號量操作本質上就是計數器的++或者--,是原子性的。當我們預定資源的時候(--)稱為p操作,釋放資源(++)稱為v操作。
如果信號量的初始值是1就代表了訪問公共資源作為一個整體來使用,一個進程申請了別的進程就不能再申請了,我們把只有兩種狀態(tài)的信號量稱為二元信號量。

4.4 信號量接口

4.4.1 信號量申請semget

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>int semget(key_t key, int nsems, int semflg);

參數介紹:

nsems:表示申請信號量的個數
第一個和第三個參數就跟前面的shmget相同。
返回值:信號量集創(chuàng)建成功時,semget函數返回的一個有效的信號量集標識符

4.4.2 信號量控制semctl

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semctl(int semid, int semnum, int cmd, ...);

參數介紹:
semid:信號量標識符
semnum:信號量的下標,默認0

4.4.3 信號量操作semop

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semop(int semid, struct sembuf *sops, unsigned nsops);

參數介紹:
sembuf:一個結構體

在這里插入圖片描述
sem_num:信號量下標。
sem_op:1表示++p操作,-1表示--v操作。
sem_flg:選項設為0即可。

nsops:有多少個sembuf結構體。

五、總結

我們可以發(fā)現,共享內存、消息隊列、信號量接口相似度非常高,尤其是獲取與刪除,這些都是system V標準的進程間通信
他們的第一個成員都是ipc_perm

struct ipc_perm {key_t          __key;    /* Key supplied to shmget(2) */uid_t          uid;      /* Effective UID of owner */gid_t          gid;      /* Effective GID of owner */uid_t          cuid;     /* Effective UID of creator */gid_t          cgid;     /* Effective GID of creator */unsigned short mode;     /* Permissions + SHM_DEST andSHM_LOCKED flags */unsigned short __seq;    /* Sequence number */};

我們可能會申請共享內存、消息隊列、信號量的任意一種,那么操作系統(tǒng)如何組織它們呢?

因為ipc_perm是一樣的,所以可以維護一個struct ipc_perm*的指針數組,存共享內存、消息隊列、信號量它們的第一個元素的地址,也就是&ipc_perm。
而我們知道結構體的第一個成員的地址和結構體對象的地址在數字上是相等的。

所以當我們想使用的時候直接強轉成想用的結構體(共享內存、消息隊列、信號量)就可以。

http://m.aloenet.com.cn/news/40021.html

相關文章:

  • 能免費做網站嗎信息流廣告模板
  • 成都定制企業(yè)網站制作免費學生網頁制作成品代碼
  • 專業(yè)手機網站制作公司網站快速排名服務商
  • 做網站開發(fā)人員架構市場營銷
  • win7如何做網站建立自己的網站平臺
  • 鋼管網站模板國外搜索引擎大全不屏蔽
  • 學做川菜的網站站長工具whois查詢
  • 山西電力建設三公司網站免費的行情網站app
  • 網站建設 公司 常見問題seo綜合查詢是什么
  • 湘潭網站建站公司武漢seo結算
  • 淄博的大型網站建設怎樣做網站
  • 網站建設費用能否計入開辦費百度論壇發(fā)帖
  • 新鄉(xiāng)市建設工程信息網seo工作內容有哪些
  • 深圳網站制作工作室百度推廣介紹
  • 工業(yè)設計相關網站公司官網搭建
  • 站長網站的優(yōu)勢百度網絡營銷中心
  • 西安做網站電話百度一下你就知道網頁
  • 佛山新網站制作平臺鄭州seo優(yōu)化公司
  • 門戶網站解決方案蘇州seo建站
  • 臨淄網站建設公司網站推廣搜索
  • 麗江網站建設怎么自己創(chuàng)建一個網站
  • ppt做視頻 模板下載網站營銷方式和渠道
  • 重慶網站建設合肥公司網站怎么宣傳
  • 做界面網站用什么語言seo教程
  • 青海住房與建設廳網站廣東網約車漲價
  • 用dw做淘客網站的步驟南京百度推廣開戶
  • 工控做網站網站免費軟件
  • 做企業(yè)網站注意些啥百度指數數據分析平臺官網
  • 專門做圖片的網站有哪些今日軍事新聞
  • 網站建設銷售實習服務營銷策劃方案