书中 很多 地方 新的内核 除了壳子 都面目全非了, 研究内核就是痛苦终身的事情 。如果你订阅了mail list 那你肯定坚持不了一个月就 unsubscribe了 。
上层 recv send 二十年如一日 的调用 kernel 里面早就翻天覆地了 从 2.6.38的内核看来吧
以前看书从来不写blog , 现在发现写 还是有好处的 , 比如一年前如果我写了cglib jvm 的阅读心得 ,我现在就不会忘记的差不多了 , 现在看别人讨论spring 源码都觉得 陌生的可怕 。。。唉
因为是 review 所以只是一些 个人的 记录 。 不是 全书的读书笔记 。
================================================
Notification chains
通知链: 当一个给定事件发生了 要执行的一系列简单的函数 ,每一个函数让另一个子系统知道有情况发生了, 所以有一个被通知的 和通知者(Observer 模式...)
函数的执行完全靠 被通知方的意愿执行 , 通知方不能干涉 它只能定义一个通知链,
任何内核子系统 都可以把在这个通知链表上 注册自己需要的回调 函数 。
通知链的好处就不多说了 ,自己去看Observer 模式 .....
每一个内核的子系统维护组织 都不需要天天盯着邮件列表看看有没有新的子系统加入 。
他们只需要 :
这个子系统有什么有趣的事情 他想知道的 。
他想知道别的子系统对这个事件感兴趣不。 所以现在事情大家都可以共享 但都可以解放不去管别人了
Notifier.h 里面定了 它 的结构
通知链分 4种 类型
* 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.
举例 :
写道
struct notifier_block {
int (*notifier_call)(struct notifier_block *, unsigned long, void *);
struct notifier_block *next;
int priority;
};
通知产生通过 notifier_call_chain 这个函数 也是在 Notifier.c 中
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;
/*在一个安全的情况下获得rcu 保护的指针 */
nb = rcu_dereference_raw(*nl);
while (nb && nr_to_call) {
next_nb = rcu_dereference_raw(nb->next);
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;
}
System Initializaion
首先 Main.c 中 的
写道
asmlinkage void __init start_kernel(void)
static noinline void __init_refok rest_init(void) __releases(kernel_lock)
kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
static void __init do_basic_setup(void)
static void __init do_initcalls(void)
{
initcall_t *fn;
for (fn = __early_initcall_end; fn < __initcall_end; fn++)
do_one_initcall(*fn);
/* Make sure there is no pending stuff from the initcall sequence */
flush_scheduled_work();
}
init_post();
注册和初始化任务 一部分是由内核完成的 ,另一部分是设备驱动里面做的 。
主要分为
硬件初始化: 设备驱动做的, 比如初始化IRQ line 和I/O 端口映射 内存映射 DMA(dam9000)之类 的(request_region release_region等一些请求资源API) 可以去看设备驱动的书
软件初始化: 根据编译内核的config 选项 还有一些别的配置文件决定 协议啊 功能啊什么的
内核与驱动之间的交互 主要是
轮询 中断 (类比SNMP 中的 Get/Trap)
算了 驱动的东西不写了, 看datasheet 和CS8900的驱动吧 写的话下去远了
不想看懂驱动源码的 记得 文件系统永远是你的天堂 驱动对外的接口
/sys/module/网卡驱动名/parameters
/sys/class/net/eth0
static int __init net_dev_init(void)
{
int i, rc = -ENOMEM;
./*proc 文件系统和 kobject 设备模型的初始化 */
if (dev_proc_init())
goto out;
if (netdev_kobject_init())
goto out;
INIT_LIST_HEAD(&ptype_all);
/*初始化支持的协议数组*/
for (i = 0; i < PTYPE_HASH_SIZE; i++)
INIT_LIST_HEAD(&ptype_base[i]);
/*注册网络子系统 ,当网络命名空间被创建时就会去回调 传入结构的init方法 etc*/
if (register_pernet_subsys(&netdev_net_ops))
goto out;
/*初始化所有cpu上面的包接收队列*/
for_each_possible_cpu(i) {
struct softnet_data *sd = &per_cpu(softnet_data, i);
/*2.6.38里面这个结构变的十分强大*/
memset(sd, 0, sizeof(*sd));
skb_queue_head_init(&sd->input_pkt_queue);
skb_queue_head_init(&sd->process_queue);
sd->completion_queue = NULL;
INIT_LIST_HEAD(&sd->poll_list);
sd->output_queue = NULL;
sd->output_queue_tailp = &sd->output_queue;
/*对于支持RPS的配置 ,将会被多个CPU来使用
对于.38内核RPS(XPS)的实现以后说 <sys fs 依然给了你配置的能力>
/sys/class/net/<device>/queues/tx-<n>/xps_cpus
/sys/class/net/<device>/queues/rx-<n>/rps_cpus*/
#ifdef CONFIG_RPS
sd->csd.func = rps_trigger_softirq;
sd->csd.info = sd;
sd->csd.flags = 0;
sd->cpu = i;
#endif
sd->backlog.poll = process_backlog;
sd->backlog.weight = weight_p;
sd->backlog.gro_list = NULL;
sd->backlog.gro_count = 0;
}
dev_boot_phase = 0;
/*注册一个 loopback <包括proc fs> 和default 设备*/
if (register_pernet_device(&loopback_net_ops))
goto out;
if (register_pernet_device(&default_device_ops))
goto out;
/*使能TX RX软中断*/
open_softirq(NET_TX_SOFTIRQ, net_tx_action);
open_softirq(NET_RX_SOFTIRQ, net_rx_action);
hotcpu_notifier(dev_cpu_callback, 0); /*初始化DST 子系统 通知链 */
dst_init();
/*用于 IP multicast的每个网络设备值 proc/net/dev_mcast*/
dev_mcast_init();
rc = 0;
out:
return rc;
}
static int __init net_dev_init(void) 用了gcc 的__section(.init.text) 在boot 的时候还只有一个线程什么同步都不需要
下面是精简的主要代码 (from 2.6.38)
有时候 内核也需要执行 PATH=/sbin:/usr/sbin:/bin:/usr/bin 下面的命令...
也有类似 execpl 的 函数 call_usermodehelper 当然也有wrapper 过的
request_module kobject_hotplug
(/sbin/modprobe and /sbin/hotplug)
分享到:
相关推荐
Linux内核2.6.38是Linux操作系统的核心部分,负责管理系统的硬件资源,调度进程,实现硬件抽象层,提供系统调用接口等关键功能。对于开发者而言,它是一个极其重要的基础,尤其对于那些需要定制化操作系统的专业人员...
Mini6410 Kernel-patch Linux-2.6.38
在Ubuntu 10.10环境下编译Linux内核2.6.38涉及一系列步骤,需要对操作系统、内核版本、编译工具和配置选项有深入理解。以下是详细的编译流程和注意事项: 首先,确保你的环境是Pentium 4架构的Ubuntu 10.10(内核...
ubuntu编译ARM内核linux-2.6.38所需的工具
在本文中,我们将深入探讨如何将CS8900A网络控制器从Linux 2.6.35内核移植到2.6.38内核的过程。CS8900A是一款广泛使用的以太网控制器,尤其适用于嵌入式系统。在基于FS2410的开发板上进行移植工作,我们需要理解内核...
最新的Linux2.6操作系统,Linux-2.6.38.4,加入了新的功能,下载体验吧
### 基于 Linux-2.6.38 内核的嵌入式驱动常用函数调用解析 #### 一、`copy_from_user()` **函数定义:** ```c static inline unsigned long copy_from_user(void __user *to, const void *from, unsigned long n)...
erver01> tar xvf linux-2.6.38.tar.bz2 server01> cd linux-2.6.38 server01> make mrproper server01> cp ../linux-2.6.18-xxx/.config .config #此处为了防止遗漏某些模块的添加,将原来的内核配置文件拷贝过来...
* #include <linux/miscdevice.h> * #include <linux/delay.h> * #include <asm/irq.h> * #include <mach/regs-gpio.h> * #include <mach/hardware.h> * #include <linux/kernel.h> * #include <linux/module.h> 本...
- **驱动程序源代码位置**:`Linux-2.6.38/fs/yaffs2` - **设备名**:无特定设备名 - **备注**:YAFFS2(Yet Another Flash File System)是一种专为闪存设计的文件系统,主要用于嵌入式系统中。它能够有效管理非易...
Linux 2.6.38内核是Linux操作系统的一个版本,它包含了多种驱动开发所需的函数和API。在开发基于Linux内核的设备驱动程序时,熟练使用这些内核提供的函数是至关重要的。下面将详细介绍文档中提及的一些内核驱动常用...
对2.6.38内核中wifi驱动中出现的SD卡热插拔,wifi驱动进行了一个初步的分析.有什么不对的地方,还希望高手指点!
在"linux-2.6.38-tiny6410"这个项目中,我们将关注的是Linux内核的一个特定版本,针对tiny6410开发板进行了优化和适配。 tiny6410开发板是基于三星S5PV210处理器的嵌入式平台,常用于教学、实验和产品原型设计。S5...
在本文中,我们将深入探讨如何在Tiny6410开发板上移植Linux内核2.6.38。Tiny6410是一款基于ARM Cortex-A8处理器的嵌入式开发板,具有2GB NAND Flash存储和256MB RAM。移植内核到这样的硬件平台涉及多个步骤,包括...
TQ2440的u_boot不能引导2.6.36以上的内核,用TQ2440的u_boot修改的,可以引导linux2.6.36以上的内核,同时兼容linux2.6.37以下老版本内核 用法: #make distclean #make Wamy2440_config #make 下载u-boot.bin后...
原创的友善之臂的mini6410 linux-2.6.38内核的uart1 串口驱动,使用platform_device方式,压缩包里面有驱动源代码、编译好了的ko文件、使用说明文档、用户例程的源代码和可执行程序,但是并没有给出直接编译驱动和...
在Linux 2.6.38版本中,驱动程序设计涉及到多个关键的结构体,包括`struct file_operations`, `struct inode`, 和 `struct file`。下面是对这些结构体及其关系的详细解释。 1. **struct file_operations** 这个...
- 这里假设你已经拥有名为`linux-2.6.38-20110325.tar.gz`的内核压缩包,并将其解压到`/srv/linux`目录下。 **步骤2:配置内核** - 进入解压后的内核源码目录: ```bash cd /srv/linux/linux-2.6.38 ``` - 在...
- 运行`make menuconfig`,在`Device Drivers -> Network devices support`下选择`CS8900 support`。 - 在`Kernel Features`下启用ARMEABI支持,并允许旧的ABI二进制文件运行。 4. **编译内核** - 执行`make ...
Linux简单的字符驱动例子,改自宋宝华的书,移植2.6.38成功 使用make modules编译,生成的ko放到tiny6410开发板,可以insmod和rmmod 此例是移植到了2.6.38,书上原有的例子不适合2.6.36以上。因为ioctl被改名了