<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > Linux串口上網(wǎng)的程序實(shí)現方法

Linux串口上網(wǎng)的程序實(shí)現方法

作者: 時(shí)間:2011-05-10 來(lái)源:網(wǎng)絡(luò ) 收藏
ether_setup()填充一些以太網(wǎng)的缺省設置。dev->hard_header_cache=NULL表示不緩存向本網(wǎng)絡(luò )接口回復的ARP網(wǎng)絡(luò )數據包。IFF_NOARP的標志設置表明本網(wǎng)絡(luò )接口不使用ARP。ARP的主要功能是獲得通信對方的網(wǎng)絡(luò )接口的硬件地址,本文的偽網(wǎng)絡(luò )接口的物理地址是中設定的偽物理地址,所以我們不需要ARP協(xié)議。SET_MODULE_OWNER(dev)這個(gè)宏是設置dev結構中owner域(定義為struct module *owner;),使得它指向本模塊本身。與字符設備一樣,本網(wǎng)絡(luò )設備也需要定義在其上的操作例程。下面就對ednet_init()中用戶(hù)定義的設備操作函數做進(jìn)一步說(shuō)明。整個(gè)偽網(wǎng)絡(luò )設備操作調用結構如圖6所示。

本文引用地址:http://dyxdggzs.com/article/150775.htm

圖 6

由圖6我們看到,ednet_rx()并不是網(wǎng)絡(luò )設備的一個(gè)操作,而是模塊中的一個(gè)函數。在實(shí)際的網(wǎng)卡驅動(dòng)中,當網(wǎng)卡確實(shí)接收到數據的時(shí)候,由網(wǎng)絡(luò )中斷喚醒等待接收數據的用戶(hù)進(jìn)程,也就是說(shuō),ednet_rx()應該由那個(gè)網(wǎng)絡(luò )中斷處理例程調用。我們這里并沒(méi)有中斷,所以字符設備的device_write()可以看成是一個(gè)中斷例程,也就是說(shuō),用戶(hù)空間往字符寫(xiě)操作的時(shí)候,也就調用了網(wǎng)絡(luò )設備的數據接收內核例程ednet_rx()了。然后ednet_rx()會(huì )把原始的數據包發(fā)送到TCP/IP上層進(jìn)行處理,這一切均依賴(lài)于內核API 函數netif_rx()。ednet_rx()就需要sk_buff數據結構(linux/skbuff.h>中定義),用來(lái)存放從網(wǎng)絡(luò )接口接收到的原始網(wǎng)絡(luò )數據,分配后的sk_buff結構將在TCP/IP協(xié)議棧上被釋放掉。

下面介紹一下網(wǎng)絡(luò )設備的主要操作例程ednet_open()、ednet_release()、ednet_tx()、ednet_stats ()、ednet_change_mtu()、ednet_header()。網(wǎng)絡(luò )設備文件操作結構struct net_device(linux/netdevice.h>中有定義)中定義了指向以上函數的函數指針的原形:

ednet_open: int (*open)(struct net_device *dev);

ednet_release: int (*stop)(struct net_device *dev);

ednet_tx: int (*hard_start_xmit) (struct sk_buff *skb,struct net_device *dev);

ednet_stats: struct net_device_stats* (*get_stats)(struct net_device *dev);

ednet_change_mtu:int(*change_mtu)(struct net_device *dev, int new_mtu);

ednet_header: int (*hard_header) (struct sk_buff *skb,

struct net_device *dev,

unsigned short type,

void *daddr,

void *saddr,

unsigned len);

操作int ednet_open(struct net_device *dev)的作用是打開(kāi)偽網(wǎng)絡(luò )接口設備,獲得其需要的I/O端口、IRQ等,但是本網(wǎng)絡(luò )接口不需要和實(shí)際硬件打交道,所以不需要自動(dòng)獲得或者賦予I/O端口值,也不需要IRQ中斷號,唯一需要指定的是其偽硬件地址(這個(gè)硬件地址是0ED000,ifconfig可以看到其硬件地址是 00:45:44:30:30:30,struct net_device中的dev_addr域存放網(wǎng)絡(luò )接口的物理地址。操作ednet_open()必須調用netif_start_queue()內核API開(kāi)啟網(wǎng)絡(luò )接口接收和發(fā)送數據隊列。

當接口關(guān)閉的時(shí)候,int ednet_release(struct net_device *dev)例程被系統調用,在ednet_release()中調用netif_stop_queque()將停止接收和發(fā)送隊列的工作。

偽網(wǎng)絡(luò )設備驅動(dòng)的傳送例程int ednet_tx(struct sk_buff *skb, struct net_device *dev)將把要發(fā)送的網(wǎng)絡(luò )數據包寫(xiě)入字符設備ed[ED_TX_DEVICE]。在發(fā)送完畢數據包的時(shí)候,dev_kfree_skb() Kernel API釋放由上層協(xié)議棧分配的sk_buff數據塊。偽網(wǎng)絡(luò )接口在進(jìn)行硬件傳輸的時(shí)候,需要為網(wǎng)絡(luò )數據包打上時(shí)間戳。如果傳送數據包的時(shí)候超時(shí),將調用超時(shí)處理例程ednet_tx_timeout()超時(shí)處理例程。例程ednet_tx()調用真正的硬件傳送例程ednet_hw_tx()在實(shí)際的網(wǎng)卡驅動(dòng)程序中,就是真正向特定的網(wǎng)絡(luò )硬件設備寫(xiě)數據的程序。我們看到,我們的硬件就是本文前面描述的字符設備,字符設備的操作例程.kernel_write()在ednet_hw_tx()將被調用。

如果我們希望使用ifconfig看到偽網(wǎng)絡(luò )接口的統計信息,那么系統就調用 struct net_device_stats *ednet_stats(struct net_device *dev)。我們看到,網(wǎng)絡(luò )接口的統計信息被放到設備的私有數據指針指向的內存。網(wǎng)絡(luò )數據信息的統計結構被放在內核結構struct net_device_stats中。

在TCP會(huì )話(huà)中,也許要協(xié)商MTU的大小,int ednet_change_mtu(struct net_device *dev, int new_mtu)可以隨時(shí)改變MTU的大小。比如在使用FTP協(xié)議的時(shí)候,在傳送數據庫的時(shí)候,MTU可能被協(xié)商為最大,以提高網(wǎng)絡(luò )傳送吞吐量。由于改變了MTU,存放網(wǎng)絡(luò )數據的字符設備初始化分配的緩存區就要重新被分配,并把已經(jīng)存放數據的舊的緩存區的內容拷貝到新的緩存區中,所以,當MTU改變大小的時(shí)候,那么就要使用kmalloc(new_mtu ,GFP_KERNEL)重新分配緩存區。讀者可以根據自己的需要定義新的緩存區大小。kfree()是內核API,負責釋放內核空間的內存,它的使用和用戶(hù)空間的free()系統調用一致,這里就不列舉ed_realloc()函數的源程序了。

IP數據包在被網(wǎng)絡(luò )接口發(fā)送前,需要構建其以太網(wǎng)頭信息int ednet_header(struct sk_buff *skb,struct net_device *dev,unsigned short type,void *daddr,void *saddr,unsigned int len)例程完成此功能,我們看到網(wǎng)絡(luò )數據包的以太源、目的地址,都是從發(fā)送這個(gè)數據包的網(wǎng)絡(luò )接口設備數據結構struct net_device中得到的。源地址和目的地址信息是從網(wǎng)絡(luò )設備結構得到的。在編譯本程序的時(shí)候,如果發(fā)現htons()這個(gè)函數沒(méi)有定義,可以這樣定義htons()為:#define htons(x) ((x>>8) | (x8)) 。

因為偽網(wǎng)絡(luò )接口沒(méi)有使用ARP獲得硬件地址,所以我們可以把我們自己定義的偽硬件地址復制到數據包的以太網(wǎng)包頭。2.4.x使用設備hard_header()代替設備rebuild_header()。2.x使用的rebuild_header()例程在本文的附加源程序中,這里不再說(shuō)明。

編寫(xiě)用戶(hù)空間通信程序

控制的server應用程序完成非常簡(jiǎn)單的打包和拆包的工作,它沒(méi)有差錯控制,沒(méi)有重發(fā)機制,在實(shí)際應用中,需要加上適當的控制協(xié)議。server創(chuàng )建的子進(jìn)程負責從讀取數據并把數據傳送到receiving device /dev/ed_rec;父進(jìn)程則負責從sending device /dev/ed_tx 讀取需要發(fā)送的網(wǎng)絡(luò )數據包,然后從串口發(fā)送出去。子進(jìn)程和父進(jìn)程都是用輪詢(xún)方式讀取和寫(xiě)入設備。Server的程序流圖如圖所示。


圖 7

傳送的frame按照SLIP定義的格式:數據的兩頭都是END字符(0300),如圖8所示。

圖 8

特殊控制字符的定義如下:

#define END 0300

#define ESC 0333

#define ESC_END 0334

#define ESC_ESC 0335

linux操作系統文章專(zhuān)題:linux操作系統詳解(linux不再難懂)

linux相關(guān)文章:linux教程




評論


相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>