《linux 内核完全剖析》 笔记 CODE_SPACE 宏定义分析

在memory.c里面,遇到一个宏定义,如下:

#define CODE_SPACE(addr) ((((addr)+4095)&~4095) < current->start_code + current->end_code)

看的第一眼,不知道,第二眼,还是不知道,纠结了半天还是不知道。

睡了一晚,今天早上再看,嘿嘿,居然看懂了。。。

这个宏定义用于判断给定的addr线性地址是否位于当前进程的代码段中。

4095 = 0xFFF;

addr+4095的作用是将位于0~4095产生一个进位。

例如2+4095 = 4097 = 0x1001 最左边的1就是产生的进位,接着

(addr+4095) & ~4095的作用就是把刚得到的结果的低12位置0.这样一来

0x1001就变成了0x1000这个就是addr所在页最后的地址+1,即是当前页面的下一个页面的开始地址。

假设一个代码段占据了4个页面大小的内存

addr在这四个页面的话,(addr+4095)& ~4095 得到的将是addr所在页面的下一个页面的起始地址。如果该结果小于current->start_code + current->end_code 即代码段的结束地址,那么则该地址在代码段内,否则在代码段外面。

有一句话“认真你就输了”,其实是个人失望的表现,凡事就怕你较真,认真,死磕,终究会得到真正的答案,或许这个过程不好受。

《linux 内核完全剖析》 笔记 CODE_SPACE 宏定义分析,码迷,mamicode.com

时间: 2024-10-05 04:40:36

《linux 内核完全剖析》 笔记 CODE_SPACE 宏定义分析的相关文章

《linux 内核全然剖析》 笔记 CODE_SPACE 宏定义分析

在memory.c里面.遇到一个宏定义,例如以下: #define CODE_SPACE(addr) ((((addr)+4095)&~4095) < current->start_code + current->end_code) 看的第一眼,不知道.第二眼.还是不知道.纠结了半天还是不知道. 睡了一晚,今天早上再看,嘿嘿,竟然看懂了... 这个宏定义用于推断给定的addr线性地址是否位于当前进程的代码段中. 4095 = 0xFFF; addr+4095的作用是将位于0~40

《linux 内核全然剖析》 sys.c 代码分析

sys.c 代码分析 setregid /* * This is done BSD-style, with no consideration of the saved gid, except * that if you set the effective gid, it sets the saved gid too. This * makes it possible for a setgid program to completely drop its privileges, * which i

《linux 内核完全剖析》 fork.c 代码分析笔记

fork.c 代码分析笔记 verifiy_area long last_pid=0; //全局变量,用来记录目前最大的pid数值 void verify_area(void * addr,int size) // addr 是虚拟地址 ,size是需要写入的字节大小 { unsigned long start; start = (unsigned long) addr; //把地址强制类型转换之后,赋值给start size += start & 0xfff; //取addr在当前虚拟地址中4

《linux 内核完全剖析》 signal.c 代码分析笔记

signal.c 代码分析笔记 sgetmask int sys_sgetmask()// 获取当前进程阻塞的信号 { returncurrent->blocked; } sys_ssetmask int sys_ssetmask(int newmask) //设置当前进程阻塞信号,确保SIGKILL 和SIGSTOP不被阻塞 { int old=current->blocked; current->blocked= newmask & ~(1<<(SIGKILL-1

《linux 内核完全剖析》 exit.c 代码分析笔记

exit.c 代码分析笔记 release 释放进程的函数release() 主要根据指定进程的任务数据结构指针,在任务数组中删除指定的进程指针,释放相关内存页,并立刻让内核重新调度进程的运行. void release(struct task_struct * p) //释放p指向的进程 { int i; if (!p) //常规检测p是否为0 return; if (p == current) { //不能把自己给释放了 printk("task releasing itself\n\r&q

linux内核头文件kdev_t.h 宏定义解析

kdev_t.h 宏定义解析 这个header file反正不多,直接原因是--遇到了,就搞定它! dev_t 类型的变量定义在linux/types.h 用来保存设备编号--包括主设备号和次设备号.dev_t 是一个32位的数,其中12位用来表示设备号,其余20位用来表示次设备号. 始终不要对这32位是高12位是主设备号还是低2位是主设备号做出假定,不利于代码的可移植性,始终记得使用宏定义来处理dev_t ! 都在这里了: #define MINORBITS 20 //次设备号的占位数目 #d

《linux 内核完全剖析》 sys.c 代码分析

sys.c 代码分析 setregid /* * This is done BSD-style, with no consideration of the saved gid, except * that if you set the effective gid, it sets the saved gid too. This * makes it possible for a setgid program to completely drop its privileges, * which i

《linux 内核全然剖析》 include/asm/io.h

include/asm/io.h #define outb(value,port) __asm__ ("outb %%al,%%dx"::"a" (value),"d" (port)) //宏定义outb用汇编实现了在端口地址port处写入值value //使用的寄存器是al,一个byte长度,而端口port使用的是2byte长度地址来标记的寄存器,注意这里寄存器的使用 #define inb(port) ({ unsigned char _v;

《linux 内核全然剖析》 mktime.c

tm结构体的定义在time.h里面 struct tm { int tm_sec; int tm_min; int tm_hour; int tm_mday; int tm_mon; int tm_year; int tm_wday; int tm_yday; int tm_isdst; }; /* * linux/kernel/mktime.c * * (C) 1991 Linus Torvalds */ #include <time.h> /* * This isn't the libra