进程内核栈与进程描述符
task_struct 中部分成员的值 是随着进程的生命周期而动态变化的(如 :进程的状态 unsigned long state...)
先看一幅图:
软中断与进程内核栈
看一幅图
先从do_softirq()开始说吧,不论是再中断上下文中通过invoke_softirq()处理软中断,还是由中断守护进程ksoftirq来处理,他们都会调用到这个函数,
asmlinkage void do_softirq(void)
{
/**
typedef unsigned int __u32
它是软中断的位图(具体的说 是 __softirq_pending),无符号整形,触发软中断、检查有没有待处理的软中断
都依据的是这个pending(作者为什么要用一个整形来记录软中断?为什么要这样设计?没有更好的方法了吗?),
它的值来源于 local_softirq_pending()
好,下面我们来关注这个函数,看看它的源头活水
*/
__u32 pending;
unsigned long flags;
/*
如果还处于中断上下文环境中,就return了,为什么?
它的底层是 这样的一个宏函数 :
#define irq_count() (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK | NMI_MASK))
#define preempt_count() (current_thread_info()->preempt_count)
这个current_thread_info()函数 返回struct thread_info * 是我们重点关注的函数,在下面的代码再说,
*/
if (in_interrupt())
return;
/*
这个函数 最终调用了一个内嵌了汇编的函数:
下面是内嵌的汇编代码 :
第二行 是 cpsid i 来关闭中断。当然了开中断 就是 cpsie i 指令了
asm volatile(
" mrs %0, cpsr @ arch_local_irq_save\n"
" cpsid i"
: "=r" (flags) : : "memory", "cc");
return flags;
*/
local_irq_save(flags);
/*
好,真正的演员 闪亮登场了 .............. 下面单独说
*/
pending = local_softirq_pending();
/*
如果有待处理的软中断,就调用__do_softirq()函数处理,
这个函数不是我们的重点,它的处理过程大致是 :
我以前的博文写了一点,关于tasklet的,可参考一下
http://blog.csdn.net/leesagacious/article/details/50500096
依次检查它的32位,看是否为 1,如果为 1 ,就调用软中断处理函数
代码 :
do{
if(pending & 1) //检查第一位 是否被 置 1,所以,当pending == 0了,就说明没有待处理的软中断了,
{
h->action(h); // 看! 在这里,软中断处理函数被调用。在这里被调用,在open_softirq()函数先注册好.
}
h++;
pending >>= 1; //pending的位 >> 1位,32位向右都移动一位,丢掉已经检查后的第一位(TASKLET_SOFTIRQ位于第6位),
}while(pending);
下面有一幅图,简略描述了一下过程
*/
if (pending)
__do_softirq();
local_irq_restore(flags);
}
所以,软中断被调用的条件是 :
1 : 不在中断上下文中
2 : local_softirq_pending()返回值不为0,即有待处理的软中断
进程描述符与Linux高速缓存
进程描述符的各个成员
1 : struct files_struct * files;
先看一幅图
struct task_struct
{
struct files_struct * files;
};
struct files_struct{
/*
fd_array[]
里面存放的都是 struct file *,指向打开的文件
数组下标 就是 在应用空间执行open()函数的返回值
*/
struct file __rcu * fd_array[NR_OPEN_DEFAULT];
};
struct file{
/*
文件操作表,表中是向VFS层提供的接口函数
用户空间通过设备文件对设备的open()、ioctl()的操作,
这个表中对应的函数会响应
*/
const struct file_operations * f_op;
/*
文件的引用计数
*/
atomic_long_t f_count;
/*
打开文件时指定的标志
*/
unsigned int f_flags;
/*
访问模式
*/
fmode_t f_mode;
/*
文件指针位移
*/
loff_t f_pos;
/*
这个很重要,打开文件的私有数据,你可以把数据暂时存放在这里,
在需要的地方通过 file->private_data取出来,
这个技巧,在kernel中使用的很多,一般是在open函数中设置的
*/
void * private_data;
};
实验验证 (上面的那个图画错了,呜呜…)