Linux-Kernel-Learning icon indicating copy to clipboard operation
Linux-Kernel-Learning copied to clipboard

Results 17 Linux-Kernel-Learning issues
Sort by recently updated
recently updated
newest added

宏定义原形在/include/linux/kernel.h中,定义如下: ``` c 487 * container_of - cast a member of a structure out to the containing structure 488   * @ptr:        the pointer to the member. 489   * @type:       the...

__read_mostly原语将定义为存放在.data.read_mostly段中   `include/asm/cache.h` ``` c \#define __read_mostly __attribute__((__section__(".data.read_mostly"))) ``` 由此可见,我们可以将经常需要被读取的数据定义为`__read_mostly`类型, 这样Linux内核被加载时,该数据将自动被存放到Cache中,以提高整个系统的执行效率. 另一方面,如果所在的平台没有Cache,或者虽然有Cache,但并不提供存放数据的接口,(也就是并不允许人工放置数据在Cache中), 这样定义为`__read_mostly`类型的数据将不能存放在Linux内核中,甚至也不能够被加载到系统内存去执行,将造成Linux 内核启动失败. > 解决的方法有两种: > - 修改`include/asm/cache.h`中的`__ready_mostly`定义为: > > ``` >    #define __read_mostly > ``` > - 或者修改`arch/xxx/kernel/vmlinux.S`中`.data.read_mostly`段的位置到实际内存空间中去,例如放置在`.data`段之后等等

 Linux有时候在操作成功时需要返回指针,而在失败时则返回错误码。遗憾的是,C语言每个函数只允许一个返回值,因此任何有关可能错误的信息都必须编码到指针中。虽然一般而言指针可以指向内存中的任意位置,而Linux支持的每个体系结构的虚拟地址空间都有从一个虚拟地址0到至少4KiB的区域,该区域没有任何有意义的信息。因此内核可以重用该地址范围来编码错误码。  内核中的函数常常返回指针,问题是如果出错,也希望通过返回的指针体现出来。总体来说,如果内核返回一个指针,那么有三种情况:合法指针、NULL指针和非法指针。 - 合法指针:内核返回的指针一般是指向页面的边界(4K边界对齐),即`ptr $0xfff == 0` - 非法指针:这样的ptr的值不可能落在`(0xfffff000, 0xffffffff)`之间(这个区间是内核的高地址区间),而一般内核的出错代码也是一个小负数,在-1000到0之间,转换成`unsigned long`类型,正好在`(0xfffff000, 0xffffffff)`之间。因此可以用`(unsigned long)ptr > (unsigned long)-1000L`来判断内核函数返回值是一个有效的指针还是一个出错码。 以下是具体代码: ``` /* *Kernel pointers have redundant information, so we can use a *scheme...

相信大家在看linux的source code的时候,都会注意到asmlinkage这个宏,它是用来做什么的呢? > The asmlinkage tag is one other thing that we should observe about this simple function. This is a #define for some gcc magic that tells the compiler...

`__builtin_expect`是GCC(version>=2.9)引进的宏,其作用就是帮助编译器判断条件跳转的预期值,避免跳转造成时间乱费。拿段代码来说: ``` c #define likely(x) __builtin_expect(!!(x), 1) 表示大多数情况下likely(x)条件为真,其存在形式一般为if(likely(x)) #define unlikely(x) __builtin_expect(!!(x), 0) 表示大多数情况下unlikely(x)条件为假,其存在形式为if(unlikely(x)) ``` 具体内部汇编实现过程,参看下面程序: ``` c #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) int test_likely(int x) { if(likely(x))...

``` data_items: .long 3,67,34,222,45,75,54,34,44,33,22,11,66,0 ``` .long指示声明一组数,每个数占32位,相当于C语言中的数组。这个数组开头定义了一个符号data_items,汇编器会把数组的首地址作为data_items符号所代表的地址,data_items类似于C语言中的数组名。data_items这个标号没有用.globl声明,因为它只在这个汇编程序内部使用,链接器不需要用到这个名字。除了.long之外,常用的数据声明还有: - .byte,也是声明一组数,每个数占8位 - .ascii,例如.ascii "Hello world",声明11个数,取值为相应字符的ASCII码。注意,和C语言不同,这样声明的字符串末尾是没有'\0'字符的,如果需要以'\0'结尾可以声明为.ascii "Hello world\0"。 data_items数组的最后一个数是0,我们在一个循环中依次比较每个数,碰到0的时候让循环终止

自从2.6内核放出以后,对于内核爱好者来说,每天都有享不尽的大餐,太令人激动了,每个版本都会推出新东西,本文就很简单的两个方面来讨论一下,一个是2.6内核以后在进入系统空间SAVE_ALL的时候,将ds寄存器设置为了`__USER_DS ` ``` #define SAVE_ALL \           cld; \           pushl %es; \           pushl %ds; \           pushl %eax; \           pushl %ebp; \           pushl %edi; \           pushl %esi; \           pushl %edx; \           pushl...