試述網(wǎng)站建設(shè)應(yīng)考慮哪些方面的問(wèn)題競(jìng)價(jià)排名的定義
文章目錄
- 計(jì)算機(jī)結(jié)構(gòu)
- 馮·諾依曼結(jié)構(gòu)
- 哈弗結(jié)構(gòu)
- 馮·諾依曼結(jié)構(gòu)與哈弗結(jié)構(gòu)對(duì)比
- 安卓采用的架構(gòu)
- 安卓操作系統(tǒng)
- 進(jìn)程間通訊(IPC)
- 內(nèi)存共享
- linux內(nèi)存共享
- 安卓?jī)?nèi)存共享
- 管道
- Unix Domain Socket
- 同步
- 常見(jiàn)同步機(jī)制
- 信號(hào)量
- Mutex
- 管程
- 安卓同步機(jī)制
- 安卓中的Mutex
- 安卓中的Condition
- Barrier
- Autolock
- 內(nèi)存管理
- 虛擬內(nèi)存
- mmap函數(shù)
計(jì)算機(jī)結(jié)構(gòu)
馮·諾依曼結(jié)構(gòu)
馮·諾依曼結(jié)構(gòu)(也稱(chēng)為存儲(chǔ)程序計(jì)算機(jī))是一種廣泛使用的計(jì)算機(jī)體系結(jié)構(gòu),是現(xiàn)代計(jì)算機(jī)設(shè)計(jì)的基礎(chǔ)。它是由馮·諾依曼(John von Neumann)于1945年提出的,這種結(jié)構(gòu)使用一個(gè)單一的存儲(chǔ)器來(lái)存儲(chǔ)指令和數(shù)據(jù),通過(guò)一個(gè)公共總線來(lái)傳輸指令和數(shù)據(jù)。
馮·諾依曼結(jié)構(gòu)的計(jì)算機(jī)由五個(gè)主要部件組成:中央處理器(CPU)、存儲(chǔ)器、輸入設(shè)備、輸出設(shè)備和控制器。CPU包括算術(shù)邏輯單元(ALU)和控制單元(CU),其中ALU負(fù)責(zé)執(zhí)行算術(shù)和邏輯操作,CU負(fù)責(zé)指令的解碼和執(zhí)行。
在馮·諾依曼結(jié)構(gòu)中,指令和數(shù)據(jù)存儲(chǔ)在同一個(gè)存儲(chǔ)器中,存儲(chǔ)器被劃分為一系列地址,每個(gè)地址存儲(chǔ)一個(gè)字節(jié)。CPU通過(guò)總線來(lái)訪問(wèn)存儲(chǔ)器,可以從任意地址讀取指令和數(shù)據(jù),并可以將結(jié)果寫(xiě)回到存儲(chǔ)器中。指令由操作碼和操作數(shù)組成,CPU從存儲(chǔ)器中讀取指令,并根據(jù)操作碼來(lái)執(zhí)行相應(yīng)的操作。
馮·諾依曼結(jié)構(gòu)的優(yōu)點(diǎn)是靈活性高,易于實(shí)現(xiàn)和擴(kuò)展,使得計(jì)算機(jī)可以執(zhí)行不同類(lèi)型的任務(wù)。但由于指令和數(shù)據(jù)共享同一條總線,因此讀取和寫(xiě)入指令和數(shù)據(jù)的速度會(huì)受到瓶頸的限制,這可能會(huì)影響計(jì)算機(jī)的性能。因此,在高性能計(jì)算機(jī)和嵌入式系統(tǒng)中,人們使用了一些改進(jìn)的結(jié)構(gòu)來(lái)克服這個(gè)問(wèn)題,如緩存和流水線等。
哈弗結(jié)構(gòu)
哈弗結(jié)構(gòu)(也稱(chēng)為分布式存儲(chǔ)器系統(tǒng))是一種常用于嵌入式系統(tǒng)的計(jì)算機(jī)體系結(jié)構(gòu)。哈弗結(jié)構(gòu)與馮·諾依曼結(jié)構(gòu)不同之處在于它使用了兩個(gè)獨(dú)立的存儲(chǔ)器,一個(gè)用于存儲(chǔ)指令,另一個(gè)用于存儲(chǔ)數(shù)據(jù),這兩個(gè)存儲(chǔ)器可以同時(shí)訪問(wèn)。
哈弗結(jié)構(gòu)的CPU包含兩個(gè)獨(dú)立的總線接口,一個(gè)用于訪問(wèn)指令存儲(chǔ)器,另一個(gè)用于訪問(wèn)數(shù)據(jù)存儲(chǔ)器。指令和數(shù)據(jù)分別存儲(chǔ)在兩個(gè)不同的存儲(chǔ)器中,因此可以在相同的時(shí)鐘周期內(nèi)同時(shí)從兩個(gè)存儲(chǔ)器中讀取數(shù)據(jù)。這種結(jié)構(gòu)可以提高計(jì)算機(jī)的運(yùn)行效率,減少指令和數(shù)據(jù)訪問(wèn)的沖突。
由于哈弗結(jié)構(gòu)使用了兩個(gè)獨(dú)立的存儲(chǔ)器,因此需要更多的硬件資源來(lái)實(shí)現(xiàn)它。此外,由于指令和數(shù)據(jù)存儲(chǔ)在不同的存儲(chǔ)器中,可能會(huì)導(dǎo)致一些困難,例如在程序中傳遞指針時(shí),需要將指針的值從數(shù)據(jù)存儲(chǔ)器中傳遞到指令存儲(chǔ)器中。這些問(wèn)題可以通過(guò)使用高級(jí)編程語(yǔ)言和編譯器來(lái)解決。
總的來(lái)說(shuō),哈弗結(jié)構(gòu)具有高效的優(yōu)點(diǎn),但也需要更多的硬件資源來(lái)實(shí)現(xiàn)。在嵌入式系統(tǒng)中,由于對(duì)運(yùn)行效率和資源的限制,哈弗結(jié)構(gòu)通常被廣泛使用。
馮·諾依曼結(jié)構(gòu)與哈弗結(jié)構(gòu)對(duì)比
馮·諾依曼結(jié)構(gòu)和哈佛結(jié)構(gòu)都是計(jì)算機(jī)體系結(jié)構(gòu)的基本形式,它們之間的主要區(qū)別在于存儲(chǔ)器和處理器之間的通信方式。
馮·諾依曼結(jié)構(gòu)使用同一條總線來(lái)傳輸指令和數(shù)據(jù)。指令和數(shù)據(jù)存儲(chǔ)在同一塊存儲(chǔ)器中,處理器通過(guò)總線讀取和寫(xiě)入存儲(chǔ)器中的指令和數(shù)據(jù)。這種結(jié)構(gòu)的優(yōu)點(diǎn)是靈活性高,易于實(shí)現(xiàn)和擴(kuò)展。然而,由于指令和數(shù)據(jù)共享同一條總線,導(dǎo)致指令和數(shù)據(jù)的讀取和寫(xiě)入不能同時(shí)進(jìn)行,因此會(huì)出現(xiàn)瓶頸問(wèn)題。
哈佛結(jié)構(gòu)則將指令存儲(chǔ)器和數(shù)據(jù)存儲(chǔ)器分開(kāi),分別使用不同的總線進(jìn)行通信。處理器可以同時(shí)從指令存儲(chǔ)器和數(shù)據(jù)存儲(chǔ)器中讀取數(shù)據(jù),因此具有更高的運(yùn)行效率。但是,由于指令和數(shù)據(jù)存儲(chǔ)在不同的存儲(chǔ)器中,需要更多的硬件資源來(lái)實(shí)現(xiàn)這種結(jié)構(gòu)。
總的來(lái)說(shuō),馮·諾依曼結(jié)構(gòu)具有靈活性高的優(yōu)點(diǎn),但指令和數(shù)據(jù)通信會(huì)出現(xiàn)瓶頸問(wèn)題;哈佛結(jié)構(gòu)具有更高的運(yùn)行效率,但需要更多的硬件資源來(lái)實(shí)現(xiàn)。
安卓采用的架構(gòu)
安卓采用的是馮·諾依曼結(jié)構(gòu)。
安卓是一個(gè)基于Linux內(nèi)核的移動(dòng)操作系統(tǒng),它使用了馮·諾依曼結(jié)構(gòu)作為計(jì)算機(jī)體系結(jié)構(gòu)。這是因?yàn)轳T·諾依曼結(jié)構(gòu)具有靈活性高、易于實(shí)現(xiàn)和擴(kuò)展等優(yōu)點(diǎn),可以讓計(jì)算機(jī)執(zhí)行不同類(lèi)型的任務(wù)。
在安卓中,所有的應(yīng)用程序和系統(tǒng)服務(wù)都是以二進(jìn)制代碼的形式存儲(chǔ)在內(nèi)存中,并且都使用相同的CPU和內(nèi)存。因此,采用馮·諾依曼結(jié)構(gòu)的計(jì)算機(jī)可以讓安卓系統(tǒng)更加高效地運(yùn)行,從而提供更好的用戶體驗(yàn)。
此外,安卓系統(tǒng)在架構(gòu)上也支持哈弗結(jié)構(gòu),但這種結(jié)構(gòu)通常用于一些嵌入式系統(tǒng),而不是移動(dòng)設(shè)備。因?yàn)楣ソY(jié)構(gòu)需要更多的硬件資源來(lái)實(shí)現(xiàn),這對(duì)于移動(dòng)設(shè)備來(lái)說(shuō)可能會(huì)影響性能和功耗。因此,馮·諾依曼結(jié)構(gòu)更適合用于移動(dòng)設(shè)備和操作系統(tǒng)。
安卓操作系統(tǒng)
安卓操作系統(tǒng)是基于Linux內(nèi)核開(kāi)發(fā)的移動(dòng)操作系統(tǒng),而Linux操作系統(tǒng)是一種開(kāi)源的自由操作系統(tǒng),其內(nèi)核也是Linux。
雖然安卓和Linux都使用了Linux內(nèi)核,但是它們?cè)诤芏喾矫嬗兴煌O旅媪信e一些主要的區(qū)別:
應(yīng)用程序框架不同:Linux操作系統(tǒng)的應(yīng)用程序主要是基于X11等桌面環(huán)境運(yùn)行的,而安卓的應(yīng)用程序框架是基于Java語(yǔ)言的。
用戶界面不同:Linux通常使用GNOME、KDE、XFCE等桌面環(huán)境,而安卓則使用自己的用戶界面。
設(shè)備驅(qū)動(dòng)程序不同:安卓使用特定于移動(dòng)設(shè)備的硬件驅(qū)動(dòng)程序,而Linux的驅(qū)動(dòng)程序則更加通用。
應(yīng)用程序管理方式不同:在Linux系統(tǒng)中,應(yīng)用程序的管理通常是基于包管理器的,而在安卓系統(tǒng)中則是通過(guò)應(yīng)用商店或APK安裝包的方式進(jìn)行管理。
安全性和隱私保護(hù)不同:安卓操作系統(tǒng)通常需要應(yīng)用程序請(qǐng)求權(quán)限才能訪問(wèn)用戶的敏感數(shù)據(jù),而Linux的用戶通常會(huì)通過(guò)sudo命令或者root權(quán)限來(lái)管理系統(tǒng),這樣可能會(huì)增加安全風(fēng)險(xiǎn)。
總之,雖然安卓操作系統(tǒng)和Linux操作系統(tǒng)都使用了Linux內(nèi)核,但是它們?cè)诤芏喾矫娑加兴煌?。安卓操作系統(tǒng)是專(zhuān)門(mén)為移動(dòng)設(shè)備而開(kāi)發(fā)的,而Linux操作系統(tǒng)則是通用的操作系統(tǒng),可以運(yùn)行在不同的計(jì)算機(jī)和設(shè)備上。
進(jìn)程間通訊(IPC)
內(nèi)存共享
linux內(nèi)存共享
Linux系統(tǒng)中實(shí)現(xiàn)共享內(nèi)存的方式也有多種,其中比較常用的方式是使用shmget()、shmat()等系統(tǒng)調(diào)用。
- 創(chuàng)建共享區(qū)域 shmget()
shmget()用于創(chuàng)建或訪問(wèn)一個(gè)共享內(nèi)存區(qū)域,如果該共享內(nèi)存區(qū)域不存在,則創(chuàng)建一個(gè)新的區(qū)域。如果區(qū)域已經(jīng)存在,則返回該區(qū)域的標(biāo)識(shí)符。
#include <sys/ipc.h>
#include <sys/shm.h>int shmget(key_t key, size_t size, int shmflg);
其中,key是共享內(nèi)存區(qū)域的鍵值,size是共享內(nèi)存區(qū)域的大小,shmflg是共享內(nèi)存區(qū)域的訪問(wèn)權(quán)限。
- shmat() 映射內(nèi)存共享
shmat()用于將一個(gè)共享內(nèi)存區(qū)域連接到調(diào)用進(jìn)程的地址空間中,并返回該內(nèi)存區(qū)域的起始地址。
#include <sys/types.h>
#include <sys/shm.h>void *shmat(int shmid, const void *shmaddr, int shmflg);
其中,shmid是共享內(nèi)存區(qū)域的標(biāo)識(shí)符,shmaddr是指定連接的地址,如果為NULL,則由系統(tǒng)自動(dòng)分配地址,shmflg是連接的選項(xiàng)。
安卓?jī)?nèi)存共享
實(shí)現(xiàn)共享內(nèi)存的方式有多種,其中比較常用的方式是使用匿名映射和共享文件映射。
- 匿名映射
匿名映射是指創(chuàng)建一個(gè)匿名的內(nèi)存區(qū)域,并映射到不同的進(jìn)程中。在安卓系統(tǒng)中,使用mmap()函數(shù)來(lái)創(chuàng)建匿名映射。
在進(jìn)程A中,可以通過(guò)以下方式創(chuàng)建一個(gè)匿名映射區(qū)域:
void *shared_memory = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
其中,size表示要?jiǎng)?chuàng)建的映射區(qū)域的大小,PROT_READ和PROT_WRITE表示映射區(qū)域可以讀寫(xiě),MAP_SHARED表示映射區(qū)域是共享的,-1表示使用系統(tǒng)自動(dòng)分配的地址,0表示起始偏移量為0。
在進(jìn)程B中,也可以通過(guò)相同的方式映射同一個(gè)地址:
void *shared_memory = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
此時(shí)進(jìn)程A和進(jìn)程B都可以通過(guò)shared_memory來(lái)訪問(wèn)同一塊物理內(nèi)存區(qū)域,從而實(shí)現(xiàn)共享內(nèi)存的目的。
- 共享文件映射
共享文件映射是指將同一個(gè)文件映射到不同進(jìn)程的地址空間中,從而實(shí)現(xiàn)不同進(jìn)程之間的內(nèi)存共享。在安卓系統(tǒng)中,使用mmap()函數(shù)來(lái)創(chuàng)建共享文件映射。
在進(jìn)程A中,可以通過(guò)以下方式創(chuàng)建一個(gè)共享文件映射區(qū)域:
int fd = open("shared_file", O_RDWR|O_CREAT, 0666);
ftruncate(fd, size);
void *shared_memory = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
其中,open()函數(shù)用于打開(kāi)一個(gè)共享文件,ftruncate()函數(shù)用于設(shè)置文件大小,mmap()函數(shù)用于將文件映射到進(jìn)程A的地址空間中。
在進(jìn)程B中,也可以通過(guò)相同的方式映射同一個(gè)文件:
int fd = open("shared_file", O_RDWR, 0666);
void *shared_memory = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
此時(shí)進(jìn)程A和進(jìn)程B都可以通過(guò)shared_memory來(lái)訪問(wèn)同一塊物理內(nèi)存區(qū)域,從而實(shí)現(xiàn)共享內(nèi)存的目的。
管道
在Linux系統(tǒng)中,進(jìn)程間通信是一個(gè)重要的概念。管道是一種進(jìn)程間通信的方式,它可以將一個(gè)進(jìn)程的輸出傳遞給另一個(gè)進(jìn)程的輸入,從而實(shí)現(xiàn)兩個(gè)進(jìn)程之間的通信。
管道的基本原理是通過(guò)創(chuàng)建一個(gè)臨時(shí)文件來(lái)實(shí)現(xiàn)數(shù)據(jù)傳輸。在Linux系統(tǒng)中,管道被實(shí)現(xiàn)為一種特殊的文件,它具有以下特點(diǎn):
- 管道是一個(gè)半雙工的通道,即只能從一端讀取數(shù)據(jù),從另一端寫(xiě)入數(shù)據(jù);
- 管道通常用于父子進(jìn)程之間的通信,父進(jìn)程可以將數(shù)據(jù)寫(xiě)入管道,子進(jìn)程可以從管道中讀取數(shù)據(jù);
- 管道有一個(gè)固定的緩沖區(qū)大小,當(dāng)緩沖區(qū)滿時(shí),寫(xiě)入操作會(huì)被阻塞,直到有足夠的空間;
- 管道是一個(gè)臨時(shí)文件,當(dāng)所有相關(guān)的進(jìn)程都關(guān)閉了管道之后,操作系統(tǒng)會(huì)自動(dòng)刪除這個(gè)文件。
Unix Domain Socket
Unix Domain Socket是一種Unix/Linux操作系統(tǒng)中的進(jìn)程間通信方式。它是基于套接字(Socket)技術(shù)實(shí)現(xiàn)的,與網(wǎng)絡(luò)套接字不同的是,Unix Domain Socket不需要通過(guò)網(wǎng)絡(luò)協(xié)議棧,而是直接在內(nèi)核中進(jìn)行進(jìn)程間通信。
Unix Domain Socket可以看作是一種本地IPC(Inter-Process Communication)方式,它可以在同一臺(tái)計(jì)算機(jī)上的不同進(jìn)程之間進(jìn)行通信。使用Unix Domain Socket進(jìn)行通信的進(jìn)程之間可以是任意兩個(gè)進(jìn)程,它們可以是父子進(jìn)程、兄弟進(jìn)程、甚至不在同一個(gè)進(jìn)程組中的進(jìn)程。
Unix Domain Socket通常使用流式套接字(SOCK_STREAM)或數(shù)據(jù)報(bào)套接字(SOCK_DGRAM)進(jìn)行通信。流式套接字提供一種可靠的、面向連接的通信方式,類(lèi)似于TCP協(xié)議;數(shù)據(jù)報(bào)套接字則提供一種不可靠的、無(wú)連接的通信方式,類(lèi)似于UDP協(xié)議。Unix Domain Socket支持多種通信方式,包括點(diǎn)對(duì)點(diǎn)通信、廣播通信和多播通信。
Unix Domain Socket(UDS)是專(zhuān)門(mén)針對(duì)單機(jī)內(nèi)的進(jìn)程間通信提出來(lái)的,有時(shí)也被稱(chēng)為IPC
Socket。兩者雖然在使用方法上類(lèi)似,但內(nèi)部實(shí)現(xiàn)原理卻有著很大區(qū)別。大家所熟識(shí)的Network
Socket是以TCP/IP協(xié)議棧為基礎(chǔ)的,需要分包、重組等一系列操作。而 UDS因?yàn)槭潜緳C(jī)內(nèi)的“安
全可靠操作”,實(shí)現(xiàn)機(jī)制上并不依賴(lài)于這些協(xié)議。
Android中使用最多的一種IPC機(jī)制是Binder,其次就是UDS。相關(guān)資料顯示,2.2版本以前
的Android系統(tǒng),曾使用Binder作為整個(gè)GUI架構(gòu)中的進(jìn)程間通信基礎(chǔ)。后來(lái)因某些原因不得不
棄之而用UDS,可見(jiàn)后者還是有一定優(yōu)勢(shì)的。
Unix Domain Socket的優(yōu)點(diǎn)包括:
它是一種高效的進(jìn)程間通信方式,因?yàn)樗恍枰?jīng)過(guò)網(wǎng)絡(luò)協(xié)議棧,通信速度比較快;
它支持多種通信方式,能夠滿足不同的通信需求;
它可以在同一臺(tái)計(jì)算機(jī)上進(jìn)行通信,避免了網(wǎng)絡(luò)傳輸帶來(lái)的延遲和不穩(wěn)定性;
它可以通過(guò)文件系統(tǒng)進(jìn)行權(quán)限控制,確保通信的安全性。
在Unix/Linux系統(tǒng)中,使用Unix Domain Socket進(jìn)行進(jìn)程間通信非常常見(jiàn),很多系統(tǒng)服務(wù)和應(yīng)用程序都使用Unix Domain Socket來(lái)實(shí)現(xiàn)進(jìn)程間通信。例如,Apache Web服務(wù)器和PHP-FPM之間就使用Unix Domain Socket進(jìn)行通信,以提高Web服務(wù)器的性能。
同步
常見(jiàn)同步機(jī)制
信號(hào)量
信號(hào)量(Semaphore)是一種用于多進(jìn)程或多線程之間同步和互斥的機(jī)制。它通常被用于控制對(duì)共享資源的訪問(wèn),以避免多個(gè)進(jìn)程或線程同時(shí)訪問(wèn)共享資源而引發(fā)的問(wèn)題,如競(jìng)態(tài)條件、死鎖等。
信號(hào)量的實(shí)現(xiàn)通?;谝粋€(gè)計(jì)數(shù)器和一個(gè)等待隊(duì)列。計(jì)數(shù)器用于記錄可用的資源數(shù)量,等待隊(duì)列用于記錄等待該資源的進(jìn)程或線程。當(dāng)一個(gè)進(jìn)程或線程需要訪問(wèn)共享資源時(shí),它會(huì)嘗試獲取信號(hào)量。如果計(jì)數(shù)器的值大于0,則該進(jìn)程或線程可以訪問(wèn)共享資源,并將計(jì)數(shù)器的值減1;否則,該進(jìn)程或線程會(huì)進(jìn)入等待隊(duì)列等待資源的釋放。
當(dāng)另一個(gè)進(jìn)程或線程釋放了該共享資源時(shí),它會(huì)調(diào)用信號(hào)量的V操作(也稱(chēng)為“發(fā)信號(hào)”操作),將計(jì)數(shù)器的值加1,同時(shí)喚醒等待隊(duì)列中的一個(gè)進(jìn)程或線程,讓其可以訪問(wèn)共享資源。
在Linux系統(tǒng)中,信號(hào)量的實(shí)現(xiàn)是通過(guò)系統(tǒng)調(diào)用semget、semop和semctl來(lái)完成的。其中,semget用于創(chuàng)建或獲取一個(gè)信號(hào)量集;semop用于對(duì)信號(hào)量進(jìn)行操作,如P操作(也稱(chēng)為“等待”操作)和V操作(也稱(chēng)為“發(fā)信號(hào)”操作);semctl用于對(duì)信號(hào)量進(jìn)行控制操作,如獲取或設(shè)置信號(hào)量的值、刪除信號(hào)量等。
使用信號(hào)量可以有效地實(shí)現(xiàn)進(jìn)程或線程之間的同步和互斥,避免了資源競(jìng)爭(zhēng)和死鎖等問(wèn)題。但是,使用不當(dāng)也可能會(huì)引發(fā)一些問(wèn)題,如信號(hào)量的數(shù)量過(guò)多會(huì)增加系統(tǒng)的開(kāi)銷(xiāo),信號(hào)量的使用不當(dāng)可能會(huì)引發(fā)饑餓問(wèn)題等。因此,在使用信號(hào)量時(shí)需要仔細(xì)設(shè)計(jì)和實(shí)現(xiàn),以確保程序的正確性和性能。
Mutex
Mutex是一種用于多線程之間同步和互斥的機(jī)制。它通常被用于控制對(duì)共享資源的訪問(wèn),以避免多個(gè)線程同時(shí)訪問(wèn)共享資源而引發(fā)的問(wèn)題,如競(jìng)態(tài)條件、死鎖等。
Mutex的實(shí)現(xiàn)通常基于一個(gè)標(biāo)志位和一個(gè)等待隊(duì)列。標(biāo)志位用于記錄當(dāng)前是否有線程正在訪問(wèn)共享資源,等待隊(duì)列用于記錄等待該資源的線程。當(dāng)一個(gè)線程需要訪問(wèn)共享資源時(shí),它會(huì)嘗試獲取Mutex。如果標(biāo)志位的值為0,則該線程可以訪問(wèn)共享資源,并將標(biāo)志位的值設(shè)置為1;否則,該線程會(huì)進(jìn)入等待隊(duì)列等待資源的釋放。
當(dāng)另一個(gè)線程釋放了該共享資源時(shí),它會(huì)將標(biāo)志位的值設(shè)置為0,并喚醒等待隊(duì)列中的一個(gè)線程,讓其可以訪問(wèn)共享資源。
在Linux系統(tǒng)中,Mutex的實(shí)現(xiàn)通?;诨コ怄i(Mutex Lock)來(lái)完成。互斥鎖是一種可重入的、線程安全的鎖,它提供了兩個(gè)主要操作:lock和unlock。當(dāng)一個(gè)線程需要訪問(wèn)共享資源時(shí),它會(huì)調(diào)用lock操作來(lái)獲取互斥鎖;當(dāng)它完成訪問(wèn)后,會(huì)調(diào)用unlock操作來(lái)釋放互斥鎖。如果另一個(gè)線程試圖獲取已經(jīng)被鎖定的互斥鎖,它會(huì)被阻塞直到鎖被釋放。
管程
管程(Monitor)是一種高級(jí)同步機(jī)制,它提供了一種結(jié)構(gòu)化的方式來(lái)實(shí)現(xiàn)并發(fā)程序的同步和互斥。它通常用于多個(gè)線程之間共享資源,如共享內(nèi)存區(qū)域、共享文件、網(wǎng)絡(luò)連接等。
管程由一個(gè)包含多個(gè)過(guò)程(Procedure)和數(shù)據(jù)的單元組成,其中過(guò)程可以被多個(gè)線程調(diào)用來(lái)訪問(wèn)管程中的數(shù)據(jù)。管程提供了一種機(jī)制,確保同一時(shí)間只有一個(gè)線程可以訪問(wèn)管程中的數(shù)據(jù),從而避免了多個(gè)線程同時(shí)訪問(wèn)數(shù)據(jù)的問(wèn)題。
管程中通常包含了互斥量、條件變量等同步機(jī)制,用于實(shí)現(xiàn)同步和互斥。當(dāng)一個(gè)線程需要訪問(wèn)管程中的數(shù)據(jù)時(shí),它會(huì)首先嘗試獲取互斥量,以避免多個(gè)線程同時(shí)訪問(wèn)管程中的數(shù)據(jù);然后,它會(huì)進(jìn)入等待狀態(tài),直到條件變量滿足某個(gè)條件。當(dāng)另一個(gè)線程修改了數(shù)據(jù)并滿足了條件時(shí),它會(huì)通知等待線程,并將互斥量釋放,讓等待線程可以訪問(wèn)數(shù)據(jù)。
管程的實(shí)現(xiàn)通常依賴(lài)于操作系統(tǒng)提供的同步機(jī)制,如互斥鎖、條件變量等。在不同的操作系統(tǒng)中,管程的實(shí)現(xiàn)可能會(huì)有所不同。在一些現(xiàn)代的編程語(yǔ)言中,如Java、Python等,也提供了管程的原語(yǔ)和API,方便開(kāi)發(fā)者使用。
總的來(lái)說(shuō),管程是一種高級(jí)的同步機(jī)制,可以提供一種結(jié)構(gòu)化的方式來(lái)實(shí)現(xiàn)并發(fā)程序的同步和互斥,避免了多個(gè)線程同時(shí)訪問(wèn)共享資源的問(wèn)題,提高了程序的可維護(hù)性和可讀性
安卓同步機(jī)制
安卓中的Mutex
在Android中,Mutex(互斥鎖)是一種同步機(jī)制,用于控制多個(gè)線程對(duì)共享資源的訪問(wèn)。Mutex可以用于實(shí)現(xiàn)多個(gè)線程對(duì)某一資源的互斥訪問(wèn),以避免多個(gè)線程同時(shí)訪問(wèn)該資源導(dǎo)致的數(shù)據(jù)競(jìng)爭(zhēng)和不一致性。在Android中,可以使用Java中的java.util.concurrent.locks包中的ReentrantLock來(lái)實(shí)現(xiàn)Mutex。
ReentrantLock是一個(gè)可重入的互斥鎖,支持公平或非公平的鎖。ReentrantLock提供了lock()和unlock()方法來(lái)獲取和釋放鎖,與synchronized關(guān)鍵字類(lèi)似,但是它提供了更多的靈活性和控制。例如,ReentrantLock提供了tryLock()方法來(lái)嘗試獲取鎖,如果鎖已被占用則返回false,而不是像synchronized關(guān)鍵字一樣一直阻塞等待鎖的釋放。此外,ReentrantLock還提供了lockInterruptibly()方法來(lái)實(shí)現(xiàn)可中斷的鎖,即在等待鎖的過(guò)程中可以響應(yīng)中斷信號(hào)。
除了lock()和unlock()方法外,ReentrantLock還提供了其他方法和特性。例如,ReentrantLock可以實(shí)現(xiàn)公平鎖,即多個(gè)線程等待鎖時(shí)會(huì)按照先后順序獲取鎖,從而避免饑餓現(xiàn)象。此外,ReentrantLock還提供了Condition對(duì)象來(lái)實(shí)現(xiàn)更為復(fù)雜的線程間通信和同步機(jī)制。通過(guò)Condition對(duì)象,線程可以等待某個(gè)條件滿足時(shí)再繼續(xù)執(zhí)行,或者喚醒其他等待條件的線程。
在Android中,Mutex通常用于控制對(duì)共享資源的訪問(wèn)。例如,在多個(gè)線程同時(shí)訪問(wèn)某一文件時(shí),可以使用Mutex來(lái)實(shí)現(xiàn)對(duì)該文件的互斥訪問(wèn),以避免數(shù)據(jù)競(jìng)爭(zhēng)和不一致性。另外,在Android中使用Binder通信時(shí),也可以使用Mutex來(lái)實(shí)現(xiàn)對(duì)共享資源的同步訪問(wèn)。例如,在多個(gè)進(jìn)程間共享某一資源時(shí),可以使用Mutex來(lái)控制進(jìn)程對(duì)該資源的訪問(wèn),以保證數(shù)據(jù)的一致性和正確性。
安卓中的Condition
在Android中,Condition是一種同步機(jī)制,它是基于Lock(鎖)的。Condition允許線程等待某個(gè)條件滿足后再繼續(xù)執(zhí)行,這個(gè)條件可以是另一個(gè)線程通知的,也可以是其他事件發(fā)生的。在Java中,Condition接口定義在java.util.concurrent.locks包中,它是Lock的一個(gè)附屬對(duì)象。
Condition對(duì)象可以通過(guò)Lock的newCondition()方法創(chuàng)建,每個(gè)Condition對(duì)象都與一個(gè)Lock對(duì)象關(guān)聯(lián)。Condition提供了await()、signal()和signalAll()方法來(lái)實(shí)現(xiàn)等待和通知機(jī)制。
await()方法會(huì)使當(dāng)前線程等待,直到另一個(gè)線程通知或中斷它。調(diào)用await()方法會(huì)釋放當(dāng)前線程持有的鎖,同時(shí)讓線程進(jìn)入等待狀態(tài)。當(dāng)另一個(gè)線程調(diào)用相應(yīng)的signal()或signalAll()方法來(lái)通知當(dāng)前線程時(shí),當(dāng)前線程才會(huì)重新獲取鎖并繼續(xù)執(zhí)行。
signal()方法會(huì)通知一個(gè)等待在該Condition對(duì)象上的線程,使其從等待狀態(tài)返回。如果有多個(gè)線程在等待,則會(huì)通知其中的一個(gè)線程,通常是等待時(shí)間最長(zhǎng)的線程。signalAll()方法會(huì)通知所有等待在該Condition對(duì)象上的線程,使它們從等待狀態(tài)返回。
在Android中,Condition通常與Lock一起使用,用于實(shí)現(xiàn)更為復(fù)雜的同步機(jī)制。例如,在多個(gè)線程之間共享某一資源時(shí),可以使用Lock和Condition來(lái)實(shí)現(xiàn)對(duì)該資源的互斥訪問(wèn)和同步操作,以避免數(shù)據(jù)競(jìng)爭(zhēng)和不一致性。另外,在Android中使用Binder通信時(shí),也可以使用Condition來(lái)實(shí)現(xiàn)對(duì)共享資源的同步訪問(wèn)。例如,在多個(gè)進(jìn)程間共享某一資源時(shí),可以使用Lock和Condition來(lái)控制進(jìn)程對(duì)該資源的訪問(wèn),以保證數(shù)據(jù)的一致性和正確性。
使用場(chǎng)景:
-
生產(chǎn)者-消費(fèi)者模型:在多線程環(huán)境下,如果一個(gè)或多個(gè)線程生產(chǎn)數(shù)據(jù),另外一個(gè)或多個(gè)線程消費(fèi)數(shù)據(jù),就會(huì)出現(xiàn)數(shù)據(jù)競(jìng)爭(zhēng)問(wèn)題。為了解決這個(gè)問(wèn)題,可以使用Condition來(lái)實(shí)現(xiàn)線程間的同步。生產(chǎn)者在生產(chǎn)數(shù)據(jù)后通過(guò)Condition喚醒等待的消費(fèi)者,消費(fèi)者在消費(fèi)數(shù)據(jù)后通過(guò)Condition喚醒等待的生產(chǎn)者。
-
讀寫(xiě)鎖:在多線程環(huán)境下,如果多個(gè)線程同時(shí)讀取共享資源,而只有一個(gè)線程寫(xiě)入共享資源,那么就需要使用讀寫(xiě)鎖來(lái)實(shí)現(xiàn)對(duì)共享資源的同步訪問(wèn)??梢允褂肅ondition來(lái)實(shí)現(xiàn)讀寫(xiě)鎖的等待和通知機(jī)制,實(shí)現(xiàn)對(duì)共享資源的同步訪問(wèn)。
-
任務(wù)隊(duì)列:在多線程環(huán)境下,如果有多個(gè)線程需要執(zhí)行一些任務(wù),那么可以使用任務(wù)隊(duì)列來(lái)實(shí)現(xiàn)對(duì)任務(wù)的管理和調(diào)度。可以使用Condition來(lái)實(shí)現(xiàn)任務(wù)隊(duì)列的等待和通知機(jī)制,以確保線程按照指定的順序執(zhí)行任務(wù)。
-
線程池:在多線程環(huán)境下,如果需要?jiǎng)?chuàng)建一個(gè)線程池來(lái)管理多個(gè)線程,那么可以使用Condition來(lái)實(shí)現(xiàn)對(duì)線程池的等待和通知機(jī)制,以確保線程池中的線程按照指定的順序執(zhí)行任務(wù)。
Barrier
Barrier是一種線程同步機(jī)制,用于實(shí)現(xiàn)多個(gè)線程之間的同步和協(xié)作。它可以使一組線程在某個(gè)點(diǎn)上同步等待,直到所有線程都到達(dá)該點(diǎn)后才繼續(xù)執(zhí)行。在多線程編程中,Barrier被廣泛用于控制線程的執(zhí)行順序和協(xié)調(diào)線程之間的交互。它可以用于解決一些并發(fā)編程中的難題,比如循環(huán)屏障和分治算法等。
在Java中,Barrier通常使用java.util.concurrent.CyclicBarrier類(lèi)來(lái)實(shí)現(xiàn)。它的使用方法與CountDownLatch類(lèi)似,都是通過(guò)調(diào)用await()方法來(lái)等待其他線程的到達(dá)。不同之處在于,CyclicBarrier可以重復(fù)使用,即在所有線程到達(dá)屏障后,它會(huì)自動(dòng)重置為初始狀態(tài),從而可以在之后的程序中繼續(xù)使用。
下面是CyclicBarrier的一些常用方法和特點(diǎn):
CyclicBarrier(int parties): 創(chuàng)建一個(gè)CyclicBarrier實(shí)例,指定需要同步的線程數(shù)。
await(): 當(dāng)線程到達(dá)屏障時(shí)調(diào)用,如果還有其他線程未到達(dá),則該線程將阻塞等待。
reset(): 重置屏障狀態(tài),使得CyclicBarrier可以被重復(fù)使用。
在Android中,CyclicBarrier可以用于實(shí)現(xiàn)多線程操作,例如在后臺(tái)線程中執(zhí)行耗時(shí)任務(wù),然后將結(jié)果傳遞給UI線程進(jìn)行更新。它也可以用于實(shí)現(xiàn)并發(fā)算法,比如分治算法,以提高程序的性能和效率。
總之,CyclicBarrier是一種高效的線程同步機(jī)制,可以幫助我們處理多線程編程中的復(fù)雜問(wèn)題。在Android中,使用CyclicBarrier可以提高程序的并發(fā)性和可靠性,從而滿足用戶的需求。
Autolock
AutoLock是一種自動(dòng)鎖定機(jī)制,用于簡(jiǎn)化線程鎖定的代碼實(shí)現(xiàn)。在多線程編程中,鎖是一種常見(jiàn)的同步機(jī)制,用于保證對(duì)共享資源的互斥訪問(wèn),防止競(jìng)態(tài)條件和數(shù)據(jù)競(jìng)爭(zhēng)等問(wèn)題。傳統(tǒng)的鎖定方式需要手動(dòng)加鎖和解鎖,代碼實(shí)現(xiàn)比較繁瑣且容易出錯(cuò)。而AutoLock可以自動(dòng)管理鎖定和解鎖的過(guò)程,從而使代碼更加簡(jiǎn)潔和易于維護(hù)。
在Java中,AutoLock通常使用try-finally語(yǔ)句塊來(lái)實(shí)現(xiàn),例如:
Lock lock = new ReentrantLock();
lock.lock();
try {// 訪問(wèn)共享資源
} finally {lock.unlock();
}
上述代碼中,try-finally語(yǔ)句塊會(huì)確保鎖定的釋放,即使在訪問(wèn)共享資源時(shí)發(fā)生異常也能保證鎖定的正確釋放。這種方式雖然能夠確保鎖定的正確性,但是代碼比較冗長(zhǎng),不易于維護(hù)。
為了簡(jiǎn)化鎖定的代碼實(shí)現(xiàn),Java提供了AutoLock機(jī)制。使用AutoLock可以將鎖定和解鎖的過(guò)程自動(dòng)化,例如:
Lock lock = new ReentrantLock();
try (AutoLock ignored = AutoLock.lock(lock)) {// 訪問(wèn)共享資源
}
上述代碼中,AutoLock的lock方法會(huì)獲取指定的鎖,并返回一個(gè)AutoLock對(duì)象。當(dāng)代碼塊執(zhí)行完畢后,AutoLock對(duì)象會(huì)自動(dòng)釋放鎖定,從而避免了手動(dòng)解鎖的過(guò)程。這種方式比傳統(tǒng)的try-finally語(yǔ)句塊更加簡(jiǎn)潔和易于使用。
在Android中,AutoLock同樣可以用于簡(jiǎn)化線程鎖定的代碼實(shí)現(xiàn)。它可以幫助我們處理多線程編程中的復(fù)雜問(wèn)題,提高代碼的可讀性和可維護(hù)性,從而更好地滿足用戶的需求。
內(nèi)存管理
虛擬內(nèi)存
虛擬內(nèi)存是一種計(jì)算機(jī)內(nèi)存管理技術(shù),它將計(jì)算機(jī)主存(RAM)抽象為一種看似無(wú)限大的地址空間,這個(gè)地址空間被稱(chēng)為虛擬地址空間。虛擬內(nèi)存的實(shí)現(xiàn)方式是通過(guò)將主存和磁盤(pán)存儲(chǔ)器結(jié)合使用,使得程序能夠訪問(wèn)比實(shí)際內(nèi)存更大的地址空間。
虛擬內(nèi)存的主要優(yōu)勢(shì)在于它能夠讓多個(gè)進(jìn)程同時(shí)運(yùn)行,并且在運(yùn)行過(guò)程中它們都能夠訪問(wèn)到自己的地址空間,從而實(shí)現(xiàn)了內(nèi)存隔離。此外,虛擬內(nèi)存還能夠?qū)⒋疟P(pán)上的文件映射到虛擬地址空間中,這樣程序就可以像訪問(wèn)內(nèi)存一樣訪問(wèn)文件。
在虛擬內(nèi)存中,每個(gè)進(jìn)程都有自己的虛擬地址空間,這個(gè)地址空間包含了程序所需的所有內(nèi)存。進(jìn)程使用的每個(gè)虛擬地址都被映射到實(shí)際的物理地址上。當(dāng)進(jìn)程訪問(wèn)一個(gè)虛擬地址時(shí),虛擬內(nèi)存會(huì)自動(dòng)將這個(gè)虛擬地址映射到實(shí)際的物理地址上。如果這個(gè)虛擬地址對(duì)應(yīng)的物理地址不在主存中,虛擬內(nèi)存會(huì)從磁盤(pán)中讀取相應(yīng)的數(shù)據(jù)到內(nèi)存中,并將這個(gè)數(shù)據(jù)的虛擬地址映射到實(shí)際的物理地址上。
虛擬內(nèi)存的實(shí)現(xiàn)需要使用到頁(yè)表和頁(yè)式存儲(chǔ)技術(shù)。頁(yè)表是一個(gè)數(shù)據(jù)結(jié)構(gòu),用于記錄虛擬地址和物理地址之間的映射關(guān)系。頁(yè)式存儲(chǔ)是一種存儲(chǔ)管理技術(shù),它將物理內(nèi)存和虛擬地址空間都分成固定大小的頁(yè)。當(dāng)進(jìn)程訪問(wèn)一個(gè)虛擬地址時(shí),虛擬內(nèi)存會(huì)將這個(gè)地址轉(zhuǎn)換成頁(yè)號(hào)和頁(yè)內(nèi)偏移量,然后使用頁(yè)表查找這個(gè)虛擬地址對(duì)應(yīng)的物理地址。如果這個(gè)物理地址不在主存中,虛擬內(nèi)存會(huì)將需要的頁(yè)面從磁盤(pán)中讀取到主存中,并更新頁(yè)表中的映射關(guān)系。
虛擬內(nèi)存的實(shí)現(xiàn)方式有多種,包括分頁(yè)式、分段式和混合式等。其中,分頁(yè)式是最常見(jiàn)的實(shí)現(xiàn)方式,它將主存和虛擬地址空間都分成固定大小的頁(yè)面,并使用頁(yè)表來(lái)實(shí)現(xiàn)地址轉(zhuǎn)換。虛擬內(nèi)存的大小可以通過(guò)修改操作系統(tǒng)的參數(shù)來(lái)調(diào)整,不同的操作系統(tǒng)和硬件平臺(tái)支持的最大虛擬內(nèi)存大小也不盡相同。
理解虛擬內(nèi)存機(jī)制,首先要學(xué)習(xí)三種不同的地址空間。
- 邏輯地址
邏輯地址是指程序在運(yùn)行時(shí)所使用的地址,也稱(chēng)為虛擬地址。每個(gè)程序都有自己獨(dú)立的虛擬地址空間,相互之間不會(huì)干擾。邏輯地址由操作系統(tǒng)管理,由CPU產(chǎn)生,用于指令和數(shù)據(jù)的尋址。
邏輯地址由兩個(gè)部分組成:段地址和偏移地址。其中,段地址指明程序中的某一段內(nèi)存空間,可以是代碼段、數(shù)據(jù)段、堆棧段等,偏移地址則是該段內(nèi)部的相對(duì)地址,表示距離該段起始地址的偏移量。通過(guò)這兩部分地址可以唯一地確定程序中的某個(gè)內(nèi)存單元。
邏輯地址的使用可以為程序提供了更大的內(nèi)存空間,因?yàn)椴僮飨到y(tǒng)可以將物理內(nèi)存分成多個(gè)虛擬地址空間,每個(gè)程序都有自己的虛擬地址空間,而不必?fù)?dān)心物理內(nèi)存的限制。此外,邏輯地址還為操作系統(tǒng)提供了更好的內(nèi)存管理能力。在使用邏輯地址時(shí),操作系統(tǒng)可以將程序需要的內(nèi)存空間劃分成多個(gè)段,對(duì)每個(gè)段進(jìn)行保護(hù)和管理,從而保證程序之間的內(nèi)存空間不會(huì)互相干擾。
邏輯地址的使用還可以方便地實(shí)現(xiàn)動(dòng)態(tài)鏈接、虛擬內(nèi)存等功能。動(dòng)態(tài)鏈接是指程序在運(yùn)行時(shí)才會(huì)根據(jù)需要鏈接所需的庫(kù)文件,而不是在編譯時(shí)就將庫(kù)文件鏈接進(jìn)程序中。虛擬內(nèi)存是指將部分程序數(shù)據(jù)暫時(shí)存儲(chǔ)在硬盤(pán)上,以釋放物理內(nèi)存,待需要時(shí)再將其調(diào)入內(nèi)存,從而擴(kuò)大程序可以使用的內(nèi)存空間。
- 線性地址
線性地址是由虛擬地址通過(guò)頁(yè)表映射得到的,它具有以下兩個(gè)特征:
-
線性地址是連續(xù)的,這意味著CPU可以將它們視為一個(gè)大的地址空間,而不必?fù)?dān)心實(shí)際內(nèi)存中的數(shù)據(jù)在哪里存儲(chǔ)。
-
線性地址是與物理地址分離的。物理地址是在RAM中分配的實(shí)際內(nèi)存地址,而線性地址是虛擬地址,可以映射到任何物理地址。
因此,虛擬內(nèi)存和線性地址允許操作系統(tǒng)和CPU管理內(nèi)存,使多個(gè)進(jìn)程可以共享相同的物理內(nèi)存而不會(huì)互相干擾,也可以保護(hù)進(jìn)程不受其他進(jìn)程的干擾。同時(shí),虛擬內(nèi)存也為操作系統(tǒng)提供了一種將內(nèi)存映射到磁盤(pán)上的方法,從而使操作系統(tǒng)能夠更有效地使用系統(tǒng)資源。
- 物理地址
物理地址是指實(shí)際的硬件地址,是計(jì)算機(jī)內(nèi)存中每個(gè)存儲(chǔ)單元的唯一地址。在計(jì)算機(jī)系統(tǒng)中,程序代碼和數(shù)據(jù)必須存儲(chǔ)在內(nèi)存中才能被CPU訪問(wèn),而CPU訪問(wèn)內(nèi)存時(shí)需要使用物理地址。
物理地址與邏輯地址和線性地址相對(duì)應(yīng)。邏輯地址是程序代碼中使用的地址,由程序生成,而不是實(shí)際存在于內(nèi)存中的地址。線性地址是虛擬地址,通過(guò)頁(yè)表映射得到的地址。物理地址是實(shí)際存在于內(nèi)存中的地址,它是通過(guò)線性地址再次映射得到的。
物理地址是在計(jì)算機(jī)系統(tǒng)中非常重要的概念,因?yàn)樗鼪Q定了CPU訪問(wèn)內(nèi)存時(shí)的實(shí)際位置。操作系統(tǒng)負(fù)責(zé)將邏輯地址或線性地址映射到物理地址,這個(gè)過(guò)程通常是由CPU的內(nèi)存管理單元(MMU)來(lái)處理的。
在訪問(wèn)內(nèi)存時(shí),CPU將邏輯地址或線性地址發(fā)送到MMU中,MMU通過(guò)頁(yè)表將線性地址映射到物理地址。然后,CPU使用物理地址從內(nèi)存中讀取數(shù)據(jù)或?qū)懭霐?shù)據(jù)。
物理地址的大小由計(jì)算機(jī)系統(tǒng)的架構(gòu)和硬件決定。在32位系統(tǒng)中,物理地址通常是32位長(zhǎng),可以尋址最多4GB的內(nèi)存。而在64位系統(tǒng)中,物理地址通常是64位長(zhǎng),可以尋址的內(nèi)存空間非常巨大,遠(yuǎn)遠(yuǎn)超過(guò)目前可用的物理內(nèi)存容量。
mmap函數(shù)
mmap() 是一個(gè) UNIX/Linux 操作系統(tǒng)下的系統(tǒng)調(diào)用函數(shù),主要用于實(shí)現(xiàn)文件的內(nèi)存映射操作。mmap() 函數(shù)可以將一個(gè)文件或者其它對(duì)象映射到調(diào)用進(jìn)程的地址空間,然后進(jìn)程就可以像訪問(wèn)內(nèi)存一樣訪問(wèn)該文件。
mmap() 函數(shù)原型如下:
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
參數(shù)解釋:
- addr:指向欲映射的內(nèi)存起始地址,通常設(shè)為 NULL,代表讓系統(tǒng)自動(dòng)選定地址。
- length:代表將文件中多少字節(jié)映射到內(nèi)存中。
- prot:映射區(qū)域的保護(hù)方式,可取值為 PROT_NONE, PROT_READ, PROT_WRITE 和 PROT_EXEC,分別代表該區(qū)域不能被訪問(wèn)、該區(qū)域可被讀取、該區(qū)域可被寫(xiě)入和該區(qū)域可被執(zhí)行。這些屬性是可以通過(guò)或運(yùn)算組合在一起使用的。
- flags:指定映射對(duì)象的類(lèi)型,常見(jiàn)的是 MAP_SHARED 和 MAP_PRIVATE。MAP_SHARED 表示映射區(qū)域的修改會(huì)反映回文件中,而 MAP_PRIVATE 表示映射區(qū)域的修改僅僅對(duì)該進(jìn)程可見(jiàn),不會(huì)反映回文件中。在使用 MAP_PRIVATE 時(shí),映射區(qū)域是寫(xiě)時(shí)拷貝的,即只有當(dāng)寫(xiě)入時(shí)才會(huì)發(fā)生真正的寫(xiě)操作,此時(shí)才會(huì)分配物理內(nèi)存并將文件數(shù)據(jù)復(fù)制到其中。
- fd:被映射對(duì)象的文件描述符。
- offset:從文件起始位置開(kāi)始的偏移量,通常設(shè)置為 0。
- mmap() 函數(shù)成功執(zhí)行后,會(huì)返回一個(gè)指向被映射區(qū)域的起始地址的指針,如果操作失敗,則返回 MAP_FAILED。
mmap() 函數(shù)的優(yōu)點(diǎn)在于能夠快速、方便地實(shí)現(xiàn)文件到內(nèi)存的映射,同時(shí)支持共享內(nèi)存和私有內(nèi)存兩種映射方式。在實(shí)現(xiàn)進(jìn)程間通信和共享數(shù)據(jù)時(shí),mmap() 函數(shù)非常實(shí)用。