<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ò ) 收藏
操作int device_open(struct inode *inode,struct file *file)是設備節點(diǎn)上的第一個(gè)操作,如果多個(gè)設備共享這一個(gè)操作函數,必須區分設備的設備號。我們使用inode->i_rdev >> 8 語(yǔ)句獲得設備的主設備號,本文中的接收設備主設備號是200,發(fā)送設備號是201。每個(gè)字符設備的file>private_data指向打開(kāi)設備時(shí)候使用的file結構,private_data實(shí)際上可以指向用戶(hù)定義的任何結構,這里只指向我們自己定義的struct ed_device,用來(lái)保存字符設備的一些基本信息,比如設備名、內核緩存區等。 操作ssize_t device_read(struct file *file,char *buffer,size_t length, loff_t *offset)是讀取設備數據的操作。device_read()結構如圖4所示。 圖4 從設備中讀取數據(用戶(hù)空間調用read()系統調用)的時(shí)候,需要從內核空間把數據拷貝到用戶(hù)空間,copy_to_user()可完成此功能,它和memcpy()此類(lèi)函數有本質(zhì)的區別,memcpy()不能完成不同用戶(hù)空間數據的交換。如果需要數據臨界區的保護,使用spin_lock()內核API負責加鎖,spin_unlock()負責解鎖,防止數據污染。由于守候進(jìn)程server需要不斷輪詢(xún)設備,以查詢(xún)是否有數據可讀,如果用戶(hù)進(jìn)程不處于休眠狀態(tài),在用戶(hù)空間查看進(jìn)程使用資源情況,發(fā)現server占用了很多CPU資源。所以我們改進(jìn)device_read(),使之在內核中輪詢(xún),當發(fā)現當前設備沒(méi)有數據可讀取,那么就阻塞用戶(hù)進(jìn)程,使用內核API add_wait_queue()可完成此功能,這時(shí)候用戶(hù)進(jìn)程并沒(méi)有占用很多CPU資源,而是處于休眠狀態(tài)。當內核發(fā)現有數據可讀的時(shí)候,調用remove_wait_queue()即可喚醒等待進(jìn)程,這段 代碼如下: DECLARE_WAITQUEUE(wait,current);

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

add_wait_queue(edp->rwait,wait);

for(;;){

set_current_state(TASK_INTERRUPTIBLE);

if ( file->f_flags O_NONBLOCK)

break;

/*其他代碼 */

if ( signal_pending(current))

break;

schedule();

}

set_current_state(TASK_RUNNING);

remove_wait_queue(edp->rwait,wait);

操作ssize_t device_write(struct file *file,const char *buffer, size_t length,loff_t *offset)向設備寫(xiě)入數據??截悢祿腸opy_from_user()和copy_to_user()的功能恰恰相反,它是從用戶(hù)空間拷貝數據到內核空間,如圖5所示。

圖 5

編寫(xiě)偽網(wǎng)絡(luò )設備驅動(dòng)

偽網(wǎng)絡(luò )驅動(dòng)和字符設備驅動(dòng)一樣,也必須初始化和注冊。網(wǎng)絡(luò )驅動(dòng)需記錄其發(fā)送和接收數據量的統計信息,所以我們定義一個(gè)記錄這些信息的數據結構。

struct ednet_priv {

#ifdef LINUX_24

struct net_device_stats stats;

#else

struct enet_statistics stats;

#endif

struct sk_buff *skb;

spinlock_t lock;

};

struct ednet_priv只有3個(gè)數據成員。2.4.x 使用的網(wǎng)絡(luò )數據狀態(tài)統計結構是struct net_device_stats,而 2.2.x則使用的是struct enet_statistics。同樣,對控制網(wǎng)絡(luò )接口設備的設備結構也有不同的定義:2.4.x使用的是struct net_device,而Linux2.2.x卻是struct device。

#ifdef LINUX_24

struct net_device ednet_dev;

#else

struct device ednet_dev;

#endif

偽網(wǎng)絡(luò )驅動(dòng)程序的也需要初始化和注冊。和字符設備的注冊不同之處是,它使用的是register_netdev(net_device *) kernel API。

int ednet_module_init(void)

{

int err;

strcpy(ednet_dev.name, ed0);

ednet_dev.init = ednet_init;

if ( (err = register_netdev(ednet_dev)) )

printk(ednet: error %i registering pseudo network device %sn,

err, ednet_dev.name);

return err;

}

ednet_dev的name域是接口名,ednet_module_init()中賦予網(wǎng)絡(luò )接口的名字為ed0,如果本網(wǎng)絡(luò )設備被加載,使用ifconfig命令可以看到ed0。

[root@localhost pku]# /sbin/ifconfig

ed0 Link encap:Ethernet HWaddr 00:45:44:30:30:30

inet addr:192.168.3.9 Bcast:192.168.3.255 Mask:255.255.255.0

UP BROADCAST RUNNING NOARP MULTICAST MTU:1500 Metric:1

RX packets:0 errors:0 dropped:0 overruns:0 frame:0

TX packets:0 errors:0 dropped:0 overruns:0 carrier:0

collisions:0 txqueuelen:100

RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)

我們看到我們的偽網(wǎng)絡(luò )接口沒(méi)有Interrupt和Base address,這是因為這個(gè)偽網(wǎng)絡(luò )接口不和硬件打交道,也沒(méi)有分配中斷號和IO基址。否則,如果你看一個(gè)實(shí)實(shí)在在的網(wǎng)絡(luò )接口(如下面的eth1),可以看到它的Interrupt號是11和IO Base address是0xa000。

eth1 Link encap:Ethernet HWaddr 50:78:4C:43:1D:01

inet addr:192.168.21.202 Bcast:192.168.21.255 Mask:255.255.255.0

UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1

RX packets:356523 errors:0 dropped:0 overruns:0 frame:0

TX packets:266 errors:0 dropped:0 overruns:0 carrier:0

collisions:0 txqueuelen:100

RX bytes:21542043 (20.5 Mb) TX bytes:19510 (19.0 Kb)

Interrupt:11 Base address:0xa000

ednet_dev的init域是一個(gè)函數指針,指向用戶(hù)定義的ednet_init()例程。ednet_init()添充net_device結構,只有ednet_init()初始化成功后,系統才被加入到設備鏈表中。ednet_dev的初始化例程ednet_init()如下:

#ifdef LINUX_24

int ednet_init(struct net_device *dev)

#else

int ednet_init(struct device *dev)

#endif

{

ether_setup(dev);

dev->open = ednet_open;

dev->stop = ednet_release;

dev->hard_start_xmit = ednet_tx;

dev->get_stats = ednet_stats;

dev->change_mtu = ednet_change_mtu;

#ifdef LINUX_24

dev->hard_header = ednet_header;

#endif

dev->rebuild_header = ednet_rebuild_header;

#ifdef LINUX_24

dev->tx_timeout = ednet_tx_timeout;

dev->watchdog_timeo = timeout;

#endif

/* We do not need the ARP protocol. */

dev->flags |= IFF_NOARP;

#ifndef LINUX_20

dev->hard_header_cache = NULL;

#endif

#ifdef LINUX_24

SET_MODULE_OWNER(dev);

#endif

dev->priv = kmalloc(sizeof(struct ednet_priv), GFP_KERNEL);

if (dev->priv == NULL)

return -ENOMEM;

memset(dev->priv, 0, sizeof(struct ednet_priv));

spin_lock_init( ((struct ednet_priv *) dev->priv)->lock);

return 0;

}

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>