新聞中心
Linux是一種非常流行的操作系統(tǒng),它有很多優(yōu)點(diǎn),例如穩(wěn)定性、安全性、強(qiáng)大的自由度等等。其中一個(gè)最重要的優(yōu)勢(shì)就是其卓越的網(wǎng)絡(luò)能力。Linux自帶網(wǎng)絡(luò)模塊,使其成為服務(wù)器、網(wǎng)絡(luò)工具和開發(fā)工具的首選。

創(chuàng)新互聯(lián)公司是一家從事企業(yè)網(wǎng)站建設(shè)、網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)、行業(yè)門戶網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)制作的專業(yè)網(wǎng)站制作公司,擁有經(jīng)驗(yàn)豐富的網(wǎng)站建設(shè)工程師和網(wǎng)頁(yè)設(shè)計(jì)人員,具備各種規(guī)模與類型網(wǎng)站建設(shè)的實(shí)力,在網(wǎng)站建設(shè)領(lǐng)域樹立了自己獨(dú)特的設(shè)計(jì)風(fēng)格。自公司成立以來曾獨(dú)立設(shè)計(jì)制作的站點(diǎn)近1000家。
那么在Linux系統(tǒng)中,如何使用網(wǎng)絡(luò)模塊呢?本文將介紹一些基本的調(diào)用方法,以便開發(fā)人員更好地利用Linux的網(wǎng)絡(luò)優(yōu)勢(shì)。
一、網(wǎng)絡(luò)模塊簡(jiǎn)介
網(wǎng)絡(luò)模塊是在內(nèi)核中實(shí)現(xiàn)的一種設(shè)備驅(qū)動(dòng)程序,它負(fù)責(zé)操作系統(tǒng)對(duì)各種網(wǎng)絡(luò)協(xié)議的處理,包括TCP/IP、UDP、ICMP等。Linux的網(wǎng)絡(luò)模塊使用了一種名為套接字(socket)的標(biāo)準(zhǔn)接口,它允許應(yīng)用程序直接訪問網(wǎng)絡(luò)協(xié)議,而無需深入了解協(xié)議的細(xì)節(jié)。
在Linux中,網(wǎng)絡(luò)模塊分為兩類:
1.協(xié)議族(protocol family)模塊:用于處理TCP/IP、UDP、ICMP等協(xié)議;
2.設(shè)備驅(qū)動(dòng)程序(device driver)模塊:用于管理網(wǎng)絡(luò)設(shè)備、以及與底層硬件通信。
二、套接字編程
套接字編程是利用套接字接口(socket API)來訪問網(wǎng)絡(luò)協(xié)議的一種方式。Linux提供了多種套接字接口,其中最常用的是BSD套接字接口。
下面是一個(gè)簡(jiǎn)單的使用套接字接口發(fā)送UDP包的示例代碼:
“`
#include
#include
#include
#include
#include
#include
#include
#define BUF_SIZE 1024
#define SERVER_PORT 8888
int mn(int argc, char *argv[]) {
int sockfd;
struct sockaddr_in servaddr;
char buf[BUF_SIZE];
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERVER_PORT);
inet_pton(AF_INET, “127.0.0.1”, &servaddr.sin_addr);
while (1) {
memset(buf, 0, sizeof(buf));
printf(“Input a message:\n”);
fgets(buf, sizeof(buf), stdin);
sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr *)&servaddr, sizeof(servaddr));
}
close(sockfd);
return 0;
}
“`
這個(gè)示例代碼使用了socket()函數(shù)創(chuàng)建了一個(gè)UDP套接字,使用sendto()函數(shù)將數(shù)據(jù)包發(fā)送出去。在這個(gè)過程中,我們需要指定目標(biāo)服務(wù)器的IP地址和端口號(hào)。
三、網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)編程
另一種調(diào)用網(wǎng)絡(luò)模塊的方式是使用網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)程序。網(wǎng)絡(luò)設(shè)備可以是以太網(wǎng)卡、Wi-Fi適配器等。在Linux中,網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)程序是以內(nèi)核模塊的形式存在的。
下面是一個(gè)簡(jiǎn)單的網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)程序展示:
“`
#include
#include
#include
#include
#include
static struct net_device *dev = NULL;
static unsigned char g_dev_addr[ETH_ALEN] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55};
static int dummy_dev_open(struct net_device *dev) {
printk(“dummy_dev: device open\n”);
netif_start_queue(dev);
return 0;
}
static int dummy_dev_stop(struct net_device *dev) {
printk(“dummy_dev: device stop\n”);
netif_stop_queue(dev);
return 0;
}
static int dummy_dev_xmit(struct sk_buff *skb, struct net_device *dev) {
printk(“dummy_dev: packet tranitted\n”);
dev_kfree_skb(skb);
return NETDEV_TX_OK;
}
static const struct net_device_ops dummy_dev_ops = {
.ndo_open = dummy_dev_open,
.ndo_stop = dummy_dev_stop,
.ndo_start_xmit = dummy_dev_xmit,
};
static int __init dummy_dev_init(void) {
dev = alloc_etherdev(sizeof(struct dummy_dev));
if (!dev) {
printk(“dummy_dev: fled to alloc_etherdev\n”);
return -ENOMEM;
}
memcpy(dev->dev_addr, g_dev_addr, ETH_ALEN);
dev->netdev_ops = &dummy_dev_ops;
dev->flags |= IFF_NOARP;
register_netdev(dev);
printk(“dummy_dev: module loaded\n”);
return 0;
}
static void __exit dummy_dev_exit(void) {
unregister_netdev(dev);
free_netdev(dev);
printk(“dummy_dev: module unloaded\n”);
}
module_init(dummy_dev_init);
module_exit(dummy_dev_exit);
“`
該代碼創(chuàng)建了一個(gè)名為dummy_dev的網(wǎng)絡(luò)設(shè)備,它可以像其他網(wǎng)絡(luò)設(shè)備一樣進(jìn)行管理。當(dāng)應(yīng)用程序嘗試發(fā)送數(shù)據(jù)包時(shí),設(shè)備驅(qū)動(dòng)程序?qū)⒃趦?nèi)核中進(jìn)行傳輸并發(fā)送到目標(biāo)地址。在這個(gè)過程中,我們可以通過alloc_netdev()和register_netdev()函數(shù)注冊(cè)設(shè)備;通過netif_start_queue()和netif_stop_queue()函數(shù)啟用或停用網(wǎng)絡(luò)設(shè)備。
成都網(wǎng)站建設(shè)公司-創(chuàng)新互聯(lián)為您提供網(wǎng)站建設(shè)、網(wǎng)站制作、網(wǎng)頁(yè)設(shè)計(jì)及定制高端網(wǎng)站建設(shè)服務(wù)!
在linux中 應(yīng)用程序如何調(diào)用模塊內(nèi)的函數(shù)
很自然的,下一個(gè)疑問接踵而至,--模塊里的其他函數(shù)如何被調(diào)用?比如我寫的模塊中除了 init_module() 和cleanup_module() 函數(shù)外,還寫了一個(gè) hello_world() 函數(shù),簡(jiǎn)單的輸出hello world到控制臺(tái),好,接下來就是這次分析的關(guān)鍵,前面我們強(qiáng)調(diào)了模塊中的函數(shù)是由內(nèi)核來調(diào)用的,除此之外沒有別的機(jī)會(huì)使它被執(zhí)行到。那如果我們的 hello_world() 函數(shù)不能被內(nèi)核調(diào)用,這不就意味著它永遠(yuǎn)也不可能被執(zhí)行到嗎?確實(shí)是這樣,換句話說,在這種情況下它就是一段垃圾代碼,永無見天日之時(shí)。怎么樣才能使我們的 hello_world() 函數(shù)被執(zhí)行?顯然,關(guān)鍵在于讓內(nèi)核認(rèn)識(shí)它,即內(nèi)核能找到它。那么,怎樣才能使內(nèi)核找到這個(gè)函數(shù)?再進(jìn)一步的問題是,內(nèi)核為什么要去找這個(gè)函數(shù)?
之一問的答案是,內(nèi)核通過系統(tǒng)中特定的數(shù)據(jù)結(jié)構(gòu)來找到函數(shù)的,當(dāng)然,這意味著在你的模塊程序中,僅僅寫上 hello_world() 函數(shù)的代碼是不夠的,還應(yīng)該再做幾步工作:
a,首先,系統(tǒng)中的各類數(shù)據(jù)結(jié)構(gòu)那么多,要使用哪個(gè)呢?這由你這個(gè)模塊的注冊(cè)性質(zhì)決定,譬如你的模塊是一個(gè)USB設(shè)備驅(qū)動(dòng)模塊,那么你就需要填寫u設(shè)備驅(qū)動(dòng)程序的數(shù)據(jù)結(jié)構(gòu)(通常數(shù)據(jù)結(jié)構(gòu)都是結(jié)構(gòu)體(struct)的形式)
struct u_driver{之一項(xiàng);第二項(xiàng);第三項(xiàng);…….}
這里的各項(xiàng)有些是字符串,有些是函數(shù)指針,具體請(qǐng)查資料。
b,把 hello_world() 的函數(shù)指針放進(jìn)一個(gè)數(shù)據(jù)結(jié)構(gòu)中。我們還是接著舉u設(shè)備驅(qū)動(dòng)程序模塊的例子吧,在它的數(shù)據(jù)結(jié)構(gòu)u_driver{}中,選一個(gè)恰好是函數(shù)指針的項(xiàng),把 hello_world() 函數(shù)的指針放進(jìn)去(通過函數(shù)名),再填滿這個(gè)數(shù)據(jù)結(jié)構(gòu)的其他部分(不想填的話就空著吧:P,用分號(hào)分隔即可)。
c,填完之后,回到之一問中,怎樣使內(nèi)核能夠找到這個(gè) hello_world() 函數(shù)?回頭想想,當(dāng)我們填完了數(shù)據(jù)結(jié)構(gòu),也就決定了我們所編的模塊的性質(zhì),在此例中它是作為一個(gè)u設(shè)備驅(qū)動(dòng)模塊,但是要讓內(nèi)核知道它的性質(zhì),還得通過執(zhí)行u設(shè)備驅(qū)動(dòng)程序的系統(tǒng)注冊(cè)函數(shù) u_register(struct u_struct *drv),向內(nèi)核注冊(cè)這個(gè)模塊以及這個(gè)填好的數(shù)據(jù)結(jié)構(gòu)。注意到了吧,注冊(cè)函數(shù)的參數(shù)就是我們前面所填寫的u設(shè)備驅(qū)動(dòng)模塊的數(shù)據(jù)結(jié)構(gòu),也就是說,執(zhí)行了這個(gè)注冊(cè)函數(shù)之后,內(nèi)核里就認(rèn)識(shí)了這個(gè)模塊,并且得到了 hello_world() 函數(shù)的指針!哈哈,這就為我們的 hello_world() 函數(shù)找到了生存的意義--它有可能被執(zhí)行了?。ㄅ加X得,程序生存的意義就在于被執(zhí)行,就跟偶們生存的意義在于編程序一樣:P)
d,還得補(bǔ)充一下,u_register(struct u_struct *drv) 函數(shù)必須被放在 init_module() 中,因?yàn)樵谧?cè)這個(gè)決定模塊性質(zhì)的數(shù)據(jù)結(jié)構(gòu)之前(短語(yǔ)太長(zhǎng),可約為這個(gè)數(shù)據(jù)結(jié)構(gòu)),模塊中可以被直接執(zhí)行到的函數(shù)只有 init_module() 和 cleanup_module() 兩個(gè),如果不把握這個(gè)機(jī)會(huì)趕緊注冊(cè)數(shù)據(jù)結(jié)構(gòu)的話,那我們的 hello_world() 函數(shù)又要永不見天日了:(。
現(xiàn)在來看第二問,內(nèi)核為什么要去找這個(gè)函數(shù)?還是用u設(shè)備驅(qū)動(dòng)模塊來解釋,其他類型的模塊偶不了解,還請(qǐng)大蝦們補(bǔ)充。對(duì)于u設(shè)備驅(qū)動(dòng)模塊,內(nèi)核找這個(gè)函數(shù)的原因當(dāng)然是,用戶程序?qū)設(shè)備進(jìn)行了某種操作,而這種操作需要u設(shè)備驅(qū)動(dòng)程序的函數(shù)來進(jìn)行實(shí)現(xiàn)。我們前面的工作中已將這個(gè)u設(shè)備驅(qū)動(dòng)模塊的數(shù)據(jù)結(jié)構(gòu)注冊(cè)進(jìn)內(nèi)核數(shù)據(jù)結(jié)構(gòu)鏈表,內(nèi)核根據(jù)我們這個(gè)模塊對(duì)應(yīng)的數(shù)據(jù)結(jié)構(gòu)u_driver的各項(xiàng)定義,找到對(duì)應(yīng)用戶要求的那個(gè)操作的那個(gè)函數(shù)。假設(shè)我們把 hello_world() 函數(shù)的指針放在u_driver的 write() 選項(xiàng)中,那么當(dāng)用戶對(duì)u設(shè)備進(jìn)行寫操作的時(shí)候,就調(diào)用了 hello_world() 函數(shù),控制臺(tái)屏幕上會(huì)打出hello world ,其他什么操作都沒有,哈哈,一定很有趣。(這里我們假設(shè)此u設(shè)備的驅(qū)動(dòng)程序正好是我們編的那個(gè))
自己的一點(diǎn)心得,大部分是憑空想像的,錯(cuò)誤之處一定數(shù)不勝數(shù),還請(qǐng)各位大蝦費(fèi)心批評(píng)指教!
虛擬機(jī)中的linux怎么連接網(wǎng)絡(luò)
選擇NAT或者僑聯(lián)就可以了
1、將網(wǎng)卡VMware Network Adapter VMnet8改成DHCP自動(dòng)獲取IP。
2、將Linux虛擬機(jī)的網(wǎng)卡自定義連接到VMware Network Adapter VMnet8網(wǎng)卡上,如下圖:
3、將你現(xiàn)在上網(wǎng)的網(wǎng)卡(有線網(wǎng)卡或者無山搭線網(wǎng)卡)共享給VMware Network Adapter VMnet8網(wǎng)卡;打開網(wǎng)卡屬神唯握性 然后共享。如下圖:
4、此時(shí)游慶查看VMware Network Adapter VMnet8網(wǎng)卡的連接詳細(xì)信息,此網(wǎng)卡已經(jīng)自動(dòng)獲取到了一個(gè)192.168.137.1/24的IP地址,將其改為手動(dòng),并且將DNS設(shè)置為物理機(jī)上網(wǎng)的DNS,如下圖:
5、此時(shí)可以將Linux虛擬機(jī)的網(wǎng)卡IP地址配置到192.168.137.x/24這個(gè)段的IP地址,網(wǎng)關(guān)就配置為 192.168.137.1;DNS配置為VMware Network Adapter VMnet8網(wǎng)卡的DNS地址,此時(shí)Linux虛擬機(jī)應(yīng)該是可以ping通物理機(jī)以及外網(wǎng)的。
到此,Linux虛擬機(jī)上外網(wǎng)的配置完成?。。?/p>
關(guān)于 Linux 網(wǎng)絡(luò),你必須知道這些
我們一起學(xué)習(xí)了文件系統(tǒng)和磁盤 I/O 的工作原理,以及相應(yīng)的性能分析和優(yōu)化方法。接下來,我們將進(jìn)入下一個(gè)重要模塊—— Linux 的網(wǎng)絡(luò)子系統(tǒng)。
由于網(wǎng)絡(luò)處理的流程最復(fù)雜,跟我們前面講到的進(jìn)程調(diào)度、中斷處理、內(nèi)存管理以及 I/O 等都密不可分,所以,我把網(wǎng)絡(luò)模塊作為最后一個(gè)資源模塊來講解。
同 CPU、內(nèi)存以及 I/O 一樣,網(wǎng)絡(luò)也是 Linux 系統(tǒng)最核心的功能。網(wǎng)絡(luò)是一種把不同計(jì)算機(jī)或網(wǎng)絡(luò)設(shè)備連接到一起的技術(shù),它本質(zhì)上是一種進(jìn)程間通信方式,特別是跨系統(tǒng)的進(jìn)程間通信,必須要通過網(wǎng)絡(luò)才能進(jìn)行。隨著高并發(fā)、分布式、云計(jì)算、微服務(wù)等技術(shù)的普及,網(wǎng)絡(luò)的性能也變得越來越重要。
說到網(wǎng)絡(luò),我想你肯定經(jīng)常提起七層負(fù)載均衡、四層負(fù)載均衡,或者三層設(shè)備、二層設(shè)備等等。那么,這里說的二層、三層、四層、七層又都是什么意思呢?
實(shí)際上,這些層都來自國(guó)際標(biāo)準(zhǔn)化組織制定的開放式系統(tǒng)互聯(lián)通信參考模型(Open System Interconnection Reference Model),簡(jiǎn)稱為 OSI 網(wǎng)絡(luò)模型。
但是 OSI 模型還是太復(fù)雜了,也沒能提供一個(gè)可實(shí)現(xiàn)的方法。所以,在 Linux 中,我們實(shí)際上使用的是另一個(gè)更實(shí)用的四層模型,即 TCP/IP 網(wǎng)絡(luò)模型。
TCP/IP 模型,把網(wǎng)絡(luò)互聯(lián)的框架分為應(yīng)用層、傳輸層、網(wǎng)絡(luò)層、網(wǎng)絡(luò)接口層等四層,其中,
為了幫你更形象理解 TCP/IP 與 OSI 模型的關(guān)系,我畫了一張圖,如下所示:
當(dāng)然了,雖說 Linux 實(shí)際按照 TCP/IP 模型,實(shí)現(xiàn)了網(wǎng)絡(luò)協(xié)議棧,但在平時(shí)的學(xué)習(xí)交流中,我們習(xí)慣上還是用 OSI 七層模型來描述。比如,說到七層和四層負(fù)載均衡,對(duì)應(yīng)的分別是 OSI 模型中的應(yīng)用層和傳輸層(而它們對(duì)應(yīng)到 TCP/IP 模型中,實(shí)際上是四層和三層)。
OSI引入了服務(wù)、接口、協(xié)議、分層的概念,TCP/IP借鑒了OSI的這些概念建立TCP/IP模型。
OSI先有模型,后有協(xié)議,先有標(biāo)準(zhǔn),后進(jìn)行實(shí)踐;而TCP/IP則相反,先有協(xié)議和應(yīng)用再提出了模型,且是參照的OSI模型。
OSI是一種理論下的模型,而TCP/IP已被廣泛使用,成為網(wǎng)絡(luò)互聯(lián)事實(shí)上的標(biāo)準(zhǔn)。
有了 TCP/IP 模型后,在進(jìn)行網(wǎng)絡(luò)傳輸時(shí),數(shù)據(jù)包就會(huì)按照協(xié)議棧,對(duì)上一層發(fā)來的數(shù)據(jù)進(jìn)行逐層處理;然后封裝上該層的協(xié)議頭,再發(fā)送給下一層。
當(dāng)然,網(wǎng)絡(luò)包在每一層的處理邏輯,都取決于各層采用的網(wǎng)絡(luò)協(xié)議。比如在應(yīng)用層,一個(gè)提供 REST API 的應(yīng)用,可以使用 HTTP 協(xié)議,把它需要傳輸?shù)?ON 數(shù)據(jù)封裝到 HTTP 協(xié)議中,然后向下傳遞給 TCP 層。
而封裝做的事情就很簡(jiǎn)單了,只是在原來的負(fù)載前后,增加固定格式的元數(shù)據(jù),原始的負(fù)載數(shù)據(jù)并不會(huì)被修改。
比如,以通過 TCP 協(xié)議通信的網(wǎng)絡(luò)包為例,通過下面這張圖,我們可以看到,應(yīng)用程序數(shù)據(jù)在每個(gè)層的封裝格式。
這些新增的頭部和尾部,增加了網(wǎng)絡(luò)包的大小,但我們都知道,物理鏈路中并不能傳輸任意大小的數(shù)據(jù)包。網(wǎng)絡(luò)接口配置的更大傳輸單元(MTU),就規(guī)定了更大的 IP 包大小。在我們最常用的以太網(wǎng)中,MTU 默認(rèn)值是 1500(這也是 Linux 的默認(rèn)值)。
一旦網(wǎng)絡(luò)包超過 MTU 的大小,就會(huì)在網(wǎng)絡(luò)層分片,以保證分片后的 IP 包不大于 MTU 值。顯然,MTU 越大,需要的分包也就越少,自然,網(wǎng)絡(luò)吞吐能力就越好。
理解了 TCP/IP 網(wǎng)絡(luò)模型和網(wǎng)絡(luò)包的封裝原理后,你很容易能想到,Linux 內(nèi)核中的網(wǎng)絡(luò)棧,其實(shí)也類似于 TCP/IP 的四層結(jié)構(gòu)。如下圖所示,就是 Linux 通用 IP 網(wǎng)絡(luò)棧的示意圖:
我們從上到下來看這個(gè)網(wǎng)絡(luò)棧,你可以發(fā)現(xiàn),
這里我簡(jiǎn)單說一下網(wǎng)卡。網(wǎng)卡是發(fā)送和接收網(wǎng)絡(luò)包的基本設(shè)備。在系統(tǒng)啟動(dòng)過程中,網(wǎng)卡通過內(nèi)核中的網(wǎng)卡驅(qū)動(dòng)程序注冊(cè)到系統(tǒng)中。而在網(wǎng)絡(luò)收發(fā)過程中,內(nèi)核通過中斷跟網(wǎng)卡進(jìn)行交互。
再結(jié)合前面提到的 Linux 網(wǎng)絡(luò)棧,可以看出,網(wǎng)絡(luò)包的處理非常復(fù)雜。所以,網(wǎng)卡硬中斷只處理最核心的網(wǎng)卡數(shù)據(jù)讀取或發(fā)送,而協(xié)議棧中的大部分邏輯,都會(huì)放到軟中斷中處理。
我們先來看網(wǎng)絡(luò)包的接收流程。
當(dāng)一個(gè)網(wǎng)絡(luò)幀到達(dá)網(wǎng)卡后,網(wǎng)卡會(huì)通過 DMA 方式,把這個(gè)網(wǎng)絡(luò)包放到收包隊(duì)列中;然后通過硬中斷,告訴中斷處理程序已經(jīng)收到了網(wǎng)絡(luò)包。
接著,網(wǎng)卡中斷處理程序會(huì)為網(wǎng)絡(luò)幀分配內(nèi)核數(shù)據(jù)結(jié)構(gòu)(sk_buff),并將其拷貝到 sk_buff 緩沖區(qū)中;然后再通過軟中斷,通知內(nèi)核收到了新的網(wǎng)絡(luò)幀。
接下來,內(nèi)核協(xié)議棧從緩沖區(qū)中取出網(wǎng)絡(luò)幀,并通過網(wǎng)絡(luò)協(xié)議棧,從下到上逐層處理這個(gè)網(wǎng)絡(luò)幀。比如,
最后,應(yīng)用程序就可以使用 Socket 接口,讀取到新接收到的數(shù)據(jù)了。
為了更清晰表示這個(gè)流程,我畫了一張圖,這張圖的左半部分表示接收流程,而圖中的粉色箭頭則表示網(wǎng)絡(luò)包的處理路徑。
了解網(wǎng)絡(luò)包的接收流程后,就很容易理解網(wǎng)絡(luò)包的發(fā)送流程。網(wǎng)絡(luò)包的發(fā)送流程就是上圖的右半部分,很容易發(fā)現(xiàn),網(wǎng)絡(luò)包的發(fā)送方向,正好跟接收方向相反。
首先,應(yīng)用程序調(diào)用 Socket API(比如 sendmsg)發(fā)送網(wǎng)絡(luò)包。
由于這是一個(gè)系統(tǒng)調(diào)用,所以會(huì)陷入到內(nèi)核態(tài)的套接字層中。套接字層會(huì)把數(shù)據(jù)包放到 Socket 發(fā)送緩沖區(qū)中。
接下來,網(wǎng)絡(luò)協(xié)議棧從 Socket 發(fā)送緩沖區(qū)中,取出數(shù)據(jù)包;再按照 TCP/IP 棧,從上到下逐層處理。比如,傳輸層和網(wǎng)絡(luò)層,分別為其增加 TCP 頭和 IP 頭,執(zhí)行路由查找確認(rèn)下一跳的 IP,并按照 MTU 大小進(jìn)行分片。
分片后的網(wǎng)絡(luò)包,再送到網(wǎng)絡(luò)接口層,進(jìn)行物理地址尋址,以找到下一跳的 MAC 地址。然后添加幀頭和幀尾,放到發(fā)包隊(duì)列中。這一切完成后,會(huì)有軟中斷通知驅(qū)動(dòng)程序:發(fā)包隊(duì)列中有新的網(wǎng)絡(luò)幀需要發(fā)送。
最后,驅(qū)動(dòng)程序通過 DMA ,從發(fā)包隊(duì)列中讀出網(wǎng)絡(luò)幀,并通過物理網(wǎng)卡把它發(fā)送出去。
多臺(tái)服務(wù)器通過網(wǎng)卡、交換機(jī)、路由器等網(wǎng)絡(luò)設(shè)備連接到一起,構(gòu)成了相互連接的網(wǎng)絡(luò)。由于網(wǎng)絡(luò)設(shè)備的異構(gòu)性和網(wǎng)絡(luò)協(xié)議的復(fù)雜性,國(guó)際標(biāo)準(zhǔn)化組織定義了一個(gè)七層的 OSI 網(wǎng)絡(luò)模型,但是這個(gè)模型過于復(fù)雜,實(shí)際工作中的事實(shí)標(biāo)準(zhǔn),是更為實(shí)用的 TCP/IP 模型。
TCP/IP 模型,把網(wǎng)絡(luò)互聯(lián)的框架,分為應(yīng)用層、傳輸層、網(wǎng)絡(luò)層、網(wǎng)絡(luò)接口層等四層,這也是 Linux 網(wǎng)絡(luò)棧最核心的構(gòu)成部分。
我結(jié)合網(wǎng)絡(luò)上查閱的資料和文章中的內(nèi)容,總結(jié)了下網(wǎng)卡收發(fā)報(bào)文的過程,不知道是否正確:
當(dāng)發(fā)送數(shù)據(jù)包時(shí),與上述相反。鏈路層將數(shù)據(jù)包封裝完畢后,放入網(wǎng)卡的DMA緩沖區(qū),并調(diào)用系統(tǒng)硬中斷,通知網(wǎng)卡從緩沖區(qū)讀取并發(fā)送數(shù)據(jù)。
了解 Linux 網(wǎng)絡(luò)的基本原理和收發(fā)流程后,你肯定迫不及待想知道,如何去觀察網(wǎng)絡(luò)的性能情況。具體而言,哪些指標(biāo)可以用來衡量 Linux 的網(wǎng)絡(luò)性能呢?
實(shí)際上,我們通常用帶寬、吞吐量、延時(shí)、PPS(Packet Per Second)等指標(biāo)衡量網(wǎng)絡(luò)的性能。
除了這些指標(biāo),網(wǎng)絡(luò)的可用性(網(wǎng)絡(luò)能否正常通信)、并發(fā)連接數(shù)(TCP 連接數(shù)量)、丟包率(丟包百分比)、重傳率(重新傳輸?shù)木W(wǎng)絡(luò)包比例)等也是常用的性能指標(biāo)。
分析網(wǎng)絡(luò)問題的之一步,通常是查看網(wǎng)絡(luò)接口的配置和狀態(tài)。你可以使用 ifconfig 或者 ip 命令,來查看網(wǎng)絡(luò)的配置。我個(gè)人更推薦使用 ip 工具,因?yàn)樗峁┝烁S富的功能和更易用的接口。
以網(wǎng)絡(luò)接口 eth0 為例,你可以運(yùn)行下面的兩個(gè)命令,查看它的配置和狀態(tài):
你可以看到,ifconfig 和 ip 命令輸出的指標(biāo)基本相同,只是顯示格式略微不同。比如,它們都包括了網(wǎng)絡(luò)接口的狀態(tài)標(biāo)志、MTU 大小、IP、子網(wǎng)、MAC 地址以及網(wǎng)絡(luò)包收發(fā)的統(tǒng)計(jì)信息。
之一,網(wǎng)絡(luò)接口的狀態(tài)標(biāo)志。ifconfig 輸出中的 RUNNING ,或 ip 輸出中的 LOWER_UP ,都表示物理網(wǎng)絡(luò)是連通的,即網(wǎng)卡已經(jīng)連接到了交換機(jī)或者路由器中。如果你看不到它們,通常表示網(wǎng)線被拔掉了。
第二,MTU 的大小。MTU 默認(rèn)大小是 1500,根據(jù)網(wǎng)絡(luò)架構(gòu)的不同(比如是否使用了 VXLAN 等疊加網(wǎng)絡(luò)),你可能需要調(diào)大或者調(diào)小 MTU 的數(shù)值。
第三,網(wǎng)絡(luò)接口的 IP 地址、子網(wǎng)以及 MAC 地址。這些都是保障網(wǎng)絡(luò)功能正常工作所必需的,你需要確保配置正確。
第四,網(wǎng)絡(luò)收發(fā)的字節(jié)數(shù)、包數(shù)、錯(cuò)誤數(shù)以及丟包情況,特別是 TX 和 RX 部分的 errors、dropped、overruns、carrier 以及 collisions 等指標(biāo)不為 0 時(shí),通常表示出現(xiàn)了網(wǎng)絡(luò) I/O 問題。其中:
ifconfig 和 ip 只顯示了網(wǎng)絡(luò)接口收發(fā)數(shù)據(jù)包的統(tǒng)計(jì)信息,但在實(shí)際的性能問題中,網(wǎng)絡(luò)協(xié)議棧中的統(tǒng)計(jì)信息,我們也必須關(guān)注。你可以用 netstat 或者 ss ,來查看套接字、網(wǎng)絡(luò)棧、網(wǎng)絡(luò)接口以及路由表的信息。
我個(gè)人更推薦,使用 ss 來查詢網(wǎng)絡(luò)的連接信息,因?yàn)樗?netstat 提供了更好的性能(速度更快)。
比如,你可以執(zhí)行下面的命令,查詢套接字信息:
netstat 和 ss 的輸出也是類似的,都展示了套接字的狀態(tài)、接收隊(duì)列、發(fā)送隊(duì)列、本地地址、遠(yuǎn)端地址、進(jìn)程 PID 和進(jìn)程名稱等。
其中,接收隊(duì)列(Recv-Q)和發(fā)送隊(duì)列(Send-Q)需要你特別關(guān)注,它們通常應(yīng)該是 0。當(dāng)你發(fā)現(xiàn)它們不是 0 時(shí),說明有網(wǎng)絡(luò)包的堆積發(fā)生。當(dāng)然還要注意,在不同套接字狀態(tài)下,它們的含義不同。
當(dāng)套接字處于連接狀態(tài)(Established)時(shí),
當(dāng)套接字處于監(jiān)聽狀態(tài)(Listening)時(shí),
所謂全連接,是指服務(wù)器收到了客戶端的 ACK,完成了 TCP 三次握手,然后就會(huì)把這個(gè)連接挪到全連接隊(duì)列中。這些全連接中的套接字,還需要被 accept() 系統(tǒng)調(diào)用取走,服務(wù)器才可以開始真正處理客戶端的請(qǐng)求。
與全連接隊(duì)列相對(duì)應(yīng)的,還有一個(gè)半連接隊(duì)列。所謂半連接是指還沒有完成 TCP 三次握手的連接,連接只進(jìn)行了一半。服務(wù)器收到了客戶端的 SYN 包后,就會(huì)把這個(gè)連接放到半連接隊(duì)列中,然后再向客戶端發(fā)送 SYN+ACK 包。
類似的,使用 netstat 或 ss ,也可以查看協(xié)議棧的信息:
這些協(xié)議棧的統(tǒng)計(jì)信息都很直觀。ss 只顯示已經(jīng)連接、關(guān)閉、孤兒套接字等簡(jiǎn)要統(tǒng)計(jì),而 netstat 則提供的是更詳細(xì)的網(wǎng)絡(luò)協(xié)議棧信息。
比如,上面 netstat 的輸出示例,就展示了 TCP 協(xié)議的主動(dòng)連接、被動(dòng)連接、失敗重試、發(fā)送和接收的分段數(shù)量等各種信息。
接下來,我們?cè)賮砜纯?,如何查看系統(tǒng)當(dāng)前的網(wǎng)絡(luò)吞吐量和 PPS。在這里,我推薦使用我們的老朋友 sar,在前面的 CPU、內(nèi)存和 I/O 模塊中,我們已經(jīng)多次用到它。
給 sar 增加 -n 參數(shù)就可以查看網(wǎng)絡(luò)的統(tǒng)計(jì)信息,比如網(wǎng)絡(luò)接口(DEV)、網(wǎng)絡(luò)接口錯(cuò)誤(EDEV)、TCP、UDP、ICMP 等等。執(zhí)行下面的命令,你就可以得到網(wǎng)絡(luò)接口統(tǒng)計(jì)信息:
這兒輸出的指標(biāo)比較多,我來簡(jiǎn)單解釋下它們的含義。
其中,Bandwidth 可以用 ethtool 來查詢,它的單位通常是 Gb/s 或者 Mb/s,不過注意這里小寫字母 b ,表示比特而不是字節(jié)。我們通常提到的千兆網(wǎng)卡、萬兆網(wǎng)卡等,單位也都是比特。如下你可以看到,我的 eth0 網(wǎng)卡就是一個(gè)千兆網(wǎng)卡:
其中,Bandwidth 可以用 ethtool 來查詢,它的單位通常是 Gb/s 或者 Mb/s,不過注意這里小寫字母 b ,表示比特而不是字節(jié)。我們通常提到的千兆網(wǎng)卡、萬兆網(wǎng)卡等,單位也都是比特。如下你可以看到,我的 eth0 網(wǎng)卡就是一個(gè)千兆網(wǎng)卡:
我們通常使用帶寬、吞吐量、延時(shí)等指標(biāo),來衡量網(wǎng)絡(luò)的性能;相應(yīng)的,你可以用 ifconfig、netstat、ss、sar、ping 等工具,來查看這些網(wǎng)絡(luò)的性能指標(biāo)。
小狗同學(xué)問到: 老師,您好 ss —lntp 這個(gè) 當(dāng)session處于listening中 rec-q 確定是 syn的backlog嗎?
A: Recv-Q為全連接隊(duì)列當(dāng)前使用了多少。 中文資料里這個(gè)問題講得最明白的文章:
看了源碼發(fā)現(xiàn),這個(gè)地方講的有問題.關(guān)于ss輸出中l(wèi)isten狀態(tài)套接字的Recv-Q表示全連接隊(duì)列當(dāng)前使用了多少,也就是全連接隊(duì)列的當(dāng)前長(zhǎng)度,而Send-Q表示全連接隊(duì)列的更大長(zhǎng)度
關(guān)于linux調(diào)用網(wǎng)絡(luò)模塊的介紹到此就結(jié)束了,不知道你從中找到你需要的信息了嗎 ?如果你還想了解更多這方面的信息,記得收藏關(guān)注本站。
創(chuàng)新互聯(lián)(cdcxhl.com)提供穩(wěn)定的云服務(wù)器,香港云服務(wù)器,BGP云服務(wù)器,雙線云服務(wù)器,高防云服務(wù)器,成都云服務(wù)器,服務(wù)器托管。精選鉅惠,歡迎咨詢:028-86922220。
本文題目:如何在Linux中調(diào)用網(wǎng)絡(luò)模塊?(linux調(diào)用網(wǎng)絡(luò)模塊)
標(biāo)題鏈接:http://m.fisionsoft.com.cn/article/cdioeep.html


咨詢
建站咨詢
