linux loopback驱动分析,loopback NIC 驱动剖析Series---(1)

声明:本文为原创

#####请转贴时保留以下内容######

作者:GTT

请提出宝贵意见Mail:mtloveft@hotmail.com

Linux Version:2.6.33

提示:本文是介绍关于linux 如何实现loopback NIC 驱动!

想对linux协议栈全面了解,网卡驱动是比较基础的。

而loopback设备又是虚拟设备,不涉及到中断和DMA等,所以

还是比较简单的。先从loopback驱动下手的另外一个原因是

它是系统第一个注册的网络驱动程序。

普通的网卡驱动都是以模块化注册到系统的,但loopback驱动

是和kernel一体的,直接在linux启动时被调用。

驱动被调用的过程

114767_100906214419.jpg

kernel启动时,会执行start_kernel方法,在start_kernel里会初始化很多组件和子系统。

也就是上图的other_init代替了这些初始化过程。start_kernel在执行到最后就会启动init kernel thread。

它会完成剩下的初始化程序。其中在do_initcalls里将会按照顺序执行初始化程序。

其中系统注册过以下方法

subsys_initcall(net_dev_init)      //net/core/dev.c

当执行net_dev_init时,就会调用loopback NIC的驱动程序。

static int __init net_dev_init(void)

{

... ...

if (register_pernet_device(&loopback_net_ops)) goto out;

... ...

}

当执行register_pernet_device时

int register_pernet_device(struct pernet_operations *ops)

{

int error;

mutex_lock(&net_mutex);

error = register_pernet_operations(&pernet_list, ops);

if (!error && (first_device == &pernet_list))

first_device = &ops->list;

mutex_unlock(&net_mutex);

return error;

}

继续跟进到register_pernet_operations

static int register_pernet_operations(struct list_head *list, struct pernet_operations *ops)

{

int error;

if (ops->id) {

again:

error = ida_get_new_above(&net_generic_ids, 1, ops->id);

if (error < 0) {

if (error == -EAGAIN) {

ida_pre_get(&net_generic_ids, GFP_KERNEL);

goto again;

}

return error;

}

}

error =__register_pernet_operations(list, ops);

if (error) {

rcu_barrier();

if (ops->id)

ida_remove(&net_generic_ids, *ops->id);

}

return error;

}

看看loopback 注册struct pernet_operations的定义

/* Registered in net/core/dev.c */

struct pernet_operations __net_initdata loopback_net_ops = {

.init = loopback_net_init,

};

loopback_net_ops没有注册id,所以ops->id为NULL。直接执行 __register_pernet_operations

static int __register_pernet_operations(struct list_head *list,struct pernet_operations *ops)

{

int err = 0;

err = ops_init(ops, &init_net);

if (err) ops_free(ops, &init_net);

return err;

}

继续跟进ops_init

static int ops_init(const struct pernet_operations *ops, struct net *net)

{

int err;

if (ops->id && ops->size) {

void *data = kzalloc(ops->size, GFP_KERNEL);

if (!data) return -ENOMEM;

err = net_assign_generic(net, *ops->id, data);

if (err) {

kfree(data);

return err;

}

}

if (ops->init)

return ops->init(net);

return 0;

}

ops->id根本就没被设置,而.init = loopback_net_init,所以 loopback_net_init将被调用,

而loopback_net_init就是loopback NIC的驱动程序,

内容如下

/* Setup and register the loopback device. */

static __net_init int loopback_net_init(struct net *net)

{

struct net_device *dev;

int err;

err = -ENOMEM;

dev = alloc_netdev(0, "lo", loopback_setup);//申请一个net_device实例。并进行初始化

if (!dev) goto out;

dev_net_set(dev, net);

err = register_netdev(dev);//注册 loopback NIC 设备

if (err) goto out_free_netdev;

net->loopback_dev = dev;

return 0;

out_free_netdev:

free_netdev(dev);

out:

if (net_eq(net, &init_net))

panic("loopback: Failed to register netdevice: %d\n", err);

return err;

}

alloc_netdev主要分配net_device结构,每个网络设备对象是标准的结构,但是不同的网络驱动程序可能都要维护不同的私有信息,所以在分配net_device结构的同时可以多分配出sizeof_priv大小的结构来。比如应用程序可能会经常查询NIC NIC adress,虽然驱动程序可以通过访问网卡上的存储空间来获

取网卡地址,但是驱动程序可不希望每次都通过慢速的IO 访问来获取这些信息,通常驱动程序会为这些信息维护内存中的数据

结构中,这些信息都可以放在私有信息中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值