主要数据结构
struct tasklet_head
{
struct tasklet_struct *list;
};
struct tasklet_struct
{
struct tasklet_struct *next;
unsigned long state;
atomic_t count;
void (*func)(unsigned long);
unsigned long data;
};
tasklet 是在 softirq 的基础上实现的,基于HI_SOFTIRQ(软中断0) 和
TASKLET_SOFTIRQ(软中断5)。
这两个tasklet只是在优先级上有区别。
在初始化的时候,对应的HI_SOFTIRQ 和 TASKLET_SOFTIRQ 的 action分别被设置为
tasklet_hi_action() 和 tasklet_action()。
tasklet 和 高优先级tasklet 分别存放在 PER_CPU 变量 tasklet_vec 和
tasklet_hi_vec 中,类型为 struct tasklet_head.
对于每一个CPU,维护一个tasklet的链表,如下图所示:
&
主要数据结构:
struct softirq_action
{
void (*action)(struct softirq_action *);
void *data;
};
软中断使用 struct softirq_action 来表示。
所有的软中断在数组 softirq_vec 中, 该数组有32项,也就是说最多支持32个软中断。
数组的下标即为软中断的优先级,0最高,31最低。
当前linux只使用了6个:
0 - HI_SOFTIRQ
1 - TIMER_SOFTIRQ
2 - NET_TX_SOFTIRQ
3 - NET_RX_SOFTIRQ
4 - SCSI_SOFTIRQ
5 - TASKLET_SOFTIRQ
其中0 和 5 用于tasklet
如图所示:
(2009-08-20 13:37)
主要数据结构
struct input_dev {
void *private;
const char *name;
const char *phys;
const char *uniq;
struct input_id id;
unsigned long evbit[NBITS(EV_MAX)];
unsigned long keybit[NBITS(KEY_MAX)];
unsigned long relbit[NBITS(REL_MAX)];
unsigned long absbit[NBITS(ABS_MAX)];
unsigned long mscbit[NBITS(MSC_MAX)];
unsigned long ledbit[NBITS(LED_MAX)];
unsigned long sndbit[NBITS(SND_MAX)];
unsigned long ffbit[NBITS(FF_MAX)];
unsigned long swbit[NBITS(SW_MAX)];
unsigned int keycodemax;
unsigned int keycodesize;
void *keycode;
int (*setkeycode)(struct input_dev *dev, int scancode, int
keycode);
int (*getkeycode)(struct input_dev *dev, int scancode, int
*keycode);
struct ff_device *ff;
unsigned int repeat_key;
struct time
另外,对于Linux,可以将多个文件系统 mount 到同一个目录上,这样的话, 新 mount
的文件系统会覆盖原来mount的文件系统。
比如我们再把一个 '/dve/hdb2' 的设备 mount 到 '/home/xpl' 目录下,
这样,如果我们访问 '/home/xpl' 的时候,就会访问到 '/dev/hdb2'
当新mount的文件系统被 unmount 之后,原来被覆盖的文件系统就会再次显露出来了。
这个过程的之所以是这样的,是因为在路径查找的时候,如果发现要查找的目录上mount了
文件系统(其dentry的d_mounted 不为0),会切换文件系统。
比如我们上面的例子,当路径查找 '/home/xpl' 的时候,当查找到根文件系统的目录 'xpl'
的dentry时,发现有一个文件系统已经mount到这个目录上,就会切换文件系统,进而找到 '/dev/hdb1' 的根目录的
dentry
这样,路径查找'/home/xpl' 返回的时候,返回的是 '/dve/hdb1' 根目录的 dentry
这样,在我们 mount 第二个文件系统 '/dev/hdb2' 的时候,其mountpoint 就是 '/dev/hdb1'
的根目录的 dentry。
这个过程如下图所示:
找到了要 mount 的目录,下面就开始实际的mount过程
mount的过程就是把设备的文件系统加入到 vfs 框架中
1. 首先,要mount一个新的设备,需要创建一个新的 super block。
这通过要mount的文件系统的 file_system_type, 调用其 get_sb 方法来创建一个新的 super
block
2. 对于任何一个 mount 的文件系统,都要有一个 vfsmount, 创建这个vfsmount, 并设置好其属性(就是
vfsmount 中的各个成员)
3. 将创建好的 vfsmount 加入到系统中。
整个过程如下所示:
mount 文件系统
主要数据结构:
struct namespace {
atomic_t count;
struct vfsmount * root;
struct list_head list;
struct rw_semaphore sem;
};
struct vfsmount
{
struct list_head mnt_hash;
struct vfsmount *mnt_parent;
struct dentry *mnt_mountpoint;
struct dentry *mnt_root;
struct super_block *mnt_sb;
struct list_head mnt_mounts;
struct list_head mnt_child;
atomic_t mnt_count;
int mnt_flags;
int mnt_expiry_mark;
char *mnt_devname;
struct list_head mnt_list;
struct list_head mnt_fslink;
(2008-10-27 18:12)
前面我们介绍了高速缓存的基本概念,下面我们将介绍它和memory中的页框是如何关联到一起的.
slab alloctor是通过buddy alloctor来申请页框的.
这在 kmem_cache_alloc()
中,通过调用kmem_getpages();而kmem_getpages()又会相应的调用alloc_pages().
当一个页框被分配给slab之后,page->flag 中的
PG_slab会被置位.同时,该page描述符的lru会分别指向相应的cache和slab, 如下图所示:
&n
(2008-10-27 18:06)
主要数据结构:
struct kmem_cache_s {
struct array_cache *array[NR_CPUS];
unsigned int batchcount;
unsigned int limit;
struct kmem_list3 lists;
unsigned int objsize;
unsigned int flags;
unsigned int num;
unsigned int free_limit;
spinlock_t spinlock;
unsigned int gfporder;
unsigned int gfpflags;
size_t colour;
unsigned int colour_off;
unsigned int colour_next;
kmem_cache_t *slabp_cache;
unsigned int slab_size;
unsigned int dflags;
void (*ctor)(voi
Char Device Driver
相关数据结构:
struct cdev {
struct kobject kobj;
struct module *owner;
const struct file_operations *ops;
struct list_head list;
dev_t dev;
unsigned int count;
};
struct kobj_map {
struct probe {
struct probe *next;
dev_t dev;
unsigned long range;
struct module *owner;
kobj_probe_t *get;
int (*lock)(dev_t, void *);
void *data;
} *probes[255];
struct mutex *lock;
};
static struct char_device_struct {
struct char_device_struct *next;
unsigned int major;
unsigned int baseminor;
int minorct;
char name[64];
struct file_operations *fops;
struct cdev *cdev;
}
6. 切换数据
在
arch/arm/kernel/head-common.S 中:
00014: .type __switch_data, %object
00015: __switch_data:
00016: .long __mmap_switched
00017: .long __data_loc @ r4
00018: .long __data_start @ r5
00019: .long __bss_start @ r6
00020: .long _end @ r7
00021: .long processor_id @ r4
00022: .long __machine_arch_type @ r5
00023: .long cr_alignment @ r6
00024: .long init_thread_union + THREAD_START_SP @
sp
00025:
00026:
00034: .type __mmap_switched, %function
00035: __mmap_switched:
00036: adr r3, __switch_data + 4
00037:
00038: ldmia r3!, {r4, r5, r6, r7}