LInux 操作系統(tǒng)中斷
什么是系統(tǒng)中斷
這個(gè)沒啥可說的,大家都知道;
CPU 在執(zhí)行任務(wù)途中接收到中斷請(qǐng)求,需要保存現(xiàn)場后去處理中斷請(qǐng)求!保存現(xiàn)場稱為中斷處理程序!處理中斷請(qǐng)求也就是喚醒對(duì)應(yīng)的任務(wù)進(jìn)程來持有CPU進(jìn)行需要的操作!
有了中斷之后,提升了操作系統(tǒng)的性能!可以異步并行處理很多任務(wù)!
- 軟中斷(80中斷)
由CPU產(chǎn)生的;CPU檢查到程序代碼段發(fā)生異常會(huì)切換到內(nèi)核態(tài);
- 硬中斷
由硬件設(shè)備發(fā)起的中斷稱為硬中斷!可以發(fā)生在任何時(shí)間;比方說網(wǎng)卡設(shè)備接收到一組報(bào)文;對(duì)應(yīng)的報(bào)文會(huì)被DMA設(shè)備進(jìn)行拷貝到網(wǎng)卡緩沖區(qū)!然后網(wǎng)卡就會(huì)向CPU發(fā)起中斷信號(hào)(IRQ):
CPU收到信號(hào)后就會(huì)執(zhí)行網(wǎng)卡對(duì)應(yīng)的中斷處理程序!
內(nèi)核在系統(tǒng)中斷時(shí)做了什么事
每種中斷都有它對(duì)應(yīng)的中斷處理程序;
對(duì)應(yīng)到內(nèi)核的某一個(gè)代碼段;
CPU接收到中斷后;首先需要將寄存器中數(shù)據(jù)保存到進(jìn)程描述符!PCB!
隨后切換到內(nèi)核態(tài)處理中斷處理程序!執(zhí)行網(wǎng)卡的程序;
執(zhí)行完畢之后切換到用戶態(tài),根據(jù)PCB內(nèi)容恢復(fù)現(xiàn)場!然后就可繼續(xù)執(zhí)行代碼段了!
硬件中斷觸發(fā)的過程
中斷請(qǐng)求寄存器:保存需要發(fā)送中斷請(qǐng)求的設(shè)備記錄!
優(yōu)先級(jí)解析器:中斷請(qǐng)求是有優(yōu)先級(jí)之分的,因?yàn)镃PU不能同時(shí)執(zhí)行多個(gè)中斷請(qǐng)求!
正在服務(wù)寄存器:正在執(zhí)行的請(qǐng)求!比方我正在打字,這里面記錄的就是鍵盤IRQ1 !
操作系統(tǒng)啟動(dòng)時(shí)需要將硬件向量值與處理程序地址進(jìn)行映射!當(dāng)硬件發(fā)送中斷信息時(shí)只會(huì)發(fā)送向量值,通過匹配找到對(duì)應(yīng)的處理程序!
Socket基礎(chǔ)
Socket讀寫緩沖區(qū)機(jī)制
所謂socket,在底層也無非就是一個(gè)對(duì)象,通過對(duì)象綁定兩個(gè)緩沖區(qū),也就是數(shù)據(jù)隊(duì)列,然后調(diào)用系統(tǒng)API對(duì)這兩個(gè)緩沖區(qū)的數(shù)據(jù)進(jìn)行操作罷了!
發(fā)數(shù)據(jù);用戶態(tài)轉(zhuǎn)內(nèi)核態(tài),將數(shù)據(jù)拷貝到send緩存區(qū),然后調(diào)用write系統(tǒng)調(diào)用將數(shù)據(jù)拷貝到網(wǎng)卡,再由網(wǎng)卡通過TCP/IP協(xié)議進(jìn)行數(shù)據(jù)包的網(wǎng)絡(luò)發(fā)送!
socket兩種工作模式
- BIO
總結(jié):讀數(shù)據(jù)讀不到就一直等,發(fā)數(shù)據(jù)發(fā)不了就一直等!
- NIO
讀數(shù)據(jù)讀不到就等一會(huì)再讀,取數(shù)據(jù)取不到就等一會(huì)再取!
接受端緩沖區(qū)打滿了,線程又搶占不到CPU去清理緩沖區(qū),怎么辦!
最后發(fā)送端的數(shù)據(jù)緩沖區(qū)也會(huì)被打滿!
系統(tǒng)調(diào)用;用戶態(tài)------內(nèi)核態(tài)
- 系統(tǒng)調(diào)用:
int 0X80對(duì)應(yīng)的就是系統(tǒng)調(diào)用中斷處理程序;向量值為128;system_call;
IRQ是有限的,不可能為每一個(gè)系統(tǒng)調(diào)用都分配一個(gè)向量值,所以統(tǒng)一使用80中斷來進(jìn)行系統(tǒng)調(diào)用的路由!
為什么要有這兩種狀態(tài)
指令的危險(xiǎn)程度不一樣;
對(duì)于不同的指令,為了保證系統(tǒng)安全,劃分了用戶空間和內(nèi)核空間;
linux中:0表示內(nèi)核態(tài),3表示用戶態(tài)!
所以:linux在創(chuàng)建進(jìn)程的時(shí)候就會(huì)為進(jìn)程分配兩塊空間;
用戶棧:分配變量,創(chuàng)建對(duì)象
內(nèi)核棧:分配變量!
什么時(shí)候進(jìn)程進(jìn)行切換至內(nèi)核態(tài)
硬中斷;
用戶態(tài)中代碼出現(xiàn)錯(cuò)誤也要切換!
進(jìn)程切換時(shí)都做了什么
CPU中存在很多寄存器
這些寄存器保存了進(jìn)程在進(jìn)行運(yùn)算時(shí)的一些瞬時(shí)數(shù)據(jù);如果現(xiàn)在要進(jìn)行進(jìn)程切換了;這些數(shù)據(jù)都需要找個(gè)地方保存起來;那么保存到哪里呢?
進(jìn)程PCB:在OS創(chuàng)建進(jìn)程的時(shí)候同時(shí)也會(huì)分配一段空間存放進(jìn)程的一些信息;其中就有一個(gè)字段指向一個(gè)數(shù)據(jù)結(jié)構(gòu);叫做進(jìn)程控制塊PCB:
用來描述和控制進(jìn)程的運(yùn)行的一個(gè)數(shù)據(jù)結(jié)構(gòu)——進(jìn)程控制塊PCB(Process Control Block),是進(jìn)程實(shí)體的一部分,是操作系統(tǒng)中最重要的記錄型數(shù)據(jù)結(jié)構(gòu)。
- PCB是進(jìn)程存在的唯一標(biāo)志
- 系統(tǒng)能且只能通過PCB對(duì)進(jìn)程進(jìn)行控制和調(diào)度
- PCB記錄了操作系統(tǒng)所需的、用于描述進(jìn)程的當(dāng)前情況以及控制進(jìn)程運(yùn)行的全部信息
所以:在進(jìn)程進(jìn)行切換的時(shí)候CPU中的數(shù)據(jù)保存到了PCB中,供CPU回來時(shí)讀取恢復(fù)!
Linux select 多路復(fù)用函數(shù)
select就是一個(gè)函數(shù):只要傳入相應(yīng)的參數(shù)就能獲得相應(yīng)的數(shù)據(jù):
1、們所關(guān)心的文件描述符fd;
2、描述符中我們關(guān)心的狀態(tài):讀事件、寫事件、等
3、等待時(shí)間
調(diào)用結(jié)束后內(nèi)核會(huì)返回相關(guān)信息給我們!
做好準(zhǔn)備的個(gè)數(shù)
哪些已經(jīng)做好準(zhǔn)備;有了這些返回信息,我們就可以調(diào)用合適的IO函數(shù)!這些函數(shù)就不會(huì)再被阻塞了;-
函數(shù)詳解
- maxfdp1 readset 和 wirteset中的最大有數(shù)據(jù)位
- readset bitmap結(jié)構(gòu)的位信息;保存我們需要讀取的socket序號(hào);
- writeset 寫數(shù)據(jù)信息
- exceptset 異常信息
select函數(shù)這里不再細(xì)講,可以翻看以前的文章
將函數(shù)需要的參數(shù)準(zhǔn)備好之后調(diào)用select;
select進(jìn)行80中斷;將rset數(shù)據(jù)拷貝到內(nèi)核中;查詢對(duì)應(yīng)的狀態(tài)之后設(shè)置rset對(duì)應(yīng)的位置值,
完成后又拷貝到用戶態(tài)中的rset;這樣一來rset里面的位信息就代表了哪些socket是準(zhǔn)備好了的!
隨后遍歷這些位信息就可以調(diào)用read或wirte進(jìn)行緩沖區(qū)的操作了!
缺點(diǎn)
可以看到,while死循環(huán)中每次執(zhí)行都將rset重新置位;然后循環(huán)重新SET位信息;隨后才會(huì)發(fā)起請(qǐng)求!過程較為繁瑣且重復(fù)!
select多路復(fù)用器底層原理分析
epoll函數(shù)
了解到select的缺點(diǎn)后發(fā)現(xiàn):select每次得到數(shù)據(jù)都要進(jìn)行復(fù)位,然后又進(jìn)行重復(fù)的步驟去內(nèi)核中獲取信息;感覺就是很多時(shí)間都花在重復(fù)的勞動(dòng)上,為了解決這個(gè)問題,linux在2.6引入epoll模型,單獨(dú)在內(nèi)核區(qū)域開辟一塊空間來做select主動(dòng)去做的事,select是主動(dòng)查,epoll則是準(zhǔn)備數(shù)據(jù),線程來了直接取就行了;大大提升了性能
既然是函數(shù),看看相關(guān)的函數(shù)實(shí)現(xiàn):
實(shí)現(xiàn)思路:
在內(nèi)核創(chuàng)建一塊空間;總所周知;linux下一切皆文件;所以所謂創(chuàng)建的空間也就是一個(gè)文件描述符fd,然后這個(gè)文件結(jié)構(gòu)中有兩個(gè)指針指向另外兩個(gè)地址空間:事件隊(duì)列、就緒隊(duì)列
事件隊(duì)列:存放已經(jīng)建立所有socket連接
就緒隊(duì)列:準(zhǔn)備就緒的socket;也就是read或write的時(shí)候不用阻塞的socket;
其實(shí)epoll就像一個(gè)數(shù)據(jù)庫;里面有兩個(gè)數(shù)據(jù)表;一個(gè)放連接列表;一個(gè)放準(zhǔn)備就緒的連接列表;
既然有這兩個(gè)隊(duì)列;就要涉及到增刪查;這就是另外兩個(gè)函數(shù)的來由;
int epoll_create(int size);
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
對(duì)事件隊(duì)列進(jìn)行增刪改:
epfd : epoll的文件描述符號(hào):因?yàn)閮?nèi)核中可能有多個(gè)epoll
op : 參數(shù)op有以下幾個(gè)值:EPOLL_CTL_ADD:注冊(cè)新的fd到epfd中,并關(guān)聯(lián)事件event;EPOLL_CTL_MOD:修改已經(jīng)注冊(cè)的fd的監(jiān)聽事件;EPOLL_CTL_DEL:從epfd中移除fd,并且忽略掉綁定的event,這時(shí)event可以為null;
fd : 表示socket對(duì)應(yīng)的文件描述符。
epoll底層原理解析
-
寄存器
+關(guān)注
關(guān)注
31文章
5254瀏覽量
119214 -
cpu
+關(guān)注
關(guān)注
68文章
10702瀏覽量
209431 -
Linux
+關(guān)注
關(guān)注
87文章
11125瀏覽量
207928 -
操作系統(tǒng)
+關(guān)注
關(guān)注
37文章
6547瀏覽量
122756 -
程序
+關(guān)注
關(guān)注
115文章
3720瀏覽量
80361
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論