Linux网卡驱动程序详解

来源:Linux认证    发布时间:2012-11-10    Linux认证视频    评论


*/
top = 0;
mp = &
while (totlen > 0) {
if (top) {/*如果不是链的第一个*/
MGET(m, M_DONTWAIT, MT_DATA);/*MGET和MGETHDR差不多,只不过少一个m_flags = M_PKTHDR*/
if (m == 0) {
m_freem(top);
return (0);
}
m->m_len = MLEN;/*非链首mbuf的长度为MLEN,这个if(top)就代表不是链首mbuf*/
}/*如果跳过了上面哪个if,那肯定是链的第一个mbuf,并且m已经在循环外就分配好了.*/
len = min(totlen, epkt - cp);/*epkt在计算后指向数据的尾部,cp指向首部*/
if (len >= MINCLSIZE) {/*#define MINCLSIZE (MHLEN + 1) 这意味着只要数据大于MHLEN,就要分配一个簇*/
MCLGET(m, M_DONTWAIT);/*看到宏展开后好恐怖,有空我再说一说*/
if (m->m_flags & M_EXT)/*在mbuf中注明是扩展型mbuf(即带有簇)*/
m->m_len = len = min(len, MCLBYTES);/*如果大于2048则先装2048吧,装的语句在下面*/
else
len = m->m_len;
} else {
/*
* 如果到这了,就意味着要么这个包小于MINCLSIZE,要么是后面一点尾巴且小于MINCLSIZE.
*/
if (len < m->m_len) {
if (top == 0 && len + max_linkhdr <= m->m_len)
m->m_data += max_linkhdr;
m->m_len = len;
} else
len = m->m_len;
}
bcopy(cp, mtod(m, caddr_t), (unsigned)len);/*第一次数据移动,费时的操作*/
cp += len;
*mp = m;
mp = &m->m_next;/*把mbuf链接起来*/
totlen -= len;
if (cp == epkt)
cp = buf;
}
return (top);/*返回装填数据的mbuf链首*/
}/*总结:在该函数中,所做的事情非常费时,主要是做内存的申请,大批数据的拷贝,如果象NFS传送数据,会出现大量的簇的申请和大量簇的数据的拷贝,一次循环需要拷贝2048个32位的双字.如果是发给本机的,那还行,如果是本机做为桥转发及防活墙,即数据不上传到IP层处理,那么可以直接改写mbuf的分配方案,根据不同的网络流量可初始化一定数量的大容量的缓冲链(可以以一个以太网的整页数来分配,如是100M以太网是1514字节,可分配2048字节,是有一点浪费,但性能可提高,sc->el_pktbuf可变为一队列,用来和其他网卡的接收队列进行数据交换.这意味着光数据进入就少拷贝一次,性能将大大提高,目前我正在研究中.)*/
/*
* 处理一个IOCTL请求.
*/
static int
el_ioctl(ifp, command, data)
register struct ifnet *ifp;
u_long command; /*IOCTL的命令*/
caddr_t data;
{
int s, error = 0;
s = splimp(); /*先关闭网络中断*/
switch (command) {
case SIOCSIFADDR:
case SIOCGIFADDR:
case SIOCSIFMTU:
error = ether_ioctl(ifp, command, data);
break;
case SIOCSIFFLAGS:
/*
* 如果接口已经DOWN但FLAG还有RUNNING, 那么先停止它
*/
if (((ifp->if_flags & IFF_UP) == 0) &&
(ifp->if_flags & IFF_RUNNING)) {
el_stop(ifp->if_softc);
ifp->if_flags &= ~IFF_RUNNING;/*在FALG中去掉IFF_RUNNING标志*/
} else {
/*
* 如果接口已经DOWN,FLAG没有RUNNING, 只要调用el_init例程
*/
if ((ifp->if_flags & IFF_UP) &&
((ifp->if_flags & IFF_RUNNING) == 0))
el_init(ifp->if_softc);
}
break;
default:
error = EINVAL;
}
(void) splx(s);
return (error);
}
/* 一般是数据在规定的时间内没有发出后被调用的程序,目前该驱动程序不支持 */
static void
el_watchdog(struct ifnet *ifp)
{
log(LOG_ERR,"el%d: device timeoutn", ifp->if_unit);
ifp->if_oerrors++;
el_reset(ifp->if_softc);
}

上一页789下一页

视频学习

我考网版权与免责声明

① 凡本网注明稿件来源为"原创"的所有文字、图片和音视频稿件,版权均属本网所有。任何媒体、网站或个人转载、链接转贴或以其他方式复制发表时必须注明"稿件来源:我考网",违者本网将依法追究责任;

② 本网部分稿件来源于网络,任何单位或个人认为我考网发布的内容可能涉嫌侵犯其合法权益,应该及时向我考网书面反馈,并提供身份证明、权属证明及详细侵权情况证明,我考网在收到上述法律文件后,将会尽快移除被控侵权内容。

最近更新

社区交流

考试问答