LInux 操作系統(tǒng)中斷
什么是系統(tǒng)中斷
這個沒啥可說的,大家都知道;
CPU 在執(zhí)行任務途中接收到中斷請求,需要保存現場后去處理中斷請求!保存現場稱為中斷處理程序!處理中斷請求也就是喚醒對應的任務進程來持有CPU進行需要的操作!
有了中斷之后,提升了操作系統(tǒng)的性能!可以異步并行處理很多任務!
- 軟中斷(80中斷)
由CPU產生的;CPU檢查到程序代碼段發(fā)生異常會切換到內核態(tài);
- 硬中斷
由硬件設備發(fā)起的中斷稱為硬中斷!可以發(fā)生在任何時間;比方說網卡設備接收到一組報文;對應的報文會被DMA設備進行拷貝到網卡緩沖區(qū)!然后網卡就會向CPU發(fā)起中斷信號(IRQ):
CPU收到信號后就會執(zhí)行網卡對應的中斷處理程序!
內核在系統(tǒng)中斷時做了什么事
每種中斷都有它對應的中斷處理程序;
對應到內核的某一個代碼段;
CPU接收到中斷后;首先需要將寄存器中數據保存到進程描述符!PCB!
隨后切換到內核態(tài)處理中斷處理程序!執(zhí)行網卡的程序;
執(zhí)行完畢之后切換到用戶態(tài),根據PCB內容恢復現場!然后就可繼續(xù)執(zhí)行代碼段了!
硬件中斷觸發(fā)的過程

中斷請求寄存器:保存需要發(fā)送中斷請求的設備記錄!
優(yōu)先級解析器:中斷請求是有優(yōu)先級之分的,因為CPU不能同時執(zhí)行多個中斷請求!
正在服務寄存器:正在執(zhí)行的請求!比方我正在打字,這里面記錄的就是鍵盤IRQ1 !

操作系統(tǒng)啟動時需要將硬件向量值與處理程序地址進行映射!當硬件發(fā)送中斷信息時只會發(fā)送向量值,通過匹配找到對應的處理程序!
Socket基礎
Socket讀寫緩沖區(qū)機制

所謂socket,在底層也無非就是一個對象,通過對象綁定兩個緩沖區(qū),也就是數據隊列,然后調用系統(tǒng)API對這兩個緩沖區(qū)的數據進行操作罷了!
發(fā)數據;用戶態(tài)轉內核態(tài),將數據拷貝到send緩存區(qū),然后調用write系統(tǒng)調用將數據拷貝到網卡,再由網卡通過TCP/IP協(xié)議進行數據包的網絡發(fā)送!
socket兩種工作模式
- BIO
總結:讀數據讀不到就一直等,發(fā)數據發(fā)不了就一直等!
- NIO
讀數據讀不到就等一會再讀,取數據取不到就等一會再取!
接受端緩沖區(qū)打滿了,線程又搶占不到CPU去清理緩沖區(qū),怎么辦!
最后發(fā)送端的數據緩沖區(qū)也會被打滿!
系統(tǒng)調用;用戶態(tài)------內核態(tài)
- 系統(tǒng)調用:
int 0X80對應的就是系統(tǒng)調用中斷處理程序;向量值為128;system_call;

IRQ是有限的,不可能為每一個系統(tǒng)調用都分配一個向量值,所以統(tǒng)一使用80中斷來進行系統(tǒng)調用的路由!
為什么要有這兩種狀態(tài)
指令的危險程度不一樣;
對于不同的指令,為了保證系統(tǒng)安全,劃分了用戶空間和內核空間;
linux中:0表示內核態(tài),3表示用戶態(tài)!
所以:linux在創(chuàng)建進程的時候就會為進程分配兩塊空間;
用戶棧:分配變量,創(chuàng)建對象
內核棧:分配變量!
什么時候進程進行切換至內核態(tài)
硬中斷;
用戶態(tài)中代碼出現錯誤也要切換!
進程切換時都做了什么
CPU中存在很多寄存器

這些寄存器保存了進程在進行運算時的一些瞬時數據;如果現在要進行進程切換了;這些數據都需要找個地方保存起來;那么保存到哪里呢?
進程PCB:在OS創(chuàng)建進程的時候同時也會分配一段空間存放進程的一些信息;其中就有一個字段指向一個數據結構;叫做進程控制塊PCB:
用來描述和控制進程的運行的一個數據結構——進程控制塊PCB(Process Control Block),是進程實體的一部分,是操作系統(tǒng)中最重要的記錄型數據結構。
- PCB是進程存在的唯一標志
- 系統(tǒng)能且只能通過PCB對進程進行控制和調度
- PCB記錄了操作系統(tǒng)所需的、用于描述進程的當前情況以及控制進程運行的全部信息
所以:在進程進行切換的時候CPU中的數據保存到了PCB中,供CPU回來時讀取恢復!
Linux select 多路復用函數
select就是一個函數:只要傳入相應的參數就能獲得相應的數據:
1、們所關心的文件描述符fd;
2、描述符中我們關心的狀態(tài):讀事件、寫事件、等
3、等待時間
調用結束后內核會返回相關信息給我們!
做好準備的個數
哪些已經做好準備;有了這些返回信息,我們就可以調用合適的IO函數!這些函數就不會再被阻塞了;-
函數詳解
int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, timeval *timeout)
- maxfdp1 readset 和 wirteset中的最大有數據位
- readset bitmap結構的位信息;保存我們需要讀取的socket序號;
- writeset 寫數據信息
- exceptset 異常信息

select函數這里不再細講,可以翻看以前的文章

將函數需要的參數準備好之后調用select;
select進行80中斷;將rset數據拷貝到內核中;查詢對應的狀態(tài)之后設置rset對應的位置值,
完成后又拷貝到用戶態(tài)中的rset;這樣一來rset里面的位信息就代表了哪些socket是準備好了的!
隨后遍歷這些位信息就可以調用read或wirte進行緩沖區(qū)的操作了!
缺點
可以看到,while死循環(huán)中每次執(zhí)行都將rset重新置位;然后循環(huán)重新SET位信息;隨后才會發(fā)起請求!過程較為繁瑣且重復!
select多路復用器底層原理分析









epoll函數
了解到select的缺點后發(fā)現:select每次得到數據都要進行復位,然后又進行重復的步驟去內核中獲取信息;感覺就是很多時間都花在重復的勞動上,為了解決這個問題,linux在2.6引入epoll模型,單獨在內核區(qū)域開辟一塊空間來做select主動去做的事,select是主動查,epoll則是準備數據,線程來了直接取就行了;大大提升了性能
既然是函數,看看相關的函數實現:
實現思路:
在內核創(chuàng)建一塊空間;總所周知;linux下一切皆文件;所以所謂創(chuàng)建的空間也就是一個文件描述符fd,然后這個文件結構中有兩個指針指向另外兩個地址空間:事件隊列、就緒隊列
事件隊列:存放已經建立所有socket連接
就緒隊列:準備就緒的socket;也就是read或write的時候不用阻塞的socket;
其實epoll就像一個數據庫;里面有兩個數據表;一個放連接列表;一個放準備就緒的連接列表;
既然有這兩個隊列;就要涉及到增刪查;這就是另外兩個函數的來由;
創(chuàng)建epoll空間
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);
對事件隊列進行增刪改:
epfd : epoll的文件描述符號:因為內核中可能有多個epoll
op : 參數op有以下幾個值:EPOLL_CTL_ADD:注冊新的fd到epfd中,并關聯事件event;EPOLL_CTL_MOD:修改已經注冊的fd的監(jiān)聽事件;EPOLL_CTL_DEL:從epfd中移除fd,并且忽略掉綁定的event,這時event可以為null;
fd : 表示socket對應的文件描述符。

epoll底層原理解析












-
cpu
+關注
關注
68文章
11277瀏覽量
224954 -
Linux
+關注
關注
88文章
11758瀏覽量
219009 -
操作系統(tǒng)
+關注
關注
37文章
7401瀏覽量
129282 -
程序代碼
+關注
關注
4文章
43瀏覽量
15801
發(fā)布評論請先 登錄
Linux操作系統(tǒng)
Linux操作系統(tǒng)原理及應用
linux操作系統(tǒng)的安全性
Linux操作系統(tǒng)實時性分析及改進策略
Linux與其他操作系統(tǒng)的區(qū)別
手機支持的Linux操作系統(tǒng)
Linux操作系統(tǒng)分析
Linux的Ubuntu操作系統(tǒng)的安裝教程
LInux 操作系統(tǒng)中斷介紹
評論