读书笔记—— Under Standing Linux Network Internals(3)
来源:互联网 发布:福彩3dapp软件 编辑:程序博客网 时间:2024/05/08 12:34
读书笔记—— Under Standing Linux Network Internals(3)
介绍了本书的第3~4章
Table of Contents
简要介绍用户空间程序与内核交互的机理。
3.1 概述 3.1.1 内核还提供了三种特殊的接口,用于将内核的内部信息暴露给用户空间。这三种之中,有两种是虚拟文件系统。- procfs(/proc 文件系统)
这是一个虚拟文件系统,通常挂在在/proc上,内核通过它,将内部信息以文件的形 式输出到用户空间。/proc上面的文件并不真的存在在磁盘上,但是用户可以通过 cat,more来读取文件,通过重定向(>)来写入文件,甚至可以对他们进行权限的设置。 用户不能在该文件夹(挂载点)中新建文件或文件夹。 - sysctl (/proc/sys directory)
该接口可以允许用户读取和修改内核中变量的值。这种变量的修改方式有两种:一是 通过系统调用sysctl,二是使用/proc文件系统。 - sysfs (/sys filesystem)
2.6内核新增,输出更加clean。
- ioctl
很复杂的系统调用,后文涉及到时候在详述。 - Netlink socket
较新的一种网络程序与内核交互的接口。
procfs与sysctl都可以输出内核内部的信息,但是procfs输出的大多为只读数据,而 sysctl的输出则大多为可写的(对root来讲)。
3.2.1 procfs网络模块在系统初始化或者模块加载的时候,会在/proc文件系统中注册一个或者多 个文件。当用户读取文件时,会间接地诱发内核运行一些内核工具,从而返回一些输 出给用户。网络模块注册的信息位于/proc/net。
/proc中的目录可以通过函数proc_mkdir来创建。而/proc/net中的文件则可以通过 proc_net_fops_create和proc_net_remove来注册和卸载。上述两个函数定义在 include/linux/proc_fs中。在上述两个函数的实现中,他们分别调用了更底层的函 数crete_proc_entry和remove_proc_entry。对proc_ner_fops_create来讲, 该函数除了通过proc_net_create来创建文件以外,还负责文件操作的初始化。如 下面这个例子所示:
/*net/ipv4/arp.c*/static const struct file_operations arp_seq_fops = {
.owner = THIS_MODULE,
.open = arp_seq_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release_net,
};
static int __net_init arp_net_init(struct net *net)
{
if (!proc_net_fops_create(net, "arp", S_IRUGO, &arp_seq_fops))
return -ENOMEM;
return 0;
}
static void __net_exit arp_net_exit(struct net *net)
{
proc_net_remove(net, "arp");
}
static struct pernet_operations arp_net_ops = {
.init = arp_net_init,
.exit = arp_net_exit,
};
static int __init arp_proc_init(void)
{
return register_pernet_subsys(&arp_net_ops);
} 4 Notification Chains
Linux内核中各个子系统的独立性很强,这样,一个子系统不能直接获取另外一个子系 统的事件。为此,Linux内核采用了Notification Chains.
本章重点如下:
- Notification Chains如何声明的,网络代码中使用了哪些notification Chain
- 内核的子系统如何向Notification Chain 注册
- 一个Chain上的内核子系统如何产生一个通知
注意,这里的notification指的是内核的各个子系统中,而非用户空间和内核之间。用 户空间和内核之间的通讯方法参见前面一章。
4.1 概述所谓的notification chain就是一系列的用于在特定事件发生时候执行的函数,这些 函数可以让其他的子系统获知此时发生的事件。每一个Chain都分为主动方 (notifier,发布者)和被动方(notified,订阅者):
- notified
当某一事件发生时候需要被告知的子系统。
- notifier
发生事件的子系统,该子系统讲会调用回调函数。
Notifier有四种类型,如下:
- Atomic notifier chains
- Chain callbacks run in interrupt/atomic context. Callouts are not allowed to block.
- Blocking notifier chains
- Chain callbacks run in process context. Callouts are allowed to block.
- Raw notifier chains
- There are no restrictions on callbacks, registration, or unregistration. All locking and protection must be provided by the caller.
- SRCU notifier chains
- A variant of blocking notifier chains, with the same restrictions.
Notification Chain的元素为notifierbloc类型,其定义为:
struct notifier_block {int (*notifier_call)(struct notifier_block *, unsigned long, void *);
struct notifier_block *next;
int priority;
};
struct atomic_notifier_head {
spinlock_t lock;
struct notifier_block *head;
};
struct blocking_notifier_head {
struct rw_semaphore rwsem;
struct notifier_block *head;
};
struct raw_notifier_head {
struct notifier_block *head;
};
struct srcu_notifier_head {
struct mutex mutex;
struct srcu_struct srcu;
struct notifier_block *head;
};
其中,notifiercall待执行的函数, next为链表中指向下一个元素的指针。priority 是函数运行时候的优先级,优先级高的函数时会优先执行。但实际上,几乎所有的 notifier的priority都被设置成了0,因此他们将会按照插入列表的先后顺序来执行。
4.3 notification 的注册注册notification的通用函数为notifierchainregister。除此之外,内核含提供了 基于它的若干wrapper。例如前面提到的几种notifier都有自己的注册函数:
atomic_notifier_chain_register ()blocking_notifier_chain_cond_register ()
blocking_notifier_chain_register ()
notifier_chain_cond_register ()
notifier_chain_register ()
raw_notifier_chain_register ()
srcu_notifier_chain_register () 4.4 Chain上的通知事件
notifiercallchain( )用于对每一个接收者发送事件消息。该函数遍历Chain上的注 册的所有回调函数,并按优先级依次调用。代码如下:
/*** notifier_call_chain - Informs the registered notifiers about an event.
* @nl: Pointer to head of the blocking notifier chain
* @val: Value passed unmodified to notifier function
* @v: Pointer passed unmodified to notifier function
* @nr_to_call: Number of notifier functions to be called. Don't care
* value of this parameter is -1.
* @nr_calls: Records the number of notifications sent. Don't care
* value of this field is NULL.
* @returns: notifier_call_chain returns the value returned by the
* last notifier function called.
*/
static int __kprobes notifier_call_chain(struct notifier_block **nl,
unsigned long val, void *v,
int nr_to_call, int *nr_calls)
{
int ret = NOTIFY_DONE;
struct notifier_block *nb, *next_nb;
nb = rcu_dereference(*nl);
while (nb && nr_to_call) {
next_nb = rcu_dereference(nb->next);
#ifdef CONFIG_DEBUG_NOTIFIERS
if (unlikely(!func_ptr_is_kernel_text(nb->notifier_call))) {
WARN(1, "Invalid notifier called!");
nb = next_nb;
continue;
}
#endif
ret = nb->notifier_call(nb, val, v);
if (nr_calls)
(*nr_calls)++;
if ((ret & NOTIFY_STOP_MASK) == NOTIFY_STOP_MASK)
break;
nb = next_nb;
nr_to_call--;
}
return ret;
}
内核针对前面提到的notifier的分类而提供了若干他的wrapper,详情见kernel/notifier.c
4.5 Notification Chains for the Networking Subsystems内核2.6.32版本中未找到这一节中提到的数据结构,如netdevchain等等。
可能是因为我刚用gtags取代了cscope,用的不太熟练,当然也可能是新的内核中对网 络部分做了较大的调整。
Any way,略过本章剩下的几个小节。
Author:
Date: 2010-05-31 16:26:17
HTML generated by org-mode 6.33x in emacs 23
Author:yangyingchao, 2010-05-31
- 读书笔记—— Under Standing Linux Network Internals(3)
- Understanding Linux Network Internals
- Understanding Linux Network Internals
- Windows network services internals 3
- 《Understanding Linux Network Internals》 第一章序言
- Understanding Linux Network Internals-1. OverAll
- Understanding Linux Network Internals-3. Copyright
- Understanding Linux Network Internals-4. Preface
- Understanding Linux Network Internals-4.2 Background Information
- 正在读英文版《Understanding Linux Network Internals》
- Understanding Linux Network Internals-2. Table of Contents
- Understanding Linux Network Internals-4.1 The Audience for This Book
- Understanding Linux Network Internals-4.3 Organization of the Material
- Windows network services internals
- Gamebryo—Cloning Internals
- windows internals - 读书笔记一
- 《Microsoft Sql server 2008 Internals》读书笔记--第六章Indexes:Internals and Management(3)
- 《Microsoft Sql server 2008 Internals》读书笔记--第十一章DBCC Internals(3)
- 互联网公司---关注点
- Scala初学者学习资料:main(String[])
- device_register()和platform_device_register()的区别
- shell 测试
- Android的DDMS中的Threads的各个字段的含义
- 读书笔记—— Under Standing Linux Network Internals(3)
- 使用codeblock 编译工程发出警告:"Debug" uses an invalid compiler. Skipping...
- JDBC连接数据库和释放连接
- php数组处理函数
- delphi DLL 常见问题
- 如何判断两个链表相交及找到第一个相交点
- cocos2d-x问题汇总
- DWR异步产生的问题
- 利用easybcd在win7下安装Fedora-19-x86_64-DVD双系统