<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > Linux串口上網(wǎng)的程序?qū)崿F(xiàn)方法

          Linux串口上網(wǎng)的程序?qū)崿F(xiàn)方法

          作者: 時間:2011-05-10 來源:網(wǎng)絡(luò) 收藏
          如果我們設(shè)置另一臺 box的偽網(wǎng)接口地址是192.168.5.2那么,我們可以用線直接連接兩臺終端并使用網(wǎng)絡(luò)應(yīng)用了,在兩臺終端上運(yùn)行server守護(hù),然后執(zhí)行telnet:

          本文引用地址:http://www.ex-cimer.com/article/150775.htm

          [root@localhost test]# telnet 192.168.5.2

          Trying 192.168.5.2...

          Connected to 192.168.5.2 (192.168.5.2).

          Escape character is '^]'.

          Red Hat release 9 (Shrike)

          Kernel 2.4.20-8 on an i686

          login:

          編寫字符設(shè)備驅(qū)動用戶空間的進(jìn)程主要通過兩種方式和內(nèi)核空間模塊打交道,一種是使用proc文件系統(tǒng),另一種是使用字符設(shè)備。本文所描述的兩個字符設(shè)備sending device 和receiving device事實上是內(nèi)核空間和用戶空間交換數(shù)據(jù)的緩存區(qū),編寫字符設(shè)備驅(qū)動實際上就是編寫用戶空間讀寫字符設(shè)備所需要的內(nèi)核設(shè)備操作函數(shù)。 在頭文件中,我們定義ED_REC_DEVICE為receiving device,名字是ed_rec;定義ED_TX_DEVICE為sending device,名字是ed_tx。 #define MAJOR_NUM_REC 200

          #define MAJOR_NUM_TX 201

          #define IOCTL_SET_BUSY _IOWR(MAJOR_NUM_TX,1,int)

          200和201分別代表receiving device 和 sending device的主設(shè)備號。在內(nèi)核空間,驅(qū)動程序是根據(jù)主、次設(shè)備號識別設(shè)備的,而不是設(shè)備名;本文的字符設(shè)備的次設(shè)備號都是0,主設(shè)備號是用戶定義的且不能和系統(tǒng)已有的設(shè)備的主設(shè)備有沖突。IOCTL_SET_BUSY _IOWR(MAJOR_NUM_TX,1,int)是ioctl的操作函數(shù)定義(從用戶空間發(fā)送命令到內(nèi)核空間),主要作用是使得每次在同一時間,同一字符設(shè)備上,只可進(jìn)行一次操作。我們可以使用mknod來建立這兩個字符設(shè)備 [root@localhost]#mknod c 200 0 /dev/ed_rec

          [root@localhost]#mknod c 201 0 /dev/ed_tx

          設(shè)備建立后,編譯好的模塊就可以動態(tài)加載了:[root@localhost]#insmod ed_device.o

          為了方便對設(shè)備編程,我們還需要一個字符設(shè)備管理的數(shù)據(jù)結(jié)構(gòu): struct ed_device{

          int magic;

          char name[8];

          int busy;

          unsigned char *buffer;

          #ifdef LINUX_24

          wait_queue_head_t rwait;

          #endif

          int mtu;

          spinlock_t lock;

          int data_len;

          int buffer_size;

          struct file *file;

          ssize_t (*kernel_write)(const char *buffer,size_t length,int buffer_size);

          };

          這個數(shù)據(jù)結(jié)構(gòu)是用來保存字符設(shè)備的一些基本狀態(tài)信息。ssize_t (*kernel_write)(const char *buffer,size_t length,int buffer_size) 是一個指向函數(shù)的指針,它的作用是為偽網(wǎng)絡(luò)驅(qū)動程序提供寫字符設(shè)備數(shù)據(jù)的系統(tǒng)調(diào)用接口。magic字段主要是標(biāo)志設(shè)備類型號的,這里沒有別的特殊意義;busy字段用來說明字符設(shè)備是否是處于忙狀態(tài),buffer指向內(nèi)核緩存區(qū),用來存放讀寫數(shù)據(jù);mtu保存當(dāng)前可發(fā)送的網(wǎng)絡(luò)數(shù)據(jù)包最大傳輸單位,以字節(jié)為單位;lock的類型是自旋鎖類型spinlock_t,它實際以一個整數(shù)域作為鎖,在同一時刻對同一字符設(shè)備,只能有一個操作,所以使用內(nèi)核鎖機(jī)制保護(hù)防止數(shù)據(jù)污染;data_len是當(dāng)前緩存區(qū)內(nèi)保存的數(shù)據(jù)實際大小,以字節(jié)為單位;file是指向設(shè)備文件結(jié)構(gòu)struct file的一個指針,其作用主要是定位設(shè)備的私有數(shù)據(jù) file-> private_data。定義字符設(shè)備struct ed_device ed[2],其中ed[ED_REC_DEVICE]就是receving device,ed[ED_TX_DEVICE]就是sending device。如果sending device ED_TX_DEVICE沒有數(shù)據(jù),用戶空間的read調(diào)用將被阻塞,并把進(jìn)程信息放于rwait隊列中。當(dāng)有數(shù)據(jù)的時候,kernel_write()中的wake_up_interruptible()將喚醒等待進(jìn)程。kernel_write()函數(shù)定義如下: ssize_t kernel_write(const char *buffer,size_t length,int buffer_size)

          {

          if(length > buffer_size )

          length = buffer_size;

          memset(ed[ED_TX_DEVICE].buffer,0,buffer_size);

          memcpy(ed[ED_TX_DEVICE].buffer,buffer,buffer_size);

          ed[ED_TX_DEVICE].tx_len = length;

          #ifdef LINUX_24

          wake_up_interruptible(ed[ED_TX_DEVICE].rwait);

          #endif

          return length;

          }

          字符設(shè)備的操作及其相關(guān)函數(shù)調(diào)用過程如圖3 所示。 圖 3 當(dāng)ed_device模塊被加載的時候,eddev_module_init()調(diào)用register_chrdev()內(nèi)核API注冊ed_tx和ed_rec兩個字符設(shè)備。這個函數(shù)定義在linux/fs.h>: int register_chdev(unsigned int major, const char *, struct fle_operations *fops)

          字符設(shè)備被注冊成功后,內(nèi)核把這兩個字符設(shè)備加入到內(nèi)核字符設(shè)備驅(qū)動表中。內(nèi)核字符設(shè)備驅(qū)動表保留指向struct file_operations的一個數(shù)據(jù)指針。用戶進(jìn)程調(diào)用設(shè)備讀寫操作時,通過這個指針訪問設(shè)備的操作函數(shù), struct file_operations中的域大部分是指向函數(shù)的函數(shù)指針,指向用戶自己編寫的設(shè)備操作函數(shù)。 struct file_operations ed_ops ={

          #ifdef LINUX_24

          NULL,

          #endif

          NULL,

          device_read,

          device_write,

          NULL,

          NULL,

          device_ioctl,

          NULL,

          device_open,

          NULL,

          device_release,

          };

          注意到2.4.x和Linux2.2.x內(nèi)核中定義的struct file_operations是不一樣的。device_read()、device_write()、device_ioctl()、device_open()、device_release()就是需要用戶自己定義的函數(shù)操作了,這幾個函數(shù)是最基本的操作,如果需要設(shè)備驅(qū)動程序完成更復(fù)雜的任務(wù),還必須編寫其他struct file_operations中定義的操作。eddev_module_init()除了注冊設(shè)備及其操作外,它還有初始化字符設(shè)備結(jié)構(gòu)struct ed_device,分配內(nèi)核緩存區(qū)所需要的空間的作用。在內(nèi)核空間,分配內(nèi)存空間的API函數(shù)是kmalloc()。 下面介紹一下字符設(shè)備的主要操作例程device_open()、device_release()、device_read()、devie_write()。字符設(shè)備文件操作結(jié)構(gòu)ed_ops中定義的指向以上函數(shù)的函數(shù)指針的原形: device_open: int(*open)(struct inode *,struct file *)

          device_release: int (*release) (struct inode *, struct file *);

          device_read: ssize_t (*read) (struct file *, char *, size_t, loff_t *);

          device_write: ssize_t (*write) (struct file *, const char *, size_t, loff_t *);

          linux操作系統(tǒng)文章專題:linux操作系統(tǒng)詳解(linux不再難懂)

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




          評論


          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();