新聞中心
Linux操作系統(tǒng)中的阻塞隊列是一種高效的數(shù)據(jù)緩存機(jī)制,它被廣泛應(yīng)用于各種設(shè)備驅(qū)動程序和網(wǎng)絡(luò)協(xié)議棧的實現(xiàn)中,為Linux系統(tǒng)的性能提升做出了重要貢獻(xiàn)。本文將深入探究Linux阻塞隊列的原理、數(shù)據(jù)結(jié)構(gòu)和應(yīng)用,解密其高效的數(shù)據(jù)緩存機(jī)制,為Linux操作系統(tǒng)的開發(fā)者提供有價值的參考和啟示。

成都創(chuàng)新互聯(lián)主要從事網(wǎng)站制作、網(wǎng)站設(shè)計、網(wǎng)頁設(shè)計、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)大興安嶺,10余年網(wǎng)站建設(shè)經(jīng)驗,價格優(yōu)惠、服務(wù)專業(yè),歡迎來電咨詢建站服務(wù):028-86922220
1.阻塞隊列的原理
阻塞隊列(Blocking Queue)是在進(jìn)行隊列操作時,當(dāng)隊列為空或滿時,隊列插入和刪除操作被阻塞的一種隊列。在Linux系統(tǒng)中,阻塞隊列被廣泛應(yīng)用于各種設(shè)備驅(qū)動程序和網(wǎng)絡(luò)協(xié)議棧的實現(xiàn)中,它可以保證數(shù)據(jù)的順序和準(zhǔn)確性,并可以防止競態(tài)條件(Race Condition)的出現(xiàn),從而大大提高了系統(tǒng)的性能。
阻塞隊列的特點在于,當(dāng)隊列為空時,插入操作會被阻塞;當(dāng)隊列已滿時,刪除操作會被阻塞。這樣一來,隊列的插入和刪除操作就可以相互協(xié)調(diào),避免了一些錯誤的操作,從而提高了系統(tǒng)的效率。
2.阻塞隊列的數(shù)據(jù)結(jié)構(gòu)
Linux系統(tǒng)中的阻塞隊列通常使用兩個指針來實現(xiàn),一個指向隊列頭部,另一個指向隊列尾部。隊列的操作可以分為入隊和出隊兩種,當(dāng)對隊列進(jìn)行入隊操作時,首先要判斷隊列是否已滿,如果隊列已滿,則當(dāng)前線程會被阻塞,等待其他線程或進(jìn)程從隊列中取走數(shù)據(jù)。當(dāng)對隊列進(jìn)行出隊操作時,首先要判斷隊列是否為空,如果隊列為空,則當(dāng)前線程會被阻塞,等待其他線程或進(jìn)程插入數(shù)據(jù)到隊列中。
3.阻塞隊列的應(yīng)用
Linux系統(tǒng)中的阻塞隊列被廣泛應(yīng)用于各種設(shè)備驅(qū)動程序和網(wǎng)絡(luò)協(xié)議棧的實現(xiàn)中,例如,網(wǎng)絡(luò)協(xié)議棧中的套接字緩沖區(qū)、網(wǎng)絡(luò)設(shè)備驅(qū)動程序中的通用緩存機(jī)制等。阻塞隊列具有以下優(yōu)點:
(1)提高系統(tǒng)的可靠性和安全性
使用阻塞隊列可以避免競態(tài)條件的出現(xiàn),保證數(shù)據(jù)的順序和準(zhǔn)確性,并提高系統(tǒng)的可靠性和安全性。
(2)減少CPU資源的消耗
使用阻塞隊列可以減少CPU的頻繁調(diào)度和上下文切換開銷,從而降低CPU資源的消耗。
(3)提高系統(tǒng)的性能和效率
使用阻塞隊列可以提高系統(tǒng)的性能和效率,避免了無效的等待和競爭,從而提高了系統(tǒng)的吞吐量和響應(yīng)速度。
4.
隨著計算機(jī)技術(shù)的不斷發(fā)展,Linux操作系統(tǒng)已經(jīng)成為了開源軟件的代表,其阻塞隊列也成為了廣泛應(yīng)用于各種領(lǐng)域的高效數(shù)據(jù)緩存機(jī)制。通過深入探究Linux阻塞隊列的原理、數(shù)據(jù)結(jié)構(gòu)和應(yīng)用,可以更好地理解其高效的數(shù)據(jù)緩存機(jī)制,為Linux操作系統(tǒng)的開發(fā)者提供有價值的參考和啟示。希望本文能夠?qū)V大讀者產(chǎn)生一定的啟發(fā)和幫助,更好地理解和掌握阻塞隊列的原理和應(yīng)用。
相關(guān)問題拓展閱讀:
- 容器實戰(zhàn)
容器實戰(zhàn)
Namespace幫助容器來實現(xiàn)各種計算資源的隔離,Cgroups主要限制的是容器能夠使用的某種資源量。
init進(jìn)程創(chuàng)建的過程:
打開電源–> 執(zhí)行BIOS/boot-loader—>boot-loader加載Linux內(nèi)核(內(nèi)核文件存放在/boot目錄,文件名類似vmliunz*)–> 執(zhí)行的之一個用戶態(tài)程序就是init進(jìn)程。
1號進(jìn)程就是之一個用戶態(tài)的進(jìn)程,有它直接或者間接創(chuàng)建了namespace中的其他進(jìn)程。
特權(quán)信號就是Linux為kernel和超級用戶去刪除任意進(jìn)程所保留的,不能被忽略也不能被捕獲。
由于SIGKILL是一個特例,因為SIGKILL是不允許注冊用戶handler的,那么它只有SIG_DFL handler,init進(jìn)程是永遠(yuǎn)不能被SIGKILL所殺,但是可以被SIGTERM殺死。
進(jìn)程處理信號的選擇:
1.Linux內(nèi)核里其實都是用task_struct這個接口來表示的。Linux里基本的調(diào)度單位是任務(wù)。任務(wù)的狀態(tài)有兩個TASK_RUNNING(運行態(tài))和睡眠態(tài)(TASK_INTERRUPTIBLE,TASK_UNINTERRUPTIBLE).
運行態(tài)是無論進(jìn)程是正在運行中,還是進(jìn)程在run queue隊列里隨時可以運行,都處于這個狀態(tài)。
睡眠是指進(jìn)程需要等待某個資源而進(jìn)入的狀態(tài),要等待的資源可以是一個信號量,或者是磁盤IO,這個狀態(tài)的進(jìn)程會被放入到wait queue隊列里。
TASK_INTERRUPTIBLE是可以被打斷的,顯示為S stat,TASK_UNINTERRUPTIBLE 是不能被打斷的,顯示的進(jìn)程為D stat。
在調(diào)用do_exit()的時候,有兩個狀態(tài),EXIT_DEAD,就是進(jìn)程在真正結(jié)束退出的宴漏好那一瞬間的狀態(tài);EXIT_ZOMBIE狀態(tài),是在EXIT_DEAD之前的一個狀態(tài)。
可以晌鉛通過/proc/sys/kernel/pid_max設(shè)置進(jìn)程更大的數(shù)量。如果機(jī)器中CPU數(shù)目小于等于32,pid_max設(shè)置為32768(32K),如果CPU數(shù)目大于32,pid_max的數(shù)目為N*1024.
在創(chuàng)建容器成功之后, 創(chuàng)建容器的服務(wù)會在/sys/fs/cgroups/pids下建立一個字目錄,就是一個控制組,控制組里最關(guān)鍵的一個文件是pids.max。
父進(jìn)程在創(chuàng)建完子進(jìn)程就不管了,這就是子進(jìn)程變成僵尸進(jìn)程的原因。
在主進(jìn)程里,就是不斷在調(diào)用帶WHOHANG參數(shù)的waitpid(),通過這個方式清理容器中所有的僵尸進(jìn)程。
Containerd在停止容器的時候,就會向容器的init進(jìn)程發(fā)送一個SIGTERM信號,其他進(jìn)程收到的是SIGKILL信號。
kill()這個系統(tǒng)調(diào)用,輸入兩個參數(shù):進(jìn)程號和信號,就把特定的信號發(fā)送給搜滲指定的進(jìn)程了。
signal調(diào)用,決定了進(jìn)程收到特定的信號如何來處理,SIG_DFL參數(shù)把對應(yīng)信號恢復(fù)為缺省handler, 也可以用自定義的函數(shù)作為handler,或者用SIG_IGN參數(shù)讓進(jìn)程忽略信號。
如何解決停止容器的時候,容器內(nèi)應(yīng)用程序被強(qiáng)制殺死的問題:
在容器的init進(jìn)程中對收到的信號做轉(zhuǎn)發(fā),發(fā)送到容器中的其他子進(jìn)程,這樣容器中的所有進(jìn)程在停止時,都會收到SIGTERM,而不是SIGKILL信號了。
在/sys/fs/cgroup/cpu這個目錄看到cpu的數(shù)據(jù)
Linux普通的調(diào)度的算法是CFS(完全公平調(diào)度器)
cpu.cfs_period_us,cfs算法的一個調(diào)度周期,是以位秒為單位。
cpu.cfs_quota_us,在一個調(diào)度周期里這個控制組被允許的運行時間。
cpu.shares,cpu cgroup對于控制組之間的cpu分配比例,缺省值為1024.
由于/proc/stat文件是整個節(jié)點全局的狀態(tài)文件,不屬于任何一個Namespace,因此在容器中無法通過讀取/proc/stat文件來獲取單個容器的CPU使用率。
單個容器CPU使用率=((utime_2 – utime_1)+(stime_2 – stime_1)) 100.0/(HZ et*1)
無法通過CPU Cgroup來控制Load Average的平均負(fù)載。
Load Average是一種CPU資源需求的度量:
平均負(fù)載統(tǒng)計了這兩種情況的進(jìn)程:
Load Average = 可運行隊列進(jìn)程平均數(shù) + 休眠隊列中不可打斷的進(jìn)程平均數(shù)
OOM Killer是在Linux系統(tǒng)里如果內(nèi)存不足時,就需要殺死一個正在有耐性的進(jìn)程來釋放一些內(nèi)存。
Linux允許進(jìn)程在申請內(nèi)存的時候是overcommit,就是允許進(jìn)程申請超過實際物理內(nèi)存上線的內(nèi)存。
malloc()申請的是內(nèi)存虛擬地址,系統(tǒng)只是程序一個地址范圍,由于沒有寫入數(shù)據(jù),所以程序沒有得到真正的物理內(nèi)存。
oom_badness()函數(shù),判斷條件:
1.進(jìn)程已經(jīng)使用的物理內(nèi)存頁面數(shù);
2.每個進(jìn)程的OOM校準(zhǔn)值oom_scire_adj。在/proc文件系統(tǒng)中,每個進(jìn)程都有一個/proc//oom_score_adj的接口文件。
用系統(tǒng)總的可用頁面數(shù),乘以O(shè)OM校準(zhǔn)值oom_score_adj,再加上進(jìn)程已經(jīng)使用的物理頁面數(shù), 計算出來的值越大,那么這個進(jìn)程被OOM Killer的幾率也越大。
Memory Cgroup是對一組進(jìn)程的Memory做限制,掛在/sys/fs/cgroup/memory目錄下。
journalctl -k查看/var/log/message,看到的信息如下:
1.容器中每一個進(jìn)程使用的內(nèi)存頁面數(shù)量。
2.oom-kill: 可以看到那個容器發(fā)生
3.Killed process7445 那個進(jìn)程被殺死。
Linux內(nèi)存模型:RSS和Page Cache。
RSS:進(jìn)程真正申請到物理頁面的內(nèi)存大小。
判斷容器實際使用的內(nèi)存量需要使用memory.stat里的rss值。free獲取到的內(nèi)存值,需要去掉available字段下的值。
Page Cache是進(jìn)程在運行中讀寫磁盤文件后,作為Cache而繼續(xù)保留在內(nèi)存中,它的目的是為了提高磁盤文件的讀寫性能。
內(nèi)存使用量計算公式(memory.kmem.usage_in_bytes表示該memcg內(nèi)核內(nèi)存使用量):memory.usage_in_bytes=memory.stat+memory.stat+memory.kmem.usage_in_bytes.
Memory Cgroup OOM不是真正依據(jù)內(nèi)存使用量memory.usage_in_bytes,而是依據(jù)working set,working set的計算公式: working_set = memory.usage_in_bytes – total_inactive_file。
swappiness(/proc/sys/vm/swapiness)可以決定系統(tǒng)將會有多頻繁地使用交換分區(qū)。取值范圍為0-100,缺省值為60。
memory.swapiness(Cgroup中的參數(shù))可以控制這個Memory Cgroup控制組下面匿名內(nèi)存和page cache的回收。
當(dāng)memory.swapiness=0的時候,對匿名頁的回收是始終禁止的,也就是始終不會使用Swap空間。
為了有效地減少磁盤上冗余的鏡像數(shù)據(jù),同時減少冗余的鏡像數(shù)據(jù)在網(wǎng)絡(luò)上的傳輸,選擇一種針對容器的文件系統(tǒng)是很有必要的,這類的文件系統(tǒng)被稱為UnionFS。
UnionFS實現(xiàn)的主要功能是把多個目錄一起掛載在同一目錄下。
OverlayFS是Liunx發(fā)行版本里缺省使用的容器文件系統(tǒng)。
OverlayFS也是把多個目錄合并掛載,被掛載的目錄分為兩大類:lowerdir和upperdir。
lowerdir允許有多個目錄,在被掛載后,這些目錄里的文件都是不會被修改或者刪除,也就是只讀的;upper只有一個,不過這個目錄是可讀寫的,掛載點目錄中的所有文件修改都會在upperdir中反映出來。
OverlayFS建立2個lowerdir目錄,并且在目錄中建立相同文件名的文件,然后一起做一個overlay mount,為將文件合并成為一個。
為了避免容器把宿主機(jī)的磁盤寫滿,對OverlayFS的upper目錄做XFS Quota的限流。
docker run –storage-opt size=10M,就能限制容器OverlayFS文件系統(tǒng)可寫入的更大數(shù)據(jù)量。
限制文件大小分為兩步:
之一步:給目標(biāo)目錄打上一個Project ID;
第二步:為這個Project ID在XFS文件系統(tǒng)中,設(shè)置一個寫入數(shù)據(jù)塊的限制。
setProjectID()是調(diào)用ioctl(),setProjectQuota()調(diào)用quotactl()來修改內(nèi)核中XFS的數(shù)據(jù)結(jié)構(gòu),從而完成project ID的設(shè)置和quota的設(shè)置。
如何判斷是對那個目錄做了限制:
根據(jù)/proc/mounts中容器的OverlayFS Mount信息,可以知道限制的目錄/var/lib/docker2/,目錄下的diff目錄就是限制目錄。
IOPS就是每秒鐘磁盤讀寫的次數(shù),這個數(shù)值越大,性能越好。
吞吐量是每秒鐘磁盤中數(shù)據(jù)的讀取量。
吞吐量 = 數(shù)據(jù)塊大小 * IOPS。
在Cgroup v1里,bulkio Cgroup的虛擬文件系統(tǒng)掛載點一半在/sys/fs/cgroup/blkio/。
Direct I/O模式,用戶進(jìn)程如果要寫磁盤文件,就會通過Linux內(nèi)核的文件系統(tǒng)層(fileSystem)–>塊設(shè)備層(block layer)–>磁盤驅(qū)動–>磁盤硬件。
Buffer I/O模式,用戶進(jìn)程只是把文件寫到內(nèi)存中就返回,Linux內(nèi)核自己有線程會被內(nèi)存中的數(shù)據(jù)寫入到磁盤中Cgroup v1 blkio的子系統(tǒng)獨立于memory系統(tǒng),無法統(tǒng)計到有Page Cache刷入到磁盤的數(shù)據(jù)量。Linux中絕大多數(shù)使用的是Buffered I/O模式。
Direct I/O可以通過blkio Cgroup來限制磁盤I/O。Cgroup V2從架構(gòu)上允許一個控制組里只要同時有IO和Memory子系統(tǒng),就可以對Buffered I/O做磁盤讀寫的限速。
dirty_backgroud_ratio和dirty_ratio,這兩個值都是相對于節(jié)點可用內(nèi)存的百分比值。
當(dāng)dirty pages數(shù)量超過dirty_backgroud_ratio對應(yīng)的內(nèi)存量的時候,內(nèi)核flush線程就會開始把dirty page寫入磁盤;當(dāng)dirty pages數(shù)量超過dirty_ratio對應(yīng)的內(nèi)存量,這時候程序?qū)懳募暮瘮?shù)調(diào)用write()就會被阻塞住,知道這次調(diào)用的dirty pages全部寫入到磁盤。
在節(jié)點是大內(nèi)存容量,并且dirty_ratio為系統(tǒng)缺省值為20%,dirty_backgroud_ratio是系統(tǒng)缺省值10%的情況下,通過觀察/proc/vmstat中的nr_dirty數(shù)值可以發(fā)現(xiàn),dirty pages不會阻塞進(jìn)程的Buffered I/O寫文件操作。
修改網(wǎng)絡(luò)參數(shù)的有兩種方法:一種方法是直接到/proc文件系統(tǒng)下的/proc/sys/net目錄對參數(shù)做修改;還有就是使用sysctl來修改。
創(chuàng)建新的network namespace的方法:系統(tǒng)調(diào)用clone()或者unshare()。
Network Namespace工具包:
runC也在對/proc/sys目錄做read-only mount之前,預(yù)留出了修改接口,就是用來修改容器里/proc/sys下參數(shù)的,同樣也是sysctl的參數(shù)。
在容器啟動之前修改網(wǎng)絡(luò)相關(guān)的內(nèi)容,是可以的,如果啟動之后,修改網(wǎng)絡(luò)相關(guān)內(nèi)容的是不生效的。
docker exec、kubectl exec、ip netns exec、nsenter等命令原理相同,都是基于setns系統(tǒng)調(diào)用,切換至指定的一個或多個namespace。
解決容器與外界通訊的問題,一共需要兩步完成。
對于macvlan,每個虛擬網(wǎng)絡(luò)接口都有自己獨立的mac地址,而ipvlan的虛擬網(wǎng)絡(luò)接口是和物理網(wǎng)絡(luò)接口共享一個mac地址。
veth對外發(fā)送數(shù)據(jù)的時候,peer veth接口都會raise softirq來完成一次收報操作,這樣就會帶來數(shù)據(jù)包處理的額外開銷。
容器使用ipvlan/macvlan的網(wǎng)絡(luò)接口,網(wǎng)絡(luò)延時可以非常接近物理網(wǎng)絡(luò)接口的延時。
對于需要使用iptables規(guī)則的容器,Kubernetes使用service的容器,就不能工作:
docker inspect lat-test-1 | jq..state.Pid
Linux capabilities就是把Linux root用戶原來所有的特權(quán)做了細(xì)化,可以更加細(xì)粒度地給進(jìn)程賦予不同權(quán)限。
Privileged的容器也就是允許容器中的進(jìn)程可以執(zhí)行所有的特權(quán)操作。
容器中root用戶的進(jìn)程,系統(tǒng)也只允許了15個capabilities。
使用不同用戶執(zhí)行程序:
xfs quota功能
centos7 xfs 文件系統(tǒng)配置quota 用戶磁盤配額
quota磁盤配額(xfs)
xfs_quota 磁盤配額
xfs_quota 磁盤配額限制篇
XFS文件系統(tǒng)中quota的使用
xfs文件系統(tǒng)quota
Linux學(xué)習(xí)—CentOS7磁盤配額工具quota
linux 阻塞隊列的介紹就聊到這里吧,感謝你花時間閱讀本站內(nèi)容,更多關(guān)于linux 阻塞隊列,深入探究Linux阻塞隊列:解密高效的數(shù)據(jù)緩存機(jī)制,容器實戰(zhàn)的信息別忘了在本站進(jìn)行查找喔。
成都網(wǎng)站推廣找創(chuàng)新互聯(lián),老牌網(wǎng)站營銷公司
成都網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián)(www.cdcxhl.com)專注高端網(wǎng)站建設(shè),網(wǎng)頁設(shè)計制作,網(wǎng)站維護(hù),網(wǎng)絡(luò)營銷,SEO優(yōu)化推廣,快速提升企業(yè)網(wǎng)站排名等一站式服務(wù)。IDC基礎(chǔ)服務(wù):云服務(wù)器、虛擬主機(jī)、網(wǎng)站系統(tǒng)開發(fā)經(jīng)驗、服務(wù)器租用、服務(wù)器托管提供四川、成都、綿陽、雅安、重慶、貴州、昆明、鄭州、湖北十堰機(jī)房互聯(lián)網(wǎng)數(shù)據(jù)中心業(yè)務(wù)。
網(wǎng)站題目:深入探究Linux阻塞隊列:解密高效的數(shù)據(jù)緩存機(jī)制 (linux 阻塞隊列)
本文來源:http://m.fisionsoft.com.cn/article/ccojepd.html


咨詢
建站咨詢
