ImageVerifierCode 换一换
格式:DOC , 页数:17 ,大小:47KB ,
资源ID:9411546      下载积分:10 金币
验证码下载
登录下载
邮箱/手机:
图形码:
验证码: 获取验证码
温馨提示:
支付成功后,系统会自动生成账号(用户名为邮箱或者手机号,密码是验证码),方便下次登录下载和查询订单;
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

开通VIP
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.zixin.com.cn/docdown/9411546.html】到电脑端继续下载(重复下载【60天内】不扣币)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

开通VIP折扣优惠下载文档

            查看会员权益                  [ 下载后找不到文档?]

填表反馈(24小时):  下载求助     关注领币    退款申请

开具发票请登录PC端进行申请。


权利声明

1、咨信平台为文档C2C交易模式,即用户上传的文档直接被用户下载,收益归上传人(含作者)所有;本站仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。所展示的作品文档包括内容和图片全部来源于网络用户和作者上传投稿,我们不确定上传用户享有完全著作权,根据《信息网络传播权保护条例》,如果侵犯了您的版权、权益或隐私,请联系我们,核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
2、文档的总页数、文档格式和文档大小以系统显示为准(内容中显示的页数不一定正确),网站客服只以系统显示的页数、文件格式、文档大小作为仲裁依据,个别因单元格分列造成显示页码不一将协商解决,平台无法对文档的真实性、完整性、权威性、准确性、专业性及其观点立场做任何保证或承诺,下载前须认真查看,确认无误后再购买,务必慎重购买;若有违法违纪将进行移交司法处理,若涉侵权平台将进行基本处罚并下架。
3、本站所有内容均由用户上传,付费前请自行鉴别,如您付费,意味着您已接受本站规则且自行承担风险,本站不进行额外附加服务,虚拟产品一经售出概不退款(未进行购买下载可退充值款),文档一经付费(服务费)、不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
4、如你看到网页展示的文档有www.zixin.com.cn水印,是因预览和防盗链等技术需要对页面进行转换压缩成图而已,我们并不对上传的文档进行任何编辑或修改,文档下载后都不会有水印标识(原文档上传前个别存留的除外),下载后原文更清晰;试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓;PPT和DOC文档可被视为“模板”,允许上传人保留章节、目录结构的情况下删减部份的内容;PDF文档不管是原文档转换或图片扫描而得,本站不作要求视为允许,下载前可先查看【教您几个在下载文档中可以更好的避免被坑】。
5、本文档所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用;网站提供的党政主题相关内容(国旗、国徽、党徽--等)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
6、文档遇到问题,请及时联系平台进行协调解决,联系【微信客服】、【QQ客服】,若有其他问题请点击或扫码反馈【服务填表】;文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“【版权申诉】”,意见反馈和侵权处理邮箱:1219186828@qq.com;也可以拔打客服电话:4009-655-100;投诉/维权电话:18658249818。

注意事项

本文(PPP驱动程序的基本原理.doc)为本站上传会员【仙人****88】主动上传,咨信网仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知咨信网(发送邮件至1219186828@qq.com、拔打电话4009-655-100或【 微信客服】、【 QQ客服】),核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载【60天内】不扣币。 服务填表

PPP驱动程序的基本原理.doc

1、PPP驱动程序的基本原理 ===================== 1) ppp设备是指在点对点的物理链路之间使用PPP帧进行分组交换的内核网络接口设备, 由于Linux内核将串行设备作为终端设备来驱动, 于是引入PPP终端规程来实现终端设备与PPP设备的接口. 根据终端设备的物理传输特性的不同, PPP规程分为异步规程(N_PPP)和同步规程(N_SYNC_PPP)两种, 对于普通串口设备使用异步PPP规程. 2) 在PPP驱动程序中, 每一tty终端设备对应于一条PPP传输通道(chanell), 每一ppp网络设备对应于一个PPP接口单元(unit). 从终端设备上接收到的

2、数据流通过PPP传输通道解码后转换成PPP帧传递到PPP网络接口单元, PPP接口单元再将PPP帧转换为PPP设备的接收帧. 反之, 当PPP设备发射数据帧时, 发射帧通过PPP接口单元转换成PPP帧传递给PPP通道, PPP通道负责将PPP帧编码后写入终端设备. 在配置了多链路PPP时(CONFIG_PPP_MULTILINK), 多个PPP传输通道可连接到同一PPP接口单元. PPP接口单元将PPP帧分割成若干个片段传递给不同的PPP传输通道, 反之, PPP传输通道接收到的PPP帧片段被PPP接口单元重组成完整的PPP帧. 3) 在Linux-2.4中, 应用程序可通过字符设备/

3、dev/ppp监控内核PPP驱动程序. 用户可以用ioctl(PPPIOCATTACH)将文件绑定到PPP接口单元上, 来读写PPP接口单元的输出帧, 也可以用ioctl(PPPIOCATTCHAN)将文件绑定到PPP传输通道上, 来读写PPP传输通道的输入帧. 4) PPP传输通道用channel结构描述, 系统中所有打开的传输通道在all_channels链表中. PPP接口单元用ppp结构描述, 系统中所有建立的接口单元在all_ppp_units链表中. 当终端设备的物理链路连接成功后, 用户使用ioctl(TIOCSETD)将终端切换到PPP规程. PPP规程初始化时, 将建

4、立终端设备的传输通道和通道驱动结构. 对于异步PPP规程来说, 通道驱动结构为asyncppp, 它包含通道操作表async_ops. 传输通道和接口单元各自包含自已的设备文件(/dev/ppp)参数结构(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 -EINVAL; if (new_ldisc) { ldiscs[disc

5、] = *new_ldisc; ldiscs[disc].flags |= LDISC_FLAG_DEFINED; ldiscs[disc].num = disc; } else memset(&ldiscs[disc], 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_t

6、ty; int retval; tty = (struct tty_struct *)file->private_data; if (tty_paranoia_check(tty, inode->i_rdev, "tty_ioctl")) return -EINVAL; real_tty = tty; if (tty->driver.type == TTY_DRIVER_TYPE_PTY &&     tty->driver.subtype == PTY_TYPE_MASTER) real_tty = tty->link; ... switch (cmd)

7、{ ... case TIOCGETD: return put_user(tty->ldisc.num, (int *) arg); case TIOCSETD: return tiocsetd(tty, (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 = (

8、tty->ldisc.ioctl)(tty, file, cmd, arg); if (retval != -ENOIOCTLCMD) return retval; } return -EINVAL; } static int tiocsetd(struct 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 d

9、iscipline of a tty line. */ static int tty_set_ldisc(struct tty_struct *tty, int ldisc) { int retval = 0; struct tty_ldisc o_ldisc; char buf[64]; if ((ldisc < N_TTY) || (ldisc >= NR_LDISCS)) return -EINVAL; /* Eduardo Blanco */ /* Cyrus Durgin */ if (!(ldiscs[ldisc].flags & LDISC_FLAG_DE

10、FINED)) { 如果设定的规程不存在 char modname [20]; sprintf(modname, "tty-ldisc-%d", ldisc); request_module (modname); 尝试加载模块 } if (!(ldiscs[ldisc].flags & LDISC_FLAG_DEFINED)) return -EINVAL; if (tty->ldisc.num == ldisc) return 0; /* We are already in the desired discipline */ o_ldisc = tty->ldisc;

11、 tty_wait_until_sent(tty, 0); 等待终端输出设备的数据发送完 /* Shutdown the current discipline. */ if (tty->ldisc.close) (tty->ldisc.close)(tty); 关闭原来的规程 /* Now set up the new line discipline. */ tty->ldisc = ldiscs[ldisc]; tty->termios->c_line = ldisc; if (tty->ldisc.open) retval = (tty->ldisc.open)

12、tty); 打开新规程 if (retval < 0) { 如果打开失败, 恢复原来的规程 tty->ldisc = o_ldisc; tty->termios->c_line = tty->ldisc.num; if (tty->ldisc.open && (tty->ldisc.open(tty) < 0)) { tty->ldisc = ldiscs[N_TTY]; tty->termios->c_line = N_TTY; if (tty->ldisc.open) { int r = tty->ldisc.open(tty); if (r < 0) panic

13、"Couldn't open N_TTY ldisc for "       "%s --- error %d.",       tty_name(tty, buf), r); } } } if (tty->ldisc.num != o_ldisc.num && tty->driver.set_ldisc) tty->driver.set_ldisc(tty); return retval; } ; drivers/char/tty_ioctl.c: /* * Internal flag options for termios setting behavior

14、 */ #define TERMIOS_FLUSH 1 #define TERMIOS_WAIT 2 #define TERMIOS_TERMIO 4 void tty_wait_until_sent(struct tty_struct * tty, long timeout) { DECLARE_WAITQUEUE(wait, current); #ifdef TTY_DEBUG_WAIT_UNTIL_SENT char buf[64]; printk("%s wait until sent...\n", tty_name(tty, buf)); #endi

15、f if (!tty->driver.chars_in_buffer) return; add_wait_queue(&tty->write_wait, &wait); if (!timeout) timeout = MAX_SCHEDULE_TIMEOUT; do { #ifdef TTY_DEBUG_WAIT_UNTIL_SENT printk("waiting %s...(%d)\n", tty_name(tty, buf),        tty->driver.chars_in_buffer(tty)); #endif set_current_state(TAS

16、K_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_until_sent) tty->driver.wait_until_sent(tty, timeout); stop_waiting: current->state = TASK_RUNNING;

17、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 FCS */ #define PPP_MRU 1500 /* default MRU = max length of info field */ #define OBUFSIZE

18、256 /* Structure for storing local state. */ struct asyncppp { 异步PPP通道的驱动结构 struct tty_struct *tty; unsigned int flags; unsigned int state; unsigned int rbits; int mru; spinlock_t xmit_lock; spinlock_t recv_lock; unsigned long xmit_flags; u32 xaccm[8]; 终端字符转换位图 u32 raccm; unsigned int

19、 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 */ unsigned char obuf[OBUFSIZE]; };

20、 static struct tty_ldisc ppp_ldisc = { 异步PPP规程操作表 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_asynctty_room, receive_buf:

21、ppp_asynctty_receive, write_wakeup: ppp_asynctty_wakeup, }; struct ppp_channel_ops async_ops = { PPP通道驱动操作表 ppp_async_send, 发送PPP帧到终端设备 ppp_async_ioctl }; int ppp_async_init(void) 模块初始化 { int err; err = tty_register_ldisc(N_PPP, &ppp_ldisc); 注册N_PPP规程 if (err != 0) printk(KERN_ERR

22、 "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规程 { struct asyncppp *ap; int err; MOD_INC_USE_COUNT; err = -ENOMEM; ap = kmalloc(sizeo

23、f(*ap), GFP_KERNEL); if (ap == 0) goto out; /* initialize the asyncppp structure */ memset(ap, 0, sizeof(*ap)); ap->tty = tty; 在驱动结构上设置打开终端指针 ap->mru = PPP_MRU; spin_lock_init(&ap->xmit_lock); spin_lock_init(&ap->recv_lock); ap->xaccm[0] = ~0U; ap->xaccm[3] = 0x60000000U; ap->raccm = ~0

24、U; ap->optr = ap->obuf; ap->olim = ap->obuf; ap->lcp_fcs = -1; ap->chan.private = ap; 在一般的PPP驱动结构上设置异步驱动结构指针 ap->chan.ops = &async_ops; 异步通道操作表 ap->chan.mtu = PPP_MRU; err = ppp_register_channel(&ap->chan); 建立通道驱动程序的传输通道结构 if (err) goto out_free; tty->disc_data = ap; 在打开终端结构上设置驱动结构指针

25、 return 0; 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.

26、/ static void ppp_asynctty_close(struct 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;

27、 } /* * Read does nothing - no data is ever available this way. * Pppd reads and writes packets via /dev/ppp instead. */ static ssize_t ppp_asynctty_read(struct tty_struct *tty, struct file *file, unsigned char *buf, size_t count) { return -EAGAIN; } /* * Write on the tty does nothing, t

28、he packets all come in * from the ppp generic stuff. */ static ssize_t ppp_asynctty_write(struct tty_struct *tty, struct file *file,    const unsigned char *buf, size_t count) { return -EAGAIN; } static int ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file,    unsigned int cm

29、d, unsigned long arg) { struct asyncppp *ap = tty->disc_data; int err, val; err = -EFAULT; switch (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: 取接口单

30、元号 err = -ENXIO; if (ap == 0) break; err = -EFAULT; if (put_user(ppp_unit_number(&ap->chan), (int *) arg)) break; err = 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 == T

31、CIOFLUSH || arg == TCOFLUSH) ppp_async_flush_output(ap); err = n_tty_ioctl(tty, file, cmd, arg); break; case FIONREAD: val = 0; if (put_user(val, (int *) arg)) break; err = 0; break; case PPPIOCATTACH: 将传输通道连接到接口单元 case PPPIOCDETACH: 将传输通道与接口单元脱离 err = ppp_channel_ioctl(&ap->chan, cm

32、d, arg); break; default: err = -ENOIOCTLCMD; } return err; } /* * Flush output from our internal buffers. * Called for the TCFLSH ioctl. */ static void ppp_async_flush_output(struct asyncppp *ap) { int done = 0; spin_lock_bh(&ap->xmit_lock); ap->optr = ap->olim; if (ap->tpkt !

33、 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->chan); } /* No kernel lock - fine */ static unsigned int ppp_asynctty_poll(struct tty_struct *tty, struct file *file, poll_ta

34、ble *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 data structure used for multilink. */ struct channel { 传输通道结构 struct ppp_file file; /* s

35、tuff for read/write/poll */ struct ppp_channel *chan; /* public channel data structure */ spinlock_t downl; /* protects `chan', file.xq dequeue */ struct ppp *ppp; /* ppp unit we're connected to */ struct list_head clist; /* link in list of channels per unit */ rwlock_t upl; /* protects `ppp'

36、and `ulist' */ #ifdef CONFIG_PPP_MULTILINK u8 avail; /* flag used in multilink stuff */ u8 had_frag; /* >= 1 fragments have been sent */ u32 lastseq; /* MP: last sequence # received */ #endif /* CONFIG_PPP_MULTILINK */ }; struct ppp_channel { 传输通道的通用驱动结构 void *private; /* channel private dat

37、a */ 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 used at present */ int speed; /* transfer rate (bytes/second) */ int laten

38、cy; /* overhead time in milliseconds */ }; struct ppp_channel_ops { 驱动操作表 /* 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 *); /* Handle an ioctl call that has come in via /dev/ppp. */

39、 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 to it. */ struct ppp { struct

40、 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 receive unit */ unsigned

41、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 npmode[NUM_NP]; /* what to do with each net proto */ struct sk_buff *

42、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 pkt sent *

43、/ 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 ne

44、xtseq; /* 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 eit

45、her a ppp * interface unit or a ppp channel. In both cases, file->private_data * points to one of these. */ struct ppp_file { 监控文件结构参数 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_

46、t rwait; /* for poll on reading /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.

47、 It also ensures that finding a ppp unit in 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 atomici

48、ty of find a channel and updating its file.refcnt * field. */ 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) { stru

49、ct channel *pch; pch = kmalloc(sizeof(struct channel), GFP_ATOMIC); if (pch == 0) return -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

50、 pch->lastseq = -1; #endif /* CONFIG_PPP_MULTILINK */ spin_lock_init(&pch->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

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2025 宁波自信网络信息技术有限公司  版权所有

客服电话:4009-655-100  投诉/维权电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服