




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)
文檔簡介
1、PPP 驅(qū)動程序的基本原理1) ppp設(shè)備是指在點對點的物理鏈路之間使用PPP幀進行分組交換的內(nèi)核網(wǎng)絡(luò)接口設(shè)備,由于 Linux 內(nèi)核將串行設(shè)備作為終端設(shè)備來驅(qū)動 , 于是引入 PPP 終端規(guī)程來實現(xiàn)終端設(shè)備與 PPP設(shè)備的接口 根據(jù)終端設(shè)備的物理傳輸特性的不同,PPP規(guī)程分為異步規(guī)程(N_PPP)和同步規(guī)程(N_SYNC_PPP)兩種,對于普通串口設(shè)備使用異步PPP規(guī)程2) 在 PPP 驅(qū)動程序中 , 每一 tty 終端設(shè)備對應(yīng)于一條 PPP 傳輸通道 (chanell), 每一 ppp 網(wǎng)絡(luò)設(shè)備對應(yīng)于一個 PPP接口單元(unit).從終端設(shè)備上接收到的數(shù)據(jù)流通過PPP傳輸通道解碼后轉(zhuǎn)換成
2、PPP幀傳遞到PPP網(wǎng)絡(luò)接口單元,PPP接口單元再將 PPP幀轉(zhuǎn)換為PPP設(shè)備的接 收幀反之,當(dāng)PPP設(shè)備發(fā)射數(shù)據(jù)幀時,發(fā)射幀通過PPP接口單元轉(zhuǎn)換成 PPP幀傳遞給PPP 通道,PPP通道負(fù)責(zé)將PPP幀編碼后寫入終端設(shè)備在配置了多鏈路PPP時 (CONFIG_PPP_MULTILINK), 多個PPP傳輸通道可連接到同一PPP接口單元 PPP接口單元將PPP幀分割成若干個片段傳遞給不同的PPP傳輸通道,反之,PPP傳輸通道接收到的PPP幀片段被PPP接口單元重組成完整的PPP幀3) 在Linux-2.4中,應(yīng)用程序可通過字符設(shè)備 /dev/ppp監(jiān)控內(nèi)核PPP驅(qū)動程序用戶可以用 ioctl(
3、PPPIOCATTACH)將文件綁定到 PPP接口單元上,來讀寫PPP接口單元的輸出幀,也可 以用ioctl(PPPIOCATTCHAN)將文件綁定到PPP傳輸通道上,來讀寫PPP傳輸通道的輸入幀4) PPP傳輸通道用channel結(jié)構(gòu)描述,系統(tǒng)中所有打開的傳輸通道在all_channels鏈表中 PPP接口單元用 ppp 結(jié)構(gòu)描述 , 系統(tǒng)中所有建立的接口單元在 all_ppp_units 鏈表中 當(dāng)終端設(shè)備 的物理鏈路連接成功后,用戶使用ioctl(TIOCSETD)將終端切換到PPP規(guī)程 PPP規(guī)程初始化 時,將建立終端設(shè)備的傳輸通道和通道驅(qū)動結(jié)構(gòu)對于異步PPP規(guī)程來說,通道驅(qū)動結(jié)構(gòu)為a
4、syncppp,它包含通道操作表async_ops傳輸通道和接口單元各自包含自已的設(shè)備文件(/dev/ppp)參數(shù)結(jié)構(gòu)(ppp_file).;drivers/char/tty_io.c:int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc)if (disc < N_TTY | disc >= NR_LDISCS)return -EINV AL;if (new_ldisc) ldiscsdisc = *new_ldisc;ldiscsdiscflags |= LDISC_FLAG_DEFINED; ldiscsdis
5、c. num = disc; elsememset(&ldiscsdisc, 0, sizeof(struct tty_ldisc);return 0;int tty_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg)struct tty_struct *tty, *real_tty;int retval;tty = (struct tty_struct *)file->private_data;if (tty_paranoia_check(tty, inode-
6、>i_rdev, "tty_ioctl") return -EINV AL;real_tty = tty;if (tty->driver.type = TTY_DRIVER_TYPE_PTY && tty->driver.subtype = PTY_TYPE_MASTER) real_tty = tty->link;switch (cmd) case TIOCGETD:return put_user(tty->ldisc.num, (int *) arg);case TIOCSETD:return tiocsetd(tty, (
7、int *) arg);if (tty->driver.ioctl) int retval = (tty->driver.ioctl)(tty, file, cmd, arg);if (retval != -ENOIOCTLCMD)return retval;if (tty->ldisc.ioctl) int retval = (tty->ldisc.ioctl)(tty, file, cmd, arg);if (retval != -ENOIOCTLCMD)return retval;return -EINV AL;static int tiocsetd(struct
8、 tty_struct *tty, int *arg)int retval, ldisc;retval = get_user(ldisc, arg);if (retval)return retval;return tty_set_ldisc(tty, ldisc);/* Set the discipline of a tty line. */static int tty_set_ldisc(struct tty_struct *tty, int ldisc)int retval = 0;struct tty_ldisc o_ldisc;char buf64;if (ldisc < N_T
9、TY) | (ldisc >= NR_LDISCS)return -EINV AL;/* Eduardo Blanco */* Cyrus Durgin */if (!(ldiscsldisc.flags & LDISC_FLAG_DEFINED) 如果設(shè)定的規(guī)程不存在 char modname 20;sprintf(modname, "tty-ldisc-%d", ldisc);request_module (modname); 嘗試加載模塊if (!(ldiscsldisc.flags & LDISC_FLAG_DEFINED)return -EI
10、NV AL;if (tty->ldisc.num = ldisc)return 0; /* We are already in the desired discipline */ o_ldisc = tty->ldisc;tty_wait_until_sent(tty, 0); 等待終端輸出設(shè)備的數(shù)據(jù)發(fā)送完/* Shutdown the current discipline. */ if (tty->ldisc.close)(tty->ldisc.close)(tty); 關(guān)閉原來的規(guī)程/* Now set up the new line discipline. */
11、tty->ldisc = ldiscsldisc; tty->termios->c_line = ldisc;if (tty->ldisc.open)retval = (tty->ldisc.open)(tty); 打開新規(guī)程if (retval < 0) 如果打開失敗 , 恢復(fù)原來的規(guī)程tty->ldisc = o_ldisc;tty->termios->c_line = tty->ldisc.num;if (tty->ldisc.open && (tty->ldisc.open(tty) < 0)
12、 tty->ldisc = ldiscsN_TTY;tty->termios->c_line = N_TTY;if (tty->ldisc.open) int r = tty->ldisc.open(tty);if (r < 0) panic("Couldn't open N_TTY ldisc for ""%s - error %d.", tty_name(tty, buf), r);if (tty->ldisc.num != o_ldisc.num && tty->driver.
13、set_ldisc) tty->driver.set_ldisc(tty);return retval; drivers/char/tty_ioctl.c:/* Internal flag options for termios setting behavior*/#define TERMIOS_FLUSH 1#define TERMIOS_WAIT 2#define TERMIOS_TERMIO 4void tty_wait_until_sent(struct tty_struct * tty, long timeout) DECLARE_W AITQUEUE(wait, curren
14、t);#ifdef TTY_DEBUG_W AIT_UNTIL_SENT char buf64;printk("%s wait until sent.n", tty_name(tty, buf); #endifif (!tty->driver.chars_in_buffer)return; add_wait_queue(&tty->write_wait, &wait);if (!timeout)timeout = MAX_SCHEDULE_TIMEOUT; do #ifdef TTY_DEBUG_W AIT_UNTIL_SENT printk(&
15、quot;waiting %s.(%d)n", tty_name(tty, buf), tty->driver.chars_in_buffer(tty);#endif set_current_state(TASK_INTERRUPTIBLE);if (signal_pending(current) goto stop_waiting;if (!tty->driver.chars_in_buffer(tty)break;timeout = schedule_timeout(timeout); while (timeout);if (tty->driver.wait_u
16、ntil_sent) tty->driver.wait_until_sent(tty, timeout);stop_waiting: current->state = TASK_RUNNING; remove_wait_queue(&tty->write_wait, &wait); drivers/net/ppp_async.c:/* The basic PPP frame.*/#define PPP_HDRLEN 4 /* octets for standard ppp header */ #define PPP_FCSLEN 2 /* octets for
17、 FCS */#define PPP_MRU 1500 /* default MRU = max length of info field */#define OBUFSIZE 256/* Structure for storing local state. */struct asyncppp 異步 PPP 通道的驅(qū)動結(jié)構(gòu)struct tty_struct *tty;unsigned int flags;unsigned int state;unsigned int rbits;int mru;spinlock_t xmit_lock;spinlock_t recv_lock;unsigned
18、 long xmit_flags;u32 xaccm8; 終端字符轉(zhuǎn)換位圖u32 raccm;unsigned int bytes_sent;unsigned int bytes_rcvd;struct sk_buff *tpkt;int tpkt_pos;u16 tfcs;unsigned char *optr;unsigned char *olim;unsigned long last_xmit;struct sk_buff *rpkt; int lcp_fcs;struct ppp_channel chan; /* interface to generic ppp layer */ un
19、signed char obufOBUFSIZE;static struct tty_ldisc ppp_ldisc = 異步 PPP 規(guī)程操作表 magic: TTY_LDISC_MAGIC,name: "ppp",open: ppp_asynctty_open, close: ppp_asynctty_close, read: ppp_asynctty_read, write: ppp_asynctty_write, ioctl: ppp_asynctty_ioctl, poll: ppp_asynctty_poll, receive_room: ppp_asynctt
20、y_room, receive_buf: ppp_asynctty_receive, write_wakeup: ppp_asynctty_wakeup, ;struct ppp_channel_ops async_ops = PPP 通道驅(qū)動操作表 ppp_async_send, 發(fā)送 PPP 幀到終端設(shè)備 ppp_async_ioctl;int ppp_async_init(void) 模塊初始化 int err;err = tty_register_ldisc(N_PPP, &ppp_ldisc); 注冊 N_PPP 規(guī)程 if (err != 0)printk(KERN_ERR
21、 "PPP_async: error %d registering line disc.n", err);return err; /* Called when a tty is put into PPP line discipline.*/ static int ppp_asynctty_open(struct tty_struct *tty) 打開異步 PPP 規(guī)程 struct asyncppp *ap;int err;MOD_INC_USE_COUNT;err = -ENOMEM;ap = kmalloc(sizeof(*ap), GFP_KERNEL);if (ap
22、 = 0)goto out;/* initialize the asyncppp structure */ memset(ap, 0, sizeof(*ap);ap->tty = tty; 在驅(qū)動結(jié)構(gòu)上設(shè)置打開終端指針 ap->mru = PPP_MRU;spin_lock_init(&ap->xmit_lock); spin_lock_init(&ap->recv_lock);ap->xaccm0 = 0U;ap->xaccm3 = 0x60000000U; ap->raccm = 0U;ap->optr = ap->ob
23、uf;ap->olim = ap->obuf;ap->lcp_fcs = -1;ap->chan.private = ap; 在一般的 PPP 驅(qū)動結(jié)構(gòu)上設(shè)置異步驅(qū)動結(jié)構(gòu)指針 ap->chan.ops = &async_ops; 異步通道操作表 ap->chan.mtu = PPP_MRU;err = ppp_register_channel(&ap->chan); 建立通道驅(qū)動程序的傳輸通道結(jié)構(gòu) if (err)goto out_free;tty->disc_data = ap; 在打開終端結(jié)構(gòu)上設(shè)置驅(qū)動結(jié)構(gòu)指針return 0
24、;out_free: kfree(ap);out:MOD_DEC_USE_COUNT;return err;/* Called when the tty is put into another line discipline* or it hangs up.* We assume that while we are in this routine, the tty layer* won't call any of the other line discipline entries for the* same tty.*/static void ppp_asynctty_close(st
25、ruct tty_struct *tty)struct asyncppp *ap = tty->disc_data;if (ap = 0)return;tty->disc_data = 0; ppp_unregister_channel(&ap->chan);if (ap->rpkt != 0) kfree_skb(ap->rpkt);if (ap->tpkt != 0) kfree_skb(ap->tpkt);kfree(ap);MOD_DEC_USE_COUNT;/* Read does nothing - no data is ever
26、available this way.* Pppd reads and writes packets via /dev/ppp instead. */static ssize_tppp_asynctty_read(struct tty_struct *tty, struct file *file, unsigned char *buf, size_t count)return -EAGAIN;/* Write on the tty does nothing, the packets all come in* from the ppp generic stuff.*/static ssize_t
27、ppp_asynctty_write(struct tty_struct *tty, struct file *file, const unsigned char *buf, size_t count)return -EAGAIN;static intppp_asynctty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)struct asyncppp *ap = tty->disc_data;int err, val;err = -EFAULT; switch (
28、cmd) case PPPIOCGCHAN: 取通道號 err = -ENXIO;if (ap = 0) break; err = -EFAULT;if (put_user(ppp_channel_index(&ap->chan), (int *) arg) break;err = 0;break;case PPPIOCGUNIT: 取接口單元號 err = -ENXIO;if (ap = 0) break; err = -EFAULT;if (put_user(ppp_unit_number(&ap->chan), (int *) arg) break;err =
29、 0;break;case TCGETS:case TCGETA:err = n_tty_ioctl(tty, file, cmd, arg); break;case TCFLSH:/* flush our buffers and the serial port's buffer */ if (arg = TCIOFLUSH | arg = TCOFLUSH) ppp_async_flush_output(ap);err = n_tty_ioctl(tty, file, cmd, arg); break;case FIONREAD: val = 0;if (put_user(val,
30、(int *) arg) break;err = 0;break;case PPPIOCATTACH: 將傳輸通道連接到接口單元 case PPPIOCDETACH: 將傳輸通道與接口單元脫離 err = ppp_channel_ioctl(&ap->chan, cmd, arg); break;default:err = -ENOIOCTLCMD;return err;/* Flush output from our internal buffers.* Called for the TCFLSH ioctl.*/ static void ppp_async_flush_out
31、put(struct asyncppp *ap) int done = 0;spin_lock_bh(&ap->xmit_lock);ap->optr = ap->olim; if (ap->tpkt != NULL) kfree_skb(ap->tpkt);ap->tpkt = 0; clear_bit(XMIT_FULL, &ap->xmit_flags);done = 1; spin_unlock_bh(&ap->xmit_lock);if (done) ppp_output_wakeup(&ap->c
32、han);/* No kernel lock - fine */ static unsigned int ppp_asynctty_poll(struct tty_struct *tty, struct file *file, poll_table *wait) return 0;static int ppp_asynctty_room(struct tty_struct *tty) return 65535; drivers/net/ppp_generic.c: /* Private data structure for each channel.* This includes the da
33、ta structure used for multilink.*/struct channel 傳輸通道結(jié)構(gòu)struct ppp_file file; /* stuff for read/write/poll */struct ppp_channel *chan; /* public channel data structure */spinl ock_t dow nl; /* protects 'cha n', file.xq dequeue */struct ppp *ppp; /* ppp unit we're connected to */struct lis
34、t_head clist; /* link in list of channels per unit */ rwlock_t upl; /* protects 'ppp' and 'ulist' */#ifdef CONFIG_PPP_MULTILINKu8 avail; /* flag used in multilink stuff */u8 had_frag; /* >= 1 fragments have been sent */u32 lastseq; /* MP: last sequence # received */#endif /* CONFI
35、G_PPP_MULTILINK */;struct ppp_channel 傳輸通道的通用驅(qū)動結(jié)構(gòu)void *private; /* channel private data */struct ppp_channel_ops *ops; /* operations for this channel */ int mtu; /* max transmit packet size */int hdrlen; /* amount of headroom channel needs */void *ppp; /* opaque to channel */* the following are not
36、used at present */int speed; /* transfer rate (bytes/second) */int latency; /* overhead time in milliseconds */;struct ppp_channel_ops 驅(qū)動操作表/* Send a packet (or multilink fragment) on this channel.Returns 1 if it was accepted, 0 if not. */int (*start_xmit)(struct ppp_channel *, struct sk_buff *);/*
37、Handle an ioctl call that has come in via /dev/ppp. */int (*ioctl)(struct ppp_channel *, unsigned int, unsigned long);/* Data structure describing one ppp unit.* A ppp unit corresponds to a ppp network interface device* and represents a multilink bundle.* It can have 0 or more ppp channels connected
38、 to it.*/ struct ppp struct ppp_file file; /* stuff for read/write/poll */ struct list_head channels; /* list of attached channels */ int n_channels; /* how many channels are attached */ spinlock_t rlock; /* lock for receive side */ spinlock_t wlock; /* lock for transmit side */ int mru; /* max rece
39、ive unit */ unsigned int flags; /* control bits */ unsigned int xstate; /* transmit state bits */ unsigned int rstate; /* receive state bits */ int debug; /* debug flags */ struct slcompress *vj; /* state for VJ header compression */ enum NPmode npmodeNUM_NP; /* what to do with each net proto */ str
40、uct sk_buff *xmit_pending; /* a packet ready to go out */ struct compressor *xcomp; /* transmit packet compressor */ void *xc_state; /* its internal state */ struct compressor *rcomp; /* receive decompressor */ void *rc_state; /* its internal state */ unsigned long last_xmit; /* jiffies when last pk
41、t sent */ unsigned long last_recv; /* jiffies when last pkt rcvd */ struct net_device *dev; /* network interface device */ #ifdef CONFIG_PPP_MULTILINK int nxchan; /* next channel to send something on */ u32 nxseq; /* next sequence number to send */ int mrru; /* MP: max reconst. receive unit */ u32 n
42、extseq; /* MP: seq no of next packet */ u32 minseq; /* MP: min of most recent seqnos */ struct sk_buff_head mrq; /* MP: receive reconstruction queue */ #endif /* CONFIG_PPP_MULTILINK */ struct net_device_stats stats; /* statistics */;/* An instance of /dev/ppp can be associated with either a ppp * i
43、nterface unit or a ppp channel. In both cases, file->private_data * points to one of these.*/ struct ppp_file 監(jiān)控文件結(jié)構(gòu)參數(shù) enum INTERFACE=1, CHANNEL kind;struct sk_buff_head xq; /* pppd transmit queue */ struct sk_buff_head rq; /* receive queue for pppd */wait_queue_head_t rwait; /* for poll on readi
44、ng /dev/ppp */ atomic_t refcnt; /* # refs (incl /dev/ppp attached) */ int hdrlen; /* space to leave for headers */ struct list_head list; /* link in all_* list */ int index; /* interface unit / channel number */ ;/* all_ppp_lock protects the all_ppp_units.* It also ensures that finding a ppp unit in
45、 the all_ppp_units list* and updating its file.refcnt field is atomic. */static spinlock_t all_ppp_lock = SPIN_LOCK_UNLOCKED; static LIST_HEAD(all_ppp_units);/* all_channels_lock protects all_channels and last_channel_index, * and the atomicity of find a channel and updating its file.refcnt * field.
46、*/static spinlock_t all_channels_lock = SPIN_LOCK_UNLOCKED; static LIST_HEAD(all_channels);static int last_channel_index;/* Create a new, unattached ppp channel.*/ int ppp_register_channel(struct ppp_channel *chan) struct channel *pch;pch = kmalloc(sizeof(struct channel), GFP_ATOMIC); if (pch = 0) r
47、eturn -ENOMEM;memset(pch, 0, sizeof(struct channel); pch->ppp = NULL;pch->chan = chan; chan->ppp = pch; init_ppp_file(&pch->file, CHANNEL); pch->file.hdrlen = chan->hdrlen;#ifdef CONFIG_PPP_MULTILINK pch->lastseq = -1;#endif /* CONFIG_PPP_MULTILINK */spin_lock_init(&pch-
48、>downl); pch->upl = RW_LOCK_UNLOCKED; spin_lock_bh(&all_channels_lock); pch->file.index = +last_channel_index; list_add(&pch->file.list, &all_channels); spin_unlock_bh(&all_channels_lock); MOD_INC_USE_COUNT;return 0;/* Initialize a ppp_file structure.*/ static void init_p
49、pp_file(struct ppp_file *pf, int kind) pf->kind = kind; skb_queue_head_init(&pf->xq); skb_queue_head_init(&pf->rq); atomic_set(&pf->refcnt, 1); init_waitqueue_head(&pf->rwait);voidint ppp_channel_ioctl(struct ppp_channel *chan, unsigned int cmd, unsigned long arg)struc
50、t channel *pch = chan->ppp;int err = -ENOTTY;int unit;if (!capable(CAP_NET_ADMIN)return -EPERM;if (pch = 0)return -EINV AL;switch (cmd) case PPPIOCATTACH:if (get_user(unit, (int *) arg) break;err = ppp_connect_channel(pch, unit);break;case PPPIOCDETACH:err = ppp_disconnect_channel(pch); break;ret
51、urn err;/* Connect a PPP channel to a PPP interface unit.*/static intppp_connect_channel(struct channel *pch, int unit)struct ppp *ppp;int ret = -ENXIO;int hdrlen;spin_lock(&all_ppp_lock);ppp = ppp_find_unit(unit);if (ppp = 0)goto out;write_lock_bh(&pch->upl);ret = -EINV AL;if (pch->ppp != 0)goto outw;ppp_lock(ppp); spin_lock_bh(&pch->downl);if (pch->chan = 0) /* need to check this? */ goto outr;if (pch->file.hdrlen > ppp->file.hdrlen) ppp-&
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- T-ZTSS 0002-2024 同山燒酒評價規(guī)范
- T-ZJSEIA 007-2024 產(chǎn)品碳足跡評價技術(shù)規(guī)范光伏組件
- 二零二五年度健康產(chǎn)業(yè)商家入駐戰(zhàn)略合作協(xié)議
- 2025年度離婚財產(chǎn)分割與子女財產(chǎn)繼承協(xié)議
- 二零二五年度個人之間房產(chǎn)交易保密協(xié)議
- 二零二五年度按揭房屋借款協(xié)議書(公積金貸款)
- 2025年度籃球運動員轉(zhuǎn)會合同解除條件
- 二零二五年度超市租賃合同書:超市租賃及綠色環(huán)保產(chǎn)品合作協(xié)議
- 二零二五年度智能交通投資暗股協(xié)議
- 2025年度職業(yè)電競選手私教訓(xùn)練協(xié)議
- 血液透析并發(fā)糖尿病足護理查房課件
- 超市消防應(yīng)急疏散預(yù)案
- 當(dāng)代藝術(shù)博覽會的學(xué)術(shù)性建構(gòu)歷程與問題
- 寺廟線上運營策劃方案
- 《Unit2Myfavoriteseason》教學(xué)設(shè)計課件
- 七年級上冊生物期末測試卷(含答案)
- 路基分層-表格-
- 離婚協(xié)議書電子版下載
- 中醫(yī)藥膳學(xué)124張課件
- 汽車法規(guī)第一章
- Kappa測試數(shù)據(jù)分析報告
評論
0/150
提交評論