新聞中心
Linux是一個(gè)開源操作系統(tǒng),擁有強(qiáng)大的操作系統(tǒng)內(nèi)核和眾多的特性。其中,套接字是一個(gè)非常重要的特性之一。套接字是一種用于網(wǎng)絡(luò)通信的編程接口,它是Linux系統(tǒng)中實(shí)現(xiàn)網(wǎng)絡(luò)通信的核心之一。在Linux系統(tǒng)中,通過調(diào)用套接字操作函數(shù)來進(jìn)行網(wǎng)絡(luò)通信。本文將深入探究Linux套接字操作函數(shù)的實(shí)現(xiàn)原理。

創(chuàng)新互聯(lián)堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:網(wǎng)站建設(shè)、成都網(wǎng)站設(shè)計(jì)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的游仙網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!
一、套接字
套接字,也被稱為網(wǎng)絡(luò)套接字或通信套接字,是一種用于網(wǎng)絡(luò)通信的編程接口。套接字是一組描述符,表示兩個(gè)應(yīng)用程序之間的通信鏈路。在一對(duì)套接字描述符中,其中一個(gè)表示客戶端,另一個(gè)表示服務(wù)器端,它們通過網(wǎng)絡(luò)互相通信實(shí)現(xiàn)數(shù)據(jù)交換。
在Linux系統(tǒng)中,套接字可以使用C語言的標(biāo)準(zhǔn)庫函數(shù)來實(shí)現(xiàn)。標(biāo)準(zhǔn)庫提供了一組函數(shù),例如socket()、bind()、listen()、accept()、connect()、send()和recv(),我們可以使用這些函數(shù)實(shí)現(xiàn)與網(wǎng)絡(luò)的通信。
二、套接字操作函數(shù)實(shí)現(xiàn)原理
套接字操作函數(shù)實(shí)現(xiàn)原理可以分為以下幾個(gè)方面:
1. 創(chuàng)建套接字
調(diào)用socket()函數(shù)創(chuàng)建套接字。該函數(shù)返回套接字描述符(socket descriptor),用于后續(xù)的通信操作。在Linux系統(tǒng)中,socket()函數(shù)的實(shí)現(xiàn)是基于內(nèi)核系統(tǒng)調(diào)用的。
2. 綁定到本地地址和端口號(hào)
調(diào)用bind()函數(shù)將套接字綁定到本地地址和端口號(hào)。傳入bind()函數(shù)的參數(shù)包含了IP地址、端口號(hào)以及協(xié)議族等信息。bind()函數(shù)的實(shí)現(xiàn)會(huì)根據(jù)傳入的IP地址、端口號(hào)以及協(xié)議族信息,在內(nèi)核中創(chuàng)建對(duì)應(yīng)的網(wǎng)絡(luò)數(shù)據(jù)結(jié)構(gòu)。
3. 監(jiān)聽連接請(qǐng)求
調(diào)用listen()函數(shù),將套接字轉(zhuǎn)化為被動(dòng)套接字,以等待客戶端的連接請(qǐng)求。listen()函數(shù)將套接字置于監(jiān)聽狀態(tài),并在內(nèi)核中創(chuàng)建對(duì)應(yīng)的隊(duì)列,用于處理客戶端的連接請(qǐng)求。
4. 接受連接請(qǐng)求
調(diào)用accept()函數(shù),在服務(wù)器端接受客戶端的連接請(qǐng)求。accept()函數(shù)會(huì)阻塞等待客戶端發(fā)送連接請(qǐng)求。當(dāng)客戶端發(fā)送連接請(qǐng)求時(shí),accept()函數(shù)會(huì)返回一個(gè)新的套接字描述符,表示已連接到客戶端的套接字。
5. 發(fā)送數(shù)據(jù)
調(diào)用send()函數(shù),向連接的另一端發(fā)送數(shù)據(jù)。send()函數(shù)將數(shù)據(jù)從應(yīng)用程序緩沖區(qū)復(fù)制到內(nèi)核緩沖區(qū),再由內(nèi)核將數(shù)據(jù)發(fā)送至對(duì)端應(yīng)用程序。
6. 接收數(shù)據(jù)
調(diào)用recv()函數(shù),從連接的另一端接收數(shù)據(jù)。recv()函數(shù)將數(shù)據(jù)從內(nèi)核緩沖區(qū)復(fù)制到應(yīng)用程序緩沖區(qū),供應(yīng)用程序進(jìn)行處理。
三、
套接字是Linux系統(tǒng)中實(shí)現(xiàn)網(wǎng)絡(luò)通信的核心之一。套接字操作函數(shù)是使用套接字進(jìn)行網(wǎng)絡(luò)通信的基礎(chǔ),它們提供了一組函數(shù),包括socket()、bind()、listen()、accept()、connect()、send()和recv()等,用于實(shí)現(xiàn)與網(wǎng)絡(luò)的交互。了解套接字操作函數(shù)的實(shí)現(xiàn)原理,可以幫助開發(fā)人員更好地使用它們實(shí)現(xiàn)各種網(wǎng)絡(luò)應(yīng)用。
成都網(wǎng)站建設(shè)公司-創(chuàng)新互聯(lián)為您提供網(wǎng)站建設(shè)、網(wǎng)站制作、網(wǎng)頁設(shè)計(jì)及定制高端網(wǎng)站建設(shè)服務(wù)!
「圖文結(jié)合」Linux 進(jìn)程、線程、文件描述符的底層原理
開發(fā)十年經(jīng)驗(yàn)總結(jié),阿里架構(gòu)師的手寫Spring boot原理實(shí)踐文檔
阿里架構(gòu)師的這份:Redis核心原理與應(yīng)用實(shí)踐,帶你手撕Redis
Tomcat結(jié)構(gòu)原理詳解
說到進(jìn)程,恐怕面試中最常見的問題就是線程和進(jìn)程的關(guān)系了,那么先說一下答案:
在 Linux 系統(tǒng)中啟瞎,進(jìn)程和線程幾乎沒有區(qū)別
。
Linux 中的進(jìn)程其實(shí)就是一個(gè)數(shù)據(jù)結(jié)構(gòu),順帶可以理解文件描述符、重定向、管道命令的底層工作原理,最后我們從操作系統(tǒng)的角度看看為什么說線程和進(jìn)程基本沒有區(qū)別。
首先,抽象地來說,我們的計(jì)算機(jī)就是這個(gè)東西:
這個(gè)大的矩形表示計(jì)算機(jī)的
內(nèi)存空間
,其中的小矩形代表
進(jìn)程
,左下角的圓形表示
磁盤
,右下角的圖形表示一些
輸入輸出設(shè)備
,比如鼠標(biāo)鍵盤顯示器等等。另外,注意到內(nèi)存空間被劃分為了兩塊,上半部分表示
用戶空間
,下半部分表示
內(nèi)核空間
。
用戶空間裝著用戶進(jìn)程需要使用的資源,比如你在程序代碼里開一個(gè)數(shù)迅盯組,這個(gè)數(shù)組肯定存在用戶空間;內(nèi)核空間存放內(nèi)核進(jìn)程需要加載的系統(tǒng)資源,這一些資源一般是不允許用戶訪問的。但是注意有的用戶進(jìn)程會(huì)共享一些內(nèi)核空間的資源,比如一些動(dòng)態(tài)鏈接庫等等。
我們用 C 語言寫一個(gè) hello 程序,編譯后得到一個(gè)可執(zhí)行文件,在命令行運(yùn)行就可以打印出一句 hello world,然后程序退出。在操作系統(tǒng)層面,就是新建了一個(gè)進(jìn)程,這個(gè)進(jìn)程將我們編譯出來的可執(zhí)行文件讀入內(nèi)存空間,然后執(zhí)行,最后退出。
你編譯好的那個(gè)可執(zhí)行程序只是一個(gè)文件,不是進(jìn)程,可執(zhí)行文件必須要載入內(nèi)存,包裝成一個(gè)進(jìn)程才能真正跑起來。進(jìn)程是要依靠操作系統(tǒng)創(chuàng)建的,每個(gè)進(jìn)程都有它的固有屬性,比如進(jìn)程號(hào)(PID)、進(jìn)程狀態(tài)、打開的文件等等,進(jìn)程創(chuàng)建好之后,讀入你的程序,你的程序才被系統(tǒng)執(zhí)行。
那么,操作系統(tǒng)是如何創(chuàng)建進(jìn)程的呢?
對(duì)于操作系統(tǒng),進(jìn)程就是一個(gè)數(shù)據(jù)結(jié)構(gòu)
,我們直接來看 Linux 的源碼:
task_struct 就是 Linux 內(nèi)核對(duì)于一個(gè)進(jìn)程的描述,也可以稱為「進(jìn)程描述符」。源碼比較復(fù)雜,我這里就截取了一小部分比較常見的。
我們主要聊聊 mm 指針和 files 指針。 mm 指向的是進(jìn)程的虛擬內(nèi)存,也就是載入資源和可執(zhí)行文件的地方; files 指針指向一個(gè)數(shù)組,這個(gè)數(shù)組里裝著所有該進(jìn)程打開的文件的指針。
先說 files ,它是一個(gè)文件指針數(shù)組。一般來說,一個(gè)進(jìn)程會(huì)從 files 讀取輸入,將輸出寫入 files ,將錯(cuò)誤信息寫入 files 。
舉個(gè)例子,以我們的角度 C 語言的 printf 函數(shù)是向命令行打印字符,但是從進(jìn)程的角度來看,就是向 files 寫入數(shù)據(jù);同理, scanf 函數(shù)就是進(jìn)程試圖從 files 這個(gè)文件中讀取數(shù)據(jù)。
每個(gè)進(jìn)程被創(chuàng)建時(shí), files 的前三位被填入默認(rèn)值,分別指向標(biāo)準(zhǔn)輸入流、標(biāo)準(zhǔn)輸出流、標(biāo)準(zhǔn)錯(cuò)誤流。我們常悄昌空說的「文件描述符」就是指這個(gè)文件指針數(shù)組的索引 ,所以程序的文件描述符默認(rèn)情況下 0 是輸入,1 是輸出,2 是錯(cuò)誤。
我們可以重新畫一幅圖:
對(duì)于一般的計(jì)算機(jī),輸入流是鍵盤,輸出流是顯示器,錯(cuò)誤流也是顯示器,所以現(xiàn)在這個(gè)進(jìn)程和內(nèi)核連了三根線。因?yàn)橛布际怯蓛?nèi)核管理的,我們的進(jìn)程需要通過「系統(tǒng)調(diào)用」讓內(nèi)核進(jìn)程訪問硬件資源。
PS:不要忘了,Linux 中一切都被抽象成文件,設(shè)備也是文件,可以進(jìn)行讀和寫。
如果我們寫的程序需要其他資源,比如打開一個(gè)文件進(jìn)行讀寫,這也很簡單,進(jìn)行系統(tǒng)調(diào)用,讓內(nèi)核把文件打開,這個(gè)文件就會(huì)被放到 files 的第 4 個(gè)位置,對(duì)應(yīng)文件描述符 3:
明白了這個(gè)原理,
輸入重定向
就很好理解了,程序想讀取數(shù)據(jù)的時(shí)候就會(huì)去 files 讀取,所以我們只要把 files 指向一個(gè)文件,那么程序就會(huì)從這個(gè)文件中讀取數(shù)據(jù),而不是從鍵盤:
同理,
輸出重定向
就是把 files 指向一個(gè)文件,那么程序的輸出就不會(huì)寫入到顯示器,而是寫入到這個(gè)文件中:
錯(cuò)誤重定向也是一樣的,就不再贅述。
管道符其實(shí)也是異曲同工,把一個(gè)進(jìn)程的輸出流和另一個(gè)進(jìn)程的輸入流接起一條「管道」,數(shù)據(jù)就在其中傳遞,不得不說這種設(shè)計(jì)思想真的很巧妙:
到這里,你可能也看出「Linux 中一切皆文件」設(shè)計(jì)思路的高明了,不管是設(shè)備、另一個(gè)進(jìn)程、socket 套接字還是真正的文件,全部都可以讀寫,統(tǒng)一裝進(jìn)一個(gè)簡單的 files 數(shù)組,進(jìn)程通過簡單的文件描述符訪問相應(yīng)資源,具體細(xì)節(jié)交于操作系統(tǒng),有效解耦,優(yōu)美高效。
首先要明確的是,多進(jìn)程和多線程都是并發(fā),都可以提高處理器的利用效率,所以現(xiàn)在的關(guān)鍵是,多線程和多進(jìn)程有啥區(qū)別。
為什么說 Linux 中線程和進(jìn)程基本沒有區(qū)別呢,因?yàn)閺?Linux 內(nèi)核的角度來看,并沒有把線程和進(jìn)程區(qū)別對(duì)待。
我們知道系統(tǒng)調(diào)用 fork() 可以新建一個(gè)子進(jìn)程,函數(shù) pthread() 可以新建一個(gè)線程。 但無論線程還是進(jìn)程,都是用 task_struct 結(jié)構(gòu)表示的,唯一的區(qū)別就是共享的數(shù)據(jù)區(qū)域不同 。
換句話說,線程看起來跟進(jìn)程沒有區(qū)別,只是線程的某些數(shù)據(jù)區(qū)域和其父進(jìn)程是共享的,而子進(jìn)程是拷貝副本,而不是共享。就比如說, mm 結(jié)構(gòu)和 files 結(jié)構(gòu)在線程中都是共享的,我畫兩張圖你就明白了:
所以說,我們的多線程程序要利用鎖機(jī)制,避免多個(gè)線程同時(shí)往同一區(qū)域?qū)懭霐?shù)據(jù),否則可能造成數(shù)據(jù)錯(cuò)亂。
那么你可能問, 既然進(jìn)程和線程差不多,而且多進(jìn)程數(shù)據(jù)不共享,即不存在數(shù)據(jù)錯(cuò)亂的問題,為什么多線程的使用比多進(jìn)程普遍得多呢 ?
因?yàn)楝F(xiàn)實(shí)中數(shù)據(jù)共享的并發(fā)更普遍呀,比如十個(gè)人同時(shí)從一個(gè)賬戶取十元,我們希望的是這個(gè)共享賬戶的余額正確減少一百元,而不是希望每人獲得一個(gè)賬戶的拷貝,每個(gè)拷貝賬戶減少十元。
當(dāng)然,必須要說明的是,
只有 Linux 系統(tǒng)將線程看做共享數(shù)據(jù)的進(jìn)程
,不對(duì)其做特殊看待
,其他的很多操作系統(tǒng)是對(duì)線程和進(jìn)程區(qū)別對(duì)待的,線程有其特有的數(shù)據(jù)結(jié)構(gòu),我個(gè)人認(rèn)為不如 Linux 的這種設(shè)計(jì)簡潔,增加了系統(tǒng)的復(fù)雜度。
在 Linux 中新建線程和進(jìn)程的效率都是很高的,對(duì)于新建進(jìn)程時(shí)內(nèi)存區(qū)域拷貝的問題,Linux 采用了 copy-on-write 的策略優(yōu)化,也就是并不真正復(fù)制父進(jìn)程的內(nèi)存空間,而是等到需要寫操作時(shí)才去復(fù)制。
所以 Linux 中新建進(jìn)程和新建線程都是很迅速的
linux驅(qū)動(dòng)程序結(jié)構(gòu)框架及工作原理分別是什么?
一、Linux device driver 的概念\x0d\x0a\x0d\x0a 系統(tǒng)調(diào)用是操作系統(tǒng)內(nèi)核和應(yīng)用程序之間的接口,設(shè)備驅(qū)動(dòng)程序是操作系統(tǒng)內(nèi)核和機(jī)器硬件之間的接棗圓口。設(shè)備驅(qū)動(dòng)程序?yàn)閼?yīng)用程序屏蔽了硬件的細(xì)節(jié),這樣在應(yīng)用程序看來,硬件設(shè)備只是一個(gè)設(shè)備文件,應(yīng)用程序可以象操作普通文件一樣對(duì)硬件設(shè)備進(jìn)行操作。設(shè)備驅(qū)動(dòng)程序是內(nèi)核的一部分,它完成以下的功能:\x0d\x0a\x0d\x0a 1、對(duì)設(shè)早巖褲備初始化和釋放;\x0d\x0a\x0d\x0a 2、把數(shù)據(jù)從內(nèi)核傳送到硬件和從硬件讀取數(shù)據(jù);\x0d\x0a\x0d\x0a 3、讀取應(yīng)用程序傳送給設(shè)備文件的數(shù)據(jù)和回送應(yīng)用程序請(qǐng)求的數(shù)據(jù);\x0d\x0a\x0d\x0a 4、檢測(cè)和處理設(shè)備出現(xiàn)的錯(cuò)誤。\x0d\x0a\x0d\x0a 在Linux操作系統(tǒng)下有三類主要的設(shè)備文件類型,一是字符設(shè)備,二是塊設(shè)備,三是網(wǎng)絡(luò)設(shè)備。字符設(shè)備和塊設(shè)備的主要區(qū)別是:在對(duì)字符設(shè)備發(fā)出讀/寫請(qǐng)求時(shí),實(shí)際的硬件I/O一般就緊接著發(fā)生了,塊設(shè)備則不然,它利用一塊系統(tǒng)內(nèi)存作緩沖區(qū),當(dāng)用戶進(jìn)程對(duì)設(shè)備請(qǐng)求能滿足用戶的要求,就返回請(qǐng)求的數(shù)據(jù),如果不能,就調(diào)用請(qǐng)求函數(shù)來進(jìn)行實(shí)際的I/O操作。塊設(shè)備是主要針對(duì)磁盤等慢速設(shè)備設(shè)計(jì)的,以免耗費(fèi)過多的CPU時(shí)間來陸簡等待。\x0d\x0a\x0d\x0a 已經(jīng)提到,用戶進(jìn)程是通過設(shè)備文件來與實(shí)際的硬件打交道。每個(gè)設(shè)備文件都都有其文件屬性(c/b),表示是字符設(shè)備還是塊設(shè)備?另外每個(gè)文件都有兩個(gè)設(shè)備號(hào),之一個(gè)是主設(shè)備號(hào),標(biāo)識(shí)驅(qū)動(dòng)程序,第二個(gè)是從設(shè)備號(hào),標(biāo)識(shí)使用同一個(gè)設(shè)備驅(qū)動(dòng)程序的不同的硬件設(shè)備,比如有兩個(gè)軟盤,就可以用從設(shè)備號(hào)來區(qū)分他們。設(shè)備文件的的主設(shè)備號(hào)必須與設(shè)備驅(qū)動(dòng)程序在登記時(shí)申請(qǐng)的主設(shè)備號(hào)一致,否則用戶進(jìn)程將無法訪問到驅(qū)動(dòng)程序。\x0d\x0a\x0d\x0a 最后必須提到的是,在用戶進(jìn)程調(diào)用驅(qū)動(dòng)程序時(shí),系統(tǒng)進(jìn)入核心態(tài),這時(shí)不再是搶先式調(diào)度。也就是說,系統(tǒng)必須在你的驅(qū)動(dòng)程序的子函數(shù)返回后才能進(jìn)行其他的工作。如果你的驅(qū)動(dòng)程序陷入死循環(huán),不幸的是你只有重新啟動(dòng)機(jī)器了,然后就是漫長的fsck。\x0d\x0a\x0d\x0a 二、實(shí)例剖析\x0d\x0a\x0d\x0a 我們來寫一個(gè)最簡單的字符設(shè)備驅(qū)動(dòng)程序。雖然它什么也不做,但是通過它可以了解Linux的設(shè)備驅(qū)動(dòng)程序的工作原理。把下面的C代碼輸入機(jī)器,你就會(huì)獲得一個(gè)真正的設(shè)備驅(qū)動(dòng)程序。\x0d\x0a\x0d\x0a 由于用戶進(jìn)程是通過設(shè)備文件同硬件打交道,對(duì)設(shè)備文件的操作方式不外乎就是一些系統(tǒng)調(diào)用,如 open,read,write,close?, 注意,不是fopen, fread,但是如何把系統(tǒng)調(diào)用和驅(qū)動(dòng)程序關(guān)聯(lián)起來呢?這需要了解一個(gè)非常關(guān)鍵的數(shù)據(jù)結(jié)構(gòu):\x0d\x0a\x0d\x0a STruct file_operatiONs {\x0d\x0a\x0d\x0a int (*seek) (struct inode * ,struct file *, off_t ,int);\x0d\x0a\x0d\x0a int (*read) (struct inode * ,struct file *, char ,int);\x0d\x0a\x0d\x0a int (*write) (struct inode * ,struct file *, off_t ,int);\x0d\x0a\x0d\x0a int (*readdir) (struct inode * ,struct file *, struct dirent * ,int);\x0d\x0a\x0d\x0a int (*select) (struct inode * ,struct file *, int ,select_table *);\x0d\x0a\x0d\x0a int (*ioctl) (struct inode * ,struct file *, unsined int ,unsigned long);\x0d\x0a\x0d\x0a int (*mmap) (struct inode * ,struct file *, struct vm_area_struct *);\x0d\x0a\x0d\x0a int (*open) (struct inode * ,struct file *);\x0d\x0a\x0d\x0a int (*release) (struct inode * ,struct file *);\x0d\x0a\x0d\x0a int (*fsync) (struct inode * ,struct file *);\x0d\x0a\x0d\x0a int (*fasync) (struct inode * ,struct file *,int);\x0d\x0a\x0d\x0a int (*check_media_change) (struct inode * ,struct file *);\x0d\x0a\x0d\x0a int (*revalidate) (dev_t dev);\x0d\x0a\x0d\x0a }\x0d\x0a\x0d\x0a 這個(gè)結(jié)構(gòu)的每一個(gè)成員的名字都對(duì)應(yīng)著一個(gè)系統(tǒng)調(diào)用。用戶進(jìn)程利用系統(tǒng)調(diào)用在對(duì)設(shè)備文件進(jìn)行諸如read/write操作時(shí),系統(tǒng)調(diào)用通過設(shè)備文件的主設(shè)備號(hào)找到相應(yīng)的設(shè)備驅(qū)動(dòng)程序,然后讀取這個(gè)數(shù)據(jù)結(jié)構(gòu)相應(yīng)的函數(shù)指針,接著把控制權(quán)交給該函數(shù)。這是linux的設(shè)備驅(qū)動(dòng)程序工作的基本原理。既然是這樣,則編寫設(shè)備驅(qū)動(dòng)程序的主要工作就是編寫子函數(shù),并填充file_operations的各個(gè)域。\x0d\x0a\x0d\x0a 下面就開始寫子程序。\x0d\x0a\x0d\x0a #include
基本的類型定義\x0d\x0a\x0d\x0a #include
文件系統(tǒng)使用相關(guān)的頭文件\x0d\x0a\x0d\x0a #include
\x0d\x0a\x0d\x0a #include
\x0d\x0a\x0d\x0a #include
\x0d\x0a\x0d\x0a unsigned int test_major = 0;\x0d\x0a\x0d\x0a static int read_test(struct inode *inode,struct file *file,char *buf,int count)\x0d\x0a\x0d\x0a {\x0d\x0a\x0d\x0a int left; 用戶空間和內(nèi)核空間\x0d\x0a\x0d\x0a if (verify_area(VERIFY_WRITE,buf,count) == -EFAULT )\x0d\x0a\x0d\x0a return -EFAULT;\x0d\x0a\x0d\x0a for(left = count ; left > 0 ; left–)\x0d\x0a\x0d\x0a {\x0d\x0a\x0d\x0a __put_user(1,buf,1);\x0d\x0a\x0d\x0a buf++;\x0d\x0a\x0d\x0a }\x0d\x0a\x0d\x0a return count;\x0d\x0a\x0d\x0a }\x0d\x0a\x0d\x0a 這個(gè)函數(shù)是為read調(diào)用準(zhǔn)備的。當(dāng)調(diào)用read時(shí),read_test()被調(diào)用,它把用戶的緩沖區(qū)全部寫1。buf 是read調(diào)用的一個(gè)參數(shù)。它是用戶進(jìn)程空間的一個(gè)地址。但是在read_test被調(diào)用時(shí),系統(tǒng)進(jìn)入核心態(tài)。所以不能使用buf這個(gè)地址,必須用__put_user(),這是kernel提供的一個(gè)函數(shù),用于向用戶傳送數(shù)據(jù)。另外還有很多類似功能的函數(shù)。請(qǐng)參考,在向用戶空間拷貝數(shù)據(jù)之前,必須驗(yàn)證buf是否可用。這就用到函數(shù)verify_area。為了驗(yàn)證BUF是否可以用。\x0d\x0a\x0d\x0a static int write_test(struct inode *inode,struct file *file,const char *buf,int count)\x0d\x0a\x0d\x0a {\x0d\x0a\x0d\x0a return count;\x0d\x0a\x0d\x0a }\x0d\x0a\x0d\x0a static int open_test(struct inode *inode,struct file *file )\x0d\x0a\x0d\x0a {\x0d\x0a\x0d\x0a MOD_INC_USE_COUNT; 模塊計(jì)數(shù)加以,表示當(dāng)前內(nèi)核有個(gè)設(shè)備加載內(nèi)核當(dāng)中去\x0d\x0a\x0d\x0a return 0;\x0d\x0a\x0d\x0a }\x0d\x0a\x0d\x0a static void release_test(struct inode *inode,struct file *file )\x0d\x0a\x0d\x0a {\x0d\x0a\x0d\x0a MOD_DEC_USE_COUNT;\x0d\x0a\x0d\x0a }\x0d\x0a\x0d\x0a 這幾個(gè)函數(shù)都是空操作。實(shí)際調(diào)用發(fā)生時(shí)什么也不做,他們僅僅為下面的結(jié)構(gòu)提供函數(shù)指針。\x0d\x0a\x0d\x0a struct file_operations test_fops = {?\x0d\x0a\x0d\x0a read_test,\x0d\x0a\x0d\x0a write_test,\x0d\x0a\x0d\x0a open_test,\x0d\x0a\x0d\x0a release_test,\x0d\x0a\x0d\x0a };\x0d\x0a\x0d\x0a 設(shè)備驅(qū)動(dòng)程序的主體可以說是寫好了?,F(xiàn)在要把驅(qū)動(dòng)程序嵌入內(nèi)核。驅(qū)動(dòng)程序可以按照兩種方式編譯。一種是編譯進(jìn)kernel,另一種是編譯成模塊(modules),如果編譯進(jìn)內(nèi)核的話,會(huì)增加內(nèi)核的大小,還要改動(dòng)內(nèi)核的源文件,而且不能動(dòng)態(tài)的卸載,不利于調(diào)試,所以推薦使用模塊方式。\x0d\x0a\x0d\x0a int init_module(void)\x0d\x0a\x0d\x0a {\x0d\x0a\x0d\x0a int result;\x0d\x0a\x0d\x0a result = register_chrdev(0, “test”, &test_fops); 對(duì)設(shè)備操作的整個(gè)接口\x0d\x0a\x0d\x0a if (result
\x0d\x0a\x0d\x0a #include
\x0d\x0a\x0d\x0a #include
\x0d\x0a\x0d\x0a #include
\x0d\x0a\x0d\x0a main()\x0d\x0a\x0d\x0a {\x0d\x0a\x0d\x0a int testdev;\x0d\x0a\x0d\x0a int i;\x0d\x0a\x0d\x0a char buf;\x0d\x0a\x0d\x0a testdev = open(“/dev/test”,O_RDWR);\x0d\x0a\x0d\x0a if ( testdev == -1 )\x0d\x0a\x0d\x0a {\x0d\x0a\x0d\x0a printf(“Cann’t open file \n”);\x0d\x0a\x0d\x0a exit(0);\x0d\x0a\x0d\x0a }\x0d\x0a\x0d\x0a read(testdev,buf,10);\x0d\x0a\x0d\x0a for (i = 0; i );\x0d\x0a\x0d\x0a close(testdev);\x0d\x0a\x0d\x0a }\x0d\x0a\x0d\x0a 編譯運(yùn)行,看看是不是打印出全1 \x0d\x0a\x0d\x0a 以上只是一個(gè)簡單的演示。真正實(shí)用的驅(qū)動(dòng)程序要復(fù)雜的多,要處理如中斷,DMA,I/O port等問題。這些才是真正的難點(diǎn)。上述給出了一個(gè)簡單的字符設(shè)備驅(qū)動(dòng)編寫的框架和原理,更為復(fù)雜的編寫需要去認(rèn)真研究LINUX內(nèi)核的運(yùn)行機(jī)制和具體的設(shè)備運(yùn)行的機(jī)制等等。希望大家好好掌握LINUX設(shè)備驅(qū)動(dòng)程序編寫的方法。關(guān)于linux 套接字操作函數(shù) 實(shí)現(xiàn)原理的介紹到此就結(jié)束了,不知道你從中找到你需要的信息了嗎 ?如果你還想了解更多這方面的信息,記得收藏關(guān)注本站。
創(chuàng)新互聯(lián)-老牌IDC、云計(jì)算及IT信息化服務(wù)領(lǐng)域的服務(wù)供應(yīng)商,業(yè)務(wù)涵蓋IDC(互聯(lián)網(wǎng)數(shù)據(jù)中心)服務(wù)、云計(jì)算服務(wù)、IT信息化、AI算力租賃平臺(tái)(智算云),軟件開發(fā),網(wǎng)站建設(shè),咨詢熱線:028-86922220
本文名稱:深入探究Linux套接字操作函數(shù)實(shí)現(xiàn)原理(linux套接字操作函數(shù)實(shí)現(xiàn)原理)
URL地址:http://www.dlmjj.cn/article/dpcicoe.html


咨詢
建站咨詢
