摘要:中断共享: 和别人讨论的时候,谈到了中断共享,下面记录下几种不同的情况:1、一个IP模块中只有一个中断引脚连接到中断控制器,该IP模块中只有一个部件可以产生中断请求;2、一个IP模块中只有一个中断引脚连接到中断控制器,该IP模块中有多个部件可以产生中断请求;3、多个IP模块的中断引脚通过电路设计(例如:数字电路中的线与逻辑电路)连接到中断控制器的一个引脚,该中断引脚上对应着多个IP模块的的中断请求。第一种情形,谈不上中断共享;第二种情形,这个不好定义,因为(1)可以只有一个中断函数、在中断函数内部判定是何种原因导致了该IP模块产生中断(一般都这样);(2)可以为每种导致该IP模块产生中断的情形
阅读全文
摘要:关于handle_level_irq与handle_edge_irq的理解: 电平中断处理handle_level_irq: (1)mask_ack_irq; (2)标记IRQ_INPROGRESS; (3)若发生同一中断线上的中断嵌套、则退出; (4)中断处理(在驱动程序的中断处理过程中可能会unmask中断); (5)unmask中断; 由于驱动程序中可能unmask中断,因此对于同一中断线上可能发生中断嵌套(假定系统设定为IRQF_SHARED),故需要(2)、(3)步骤;可以看出对于电平触发中断方式而言,在软件上并不支持中断嵌套(硬件上支持)。 边沿中断处理handle_edge_..
阅读全文
摘要:对于ARM体系结构,每一个由用户态到内核态的中断或异常处理路径都经过kuser_cmpxchg_check,kuser_cmpxchg_check中检查被中断的地址是否大于TASK_SIZE;TASK_SIZE是内核与用户空间的分界点,那么对于ARM体系而言,为什么在用户态时其执行路径会“顺利”地进入内核空间? 查了下,在Documentation/zh_CN/arm/kernel/kernel_user_helpers.txt中解释了对于ARM体系结构,由于没有类似x86的“比较交换”指令,因此在用户态下完成一些原子操作时需要借助于内核空间的一些操作来完成(此时,仍处于用户态,只是执行的..
阅读全文
摘要:应用程序调用glibc的fork, fork发起系统调用SyS_clone(sys_clone),SyS_clone中主要调用了do_fork。关注了下内核中do_fork的流程,遗留的问题有:(1)关于进程的相关进程号的知识;(2)调度域;(3)调度实体中的一些统计量的意义;(4)父子进程的信号处理关系;(5)copy_mm()---->dup_mm()---->dup_mmap(), dup_mmap()没看懂;(6)其它,很多;关于新建进程时的vruntime的处理需要注意:新建时是减去了min_vruntime,而后在入队时又加上了min_vruntime。以下分析为系统调
阅读全文
摘要:注:glibc-2.17中fork的相应系统调用是sys_clone及SyS_clone。有人说调用的是sys_fork,但是我持否定意见,如果我们向真的来发起系统调用可以使用syscall。fork系统调用等价于直接调用的就是do_fork(CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHILD, NULL, NULL, NULL, &THREAD_SELF->tid)。&THREAD_SELF->tid放在svc状态下的栈上,前四个参数在r0~r3中。比较简单,sys_clone实际上是SyS_clone__ve
阅读全文
摘要:因为想跟踪下在新建进程时,如何处理新建进程的vruntime,所以跟踪了下fork。以glic-2.17中ARM为例(unicore架构的没找到),实际上通过寄存器向系统调用传递的参数为:r7: __NR_clone 120r0: CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLDr1: NULLr2: NULLr3: NULLr4: &THREAD_SELF->tidfork()---->__fork()---->__libc_fork()__libc_fork()---->INLINE_SYSCALL (c
阅读全文
摘要:中断处理完毕后,系统有三种执行流向: 1)直接返回中断前的状态;2)系统重新进行调度;3)进行信号处理;我们此处重点关注:在用户态下发生scheduler_tick,且已判定当前进程可被抢占的情形(此处以ARM为例)。__irq_usr:#......b ret_to_user_from_irqENTRY(ret_to_user_from_irq) ldr r1, [tsk, #TI_FLAGS]#define _TIF_WORK_MASK (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_NOTIFY_RESUME) tst r1, #_T...
阅读全文
摘要:周期性调度器由中断实现,系统定时产生一个中断,然后启动周期性调度器,周期性调度器执行过程中要关闭中断, 周期性调度器执行完毕后再打开中断(handle_IRQ_event, IRQF_DISABLED) 周期性调度器主要做两个工作:a)更新相关统计量b)检查进程执行的时间是否超过了它对应的ideal_runtime,如果超过了,则告诉系统,需要启动主调度器(schedule)进行进程切换。(注意thread_info:preempt_count、thread_info:flags (TIF_NEED_RESCHED))周期性调度器 |---->do_timer() 更新jiffies..
阅读全文
摘要:引述自:http://www.unixresources.net/linux/clf/linuxK/archive/00/00/47/91/479165.htmlKevin.Liu 的《调度器笔记》中指明“有几个 CPU 就会有几个 rq 结构体,所有的结构体保存在 一个数组中(即runqueues)";《深入Linux内核架构》p_73指明”系统的所有就绪队列中都在runqueues数组中,由下定义完成: static DEFINE_PER_CPU_SHARED_ALIGNED(struct rq, runqueues);由于unicore32是单核,所以原先就没关注过这个问题..
阅读全文
摘要:在抽象模型中vruntime决定了进程被调度的先后顺序,在真实模型中决定被调度的先后顺序的参数是由函数entity_key决定的。 static inline s64 entity_key(struct cfs_rq *cfs_rq, struct sched_entity *se){ return se->vruntime - cfs_rq->min_vruntime;}enqueue_task_fair---->enqueue_entity---->__enqueue_entity---->entity_key决定插入就绪队列的位置。普通进程分为40个等级,每
阅读全文
摘要:我们知道如何在遵循C++语法条件下实现"虚函数、重载运算符函数"。我认为当我们尝试来实现重载运算符的虚函数时需要知道:函数签名、redefine、overload、override、虚表、RTTI、编译器默认的插入行为。(此处没有使用虚基类,因此不需要虚表表的知识)和 同学 以及 ”EA娘家人“分别讨论了这个问题,均没有得出详细的解答,不知到android源码中有没有,没仔细找。参考:http://stackoverflow.com/questions/669818/virtual-assignment-operator-chttp://www.icu-project.or
阅读全文
摘要:调度器真实模型的主要成员变量及与抽象模型的对应关系I、cfs_rq结构体 a) struct sched_entity *curr 指向当前正在执行的可调度实体。调度器的调度单位不是进程,而是可调度的实体。每个task_struct都嵌入了一个可调度实体sched_entity,所以每个进程是一个可调度实体。可以将多个进程捆绑在一起作为一个调度单位(即调度实体)进行调度。因此,可调度实体可以是一个进程,也可以是多个进程构成的一个组。为了简化,暂时把curr理解为指向当前正在运行的进程。 d) struct rboot tasks_timeline cfs就绪队列是用红黑树来组织的,tasks.
阅读全文
摘要:参考资料:《调度器笔记》Kevin.Liu 《Linux kernel development》 《深入Linux内核架构》 version: 2.6.32.9 下文中对于红黑树或链表组织的就绪队列,统称为用队列组织的就绪队列。 linux中用struct rq将处于ready状态的进程组织在一起。 struct rq结构体包含cfs和rt成员,分别表示两个就绪队列:cfs就绪队列用于组织就绪的普通进程(这个队列上的进程用完全公平调度器进行调度);rt就绪队列用于组织就绪的实时进程(该队列上的进程用实时调度器调度)。 在多核cpu系统中,每个cpu对应一个struct rq结构体实例。 核..
阅读全文
摘要:固然书本上讲明jiffies是jiffies_64的低32位,但是我还是自己测试了下,重点在于链接脚本的写法。此处只是为了测试,因此简化链接脚本。 /* link.lds */1 ENTRY(_start) 2 3 jiffies = jiffies_64; 4 5 SECTIONS 6 { 7 8 . = 0x0; 9 10 . = ALIGN(4);11 .t...
阅读全文
摘要:逛下bbs,“在C++中实现不可继承的类”,瞒有意思的。class NoInherite { friend class Seal; private: NoInherite(void) {} ~NoInherite(void) {}};class Seal: virtual private NoInherite{ public: Seal(v...
阅读全文
摘要:装饰模式可以在不改变一个对象本身功能的基础上给对象增加额外的新行为。装饰模式降低类系统的耦合度,可以动态地增加或删除对象的职责,并使得需要装饰的具体构件类和具体装饰类可以独立变化,以便增加新的具体构件类和具体的装饰类。在装饰模式中既可以调用待装饰的原有类的方法,还可以增加新的方法,以扩充原有类的功能。在装饰模式中,为了系统具有更好的灵活性和可扩展性,通常会定义一个抽象装饰类,而将具体的装饰类作为它的子类。在装饰模式中结构图中包含4个角色(1)、Component(抽象构件):它是具体构件和抽象装饰类的共同父类,声明了在具体构件中实现的业务方法。它的引入可以使客户端以一致的方式处理未被装饰的对象
阅读全文
摘要:看了android下的代码,好长时间没看了,有个关于C++的知识点不是很清楚,查了下:如何使用基类中的赋值运算符?引述自http://stackoverflow.com/questions/1226634/how-to-use-base-classs-constructors-and-assignment-operator-in-c参考:《C++ Primer》4ed_CN p_495编译器的默认设置:struct base{ base() { std::cout << "base()" << std::endl; } base( base cons
阅读全文
摘要:组合模式使用面向对象的思想来实现树形结构的处理和构件,描述了如何将容器对象和叶子对象进行递归组合,实现简单,灵活性好。组合模式(Composite Pattern):组合多个对象形成树形结构以表示具有“整体——部分”关系的层次结构。组合模式对单个对象(即叶子对象)和组合对象(即容器对象)的使用具有一致性,组合模式又可以称为“整体——部分”(Part-While)模式,它是一种对象结构型模式。组合模式的关键是定义了一个抽象构件类,它既可以代表叶子,也可以代表容器,而客户端针对该抽象构建类进行编程,无须知道它到底表示的是叶子还是容器,可以对其进行统一处理。同时容器对象与抽象构件类之间还建立了一个聚
阅读全文
摘要:引述自http://c-programming.itags.org/q_c-programming-language_191518.html源代码中的宏min中使用了 (void) (&_x == &_y); ( c89不支持typeof )有如下解释Assuming (as the name "typeof" implies) that _x has the same type asx, and _y has the same type as y, comparing the addresses of _x and _yis legal if and on
阅读全文
摘要:引述自Documents/zh_CN/CodingStyle 函数可以返回很多种不同类型的值,最常见的一种是表明函数执行成功或者失败的值。这样的一个值可以表示为一个错误代码整数(-Exx = 失败, 0 = 成功)或者一个“成功”布尔值(0 = 失败,非0 = 成功)。混合使用这两种表达式方式是难于发现的bug的来源。为了避免产生这种bug,请遵循下面的惯例: 如果函数的名字是一个动作或者强制性的命令,那么这个函数应该返回错误代码整数。如果是一个判断,那么函数应该返回一个“成功”布尔值。 返回值是实际计算结果而不是计算是否成功的标志的函数不受此惯例的限制。一般的,他们通过返回一些正常值范...
阅读全文
摘要:BUILD_BUG_ON()在编译时调用,可以提前发现错误,这里利用了一些不常用的特性,当数组个数元素为负时会发生编译器错误,对于位域宽度而言,其为负数时也会发生编译器错误。1 #define BUILD_BUG_ON_ZERO(e) (sizeof(struct{int : -!!(e);}))2 #define BUILD_BUG_ON_NULL(e) ((void*)sizeof(struct{int : -!!(e);}))3 4 #define BUILD_BUG_ON(condition) ((void)BUILD_BUG_ON_ZERO(condition))5 6 #de...
阅读全文
摘要:ANSI和UTF-8格式都不太了解,各自好像都有好几种,下载了一个库,文件基本都是ANSI格式,linux显示乱码,原来都是在虚拟机一个个的“另存为“完成的,这次文件有点多,因此需要用命令完成。以下方法不通用,遇到特殊情况再行处理方法1:1 iconv -f GBK -t UTF-8 inputfilename -o outputfilename2 #-f后是源文件编码3 #-t后是转换成的文件编码格式4 5 #icov -l 可以查看所有的编码格式,我尝试使用了 -f ANSI没有用6 #之所以使用 -f GBK, 完全是因为在用方法2来解决文件格式转化时,尝试了GBK参数,7 #因此使用了
阅读全文
摘要:整理下目录,看了这个文件,幸好未删除。以下是《write solid code》中的原文摘录。1、How could I have prevented this bug?2、How could I have automatically detected this bug?3、If a programmer believes that a bug can simply "go away", or that fixing bugs "later" won't be harmful to the product, bugs will persist.4
阅读全文
摘要:再次拜读csapp_2ed,仍然存在大量不足,部分习题尝试做了解答,还是有些不会,一些临碎的记录如下:p_159: sizeof运算符的返回值为size_t,无符号整型; 2.75ANSI C明确规定不允许编译器改变结构体成员对象的次序;如果让编译器随心所欲地改变结构体中各个对象的位置的话,显存的程序大部分都会崩溃。在C语言中,函数往往通过在结构体地址上加上偏移量来计算变量的位置。p_466: ARM中PC为当前指令地址+8通过典型的5级流水显然很容易理解,问题在于mips体系中分支延迟槽的实现问题又一次困扰住自己了(原来看了《计算机组成与设计》,上面讲了,没有留下笔记,有时间还得再看下)p_
阅读全文
摘要:csapp p_795如下所述的问题经过讨论并未被解决……以下示例中未以ARM为例,因为我查到的ARM的ABI规范中,寄存器均由callee保存,或者callee与caller均不保存,因此很容易可以解决下列问题。以下以i386为例.关于非本地跳转存在的疑问(以setjmp、longjmp为例)函数调用之间需遵循ABI规范 有些寄存器是由caller保存(以备被callee使用而修改原来的值),当从callee返回后恢复这些寄存器; 有些寄存器是由callee保存(以备被callee使用而修改原来的值),当即将从callee返回时恢复这些寄存器; 某些寄存器可以随便使用,即不需要caller保
阅读全文
摘要:此处请参考下:http://coolshell.cn/articles/10115.html C语言全局变量那些事儿csapp :p_700以上记录的解决方法有个缺点,当我们分别编译而后再链接时,只会报warning,因此当我们定义全局变量时尽量使其成为强符号,例如对于上例:double x = 0;
阅读全文