自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

  • 博客(97)
  • 收藏
  • 关注

原创 linux的高端内存映射

我们在前面分析过,在linux内存管理中,内核使用3G—>4G的地址空间,总共1G的大小。而且有一部份用来做非连续空间的物理映射(vmalloc).除掉这部份空间之外,只留下896M大小供内核映射到物理地址。通常,我们把物理地址超过896M的区域称为高端内存。内核怎样去管理高端内存呢?今天就来分析这个问题。内核有三种方式管理高端内存。第一种是非连续映射。这我们在前面的vmalloc中已经分析过

2012-02-28 21:31:46 351

转载 内核中的等待队列

Linux内核的等待队列是以双循环链表为基础数据结构,与进程调度机制紧密结合,能够用于实现核心的异步事件通知机制。在Linux2.4.21中,等待队列在源代码树include/linux/wait.h中,这是一个通过list_head连接的典型双循环链表,如下图所示。 在这个链表

2011-07-17 15:28:55 274

转载 二级指针做参数

程序1: void myMalloc(char *s) //我想在函数中分配内存,再返回 {      s=(char *) malloc(100); } void main() {      char *p=NULL;      myMalloc(p);    //这里的p实际还是NULL,p的值没有改变,为什么?      if(p) free(p); } 程序2:void

2011-06-09 00:11:00 2243

转载 Makefile使用入门

<br />"make"使用入门<br />原文作者:Suminder S. Ahuja <br />翻译:艾艾<br />正文:<br /> 概述 <br /> makefile介绍 <br /> makefile组成 <br /> 注释 <br /> 显式规则 <br /> make的执行 <br /> 使用make的好处 <br /> 定义变量 <br /> 引用替换和计算变量名 <br /> 递归扩展和简单扩展变量 <br /> 给变量添加文本 <br /> 自动变量 <br

2011-03-28 11:16:00 985

原创 linux设备驱动(十四)--内存分配

linux内核为设备驱动程序提供了一致的内存管理接口,所以模块不涉及到分段、分页的问题。kmalloc函数kmalloc与malloc相似,除非被阻塞,否则这个函数可运行的很快,而且不对获取的空间清零,也就是说,分配给它的区域仍然保持着原有数据。它分配的内存在物理内存中是连续的。原型如下:#include void *kmalloc(size_t size,int flags);最常用的标志是:GFP_KERNEL,它表示内存分配(最终总是调用get_free_page来实现的,这就是GFP_的由来)是代表

2010-09-15 11:48:00 1426

转载 makefile备忘

makefile文件 备忘-4)替换引用规则 (也成 Pattern Rule 自定义的隐含规则)%.o : %.ctells make to build any object file somename.o from a source file somename.c.%可以代表任意长度的任意字符eg:    %.o : %.c          $(CC) -c $(CFLAGS) $(CPPFLAGS) $    把每一个c文件编译成 .o文件-3)makefile的每行命令前必须使用 tab 而不能是

2010-08-16 16:04:00 426

转载 指针

数组名与指针变量的区别       指针是C/C++语言的特色,而数组名与指针有太多的相似,甚至很多时候,数组名可以作为指针使用。于是乎,很多程序设计者就被搞糊涂了。而许多的大学老师,他们在C语言的教学过程中也错误得给学生讲解:"数组名就是指针"。很幸运,我的大学老师就是其中之一。时至今日,我日复一日地进行着C/C++项目的开发,而身边还一直充满这样的程序员,他们保留着"数

2012-04-20 09:41:01 216

转载 GDB调试

http://wiki.chinaunix.net/%E4%BD%BF%E7%94%A8GDB%E8%B0%83%E8%AF%95

2012-04-19 10:27:24 222

原创 VI的查找与替换

替换::"s"代表替换,part1代表查找的内容,part2代表替换的内容,"%"代表所有行,"g"代表替换整行里所有的内容(如果不加"/g" 则只替换每行第一个匹配part1的地方)%表示全部的行;.表示当前行;$表示最后一行;可以用具体的数字表示具体的行,如10,20等:s/part1/part2           #用part2替换当前行中第1个part1:

2012-04-04 16:31:58 344

转载 编译性语言、解释性语言和脚本语言

什么是编译性语言、解释性语言和脚本语言  计算机不能直接理解高级语言,只能直接理解机器语言,所以必须要把高级语言翻译成机器语言,计算机才能值型高级语言编写的程序。  翻译的方式有两种,一个是编译,一个是解释。两种方式只是翻译的时间不同。编译型语言写的程序执行之前,需要一个专门的编译过程,把程序编译成为机器语言的文件,比如exe文件,以后要运行的话就不用重新翻译了,直接使用编译的结果就行

2012-03-11 10:36:20 420

转载 ARM体系结构

今天学习的是ARM体系结构。以前只知道ram是随机存取存储器的意思,还不知道有体系结构这么一回事。虽然也认真听讲,但还是云里雾里的,概念很模糊。在网上发现一篇关于ARM的文章,写的不错。ARM 体系结构  Q: ARM 是什么?A: ARM(Advanced RISC Machines),既可以认为是一个公司的名字,也可以认为是对一类微处理器的通称,还可以认为是一种技术的名字。

2012-02-28 22:34:41 5236

转载 lru算法分析

什么是LRU算法? LRU是Least Recently Used的缩写,即最近最少使用页面置换算法,是为虚拟页式存储管理服务的。关于操作系统的内存管理,如何节省利用容量不大的内存为最多的进程提供资源,一直是研究的重要方向。而内存的虚拟存储管理,是现在最通用,最成功的方式——在内存有限的情况下,扩展一部分外存作为虚拟内存,真正的内存只存储当前运行时所用得到信息。这无疑极大地扩充了内存的功能,极

2012-02-28 22:01:13 499

原创 linux内核对内存的管理和使用

首先当程序需要一块不存在的内存时(也即页表项中已经标记出相应的页面不在内存中),CPU通过80386的页错误异常中断来实现。当一个进程引用一个不存在的内存页面时就会产生一个页错误中断,并把引起中断的线性地址保存在CR2寄存器中(便于高效快速访问),因此处理该中断的程序就可以知道页异常的确切地址,从而可以把进程要求的页面从二级存储空间(比如硬盘)加载到内存中。如果此时物理内存已经被占用,则可以借助二

2011-06-08 17:45:00 664

原创 C语言的几个问题

1.函数调用压入堆栈的情况:void add(int a,int b, int c){   int i,j;}在函数调用时将其参数和返回地址压入堆栈,堆栈中存储的函数调用信息成为调用结构,为了让函数找到调用结构,提供了基指针寄存器(BP)将其赋给结构的起始地址同时将局部变量压入堆栈。函数参数的压入堆栈的顺序是从右向左,局部变量的压入顺序是声明的顺序。  2.

2011-06-08 10:05:00 224

原创 0.11linux内存管理

linux内存管理程序主要有两个功能:1.实现分段和分页机制。 2.内存的寻址保护机制。通过分段虚拟地址转换为线性地址,通过分页线性地址转换为物理地址。一个系统可以有多个页目录表,但某一时刻只有一个页目录表可用,当前页目录表是有在CPU的CR3确定的,它存储着当前页目录表对应的物理地址。(0.11内核只用到了一个页目录表)。一个页目录表占用一个页面,并用4个字节寻址一个页目录项,这样一个页目录表可以寻址1024个页目录项。页目录项同理可以寻址1024个页面。这样一个页目录表可以寻址1024*1024*409

2011-06-01 12:34:00 600

原创 sys_pipe()创建管道

<br />int sys_pipe(unsigned long *fildes)  //向fildes数组中返回两个文件句柄,一个用于管道写一个用于管道读<br />{<br />    struct m_inode *inode;<br />    struct file *f[2];<br />    int fd[2];<br />    int i,j;<br /> <br />    j = 0;<br />    for(i=0;j<2&i<NR_FILE;i++)<br />       

2011-05-27 10:43:00 452

原创 进程地址空间与进程的内存区域

首先进程地址空间和进程内存区域是两个概念:1.进程地址空间:系统中每个用户空间进程所看到的内存(虚拟内存).内核采用mm_struct结构来描述进程地址空间。2.进程的内存区域:在进程地址空间中,我们更关心的是进程有权访问的虚拟内存地址区间,这些可以被合法访问的地址区间成为内存区域。如果进程访问不再有效范围之内的内存,内核会终止进程提示段错误v。用vm_area_struct结构表示。vm_area_struct包含在mm_struct之中,在内核中被组织成单链表和红黑树的形式。便于便利和查找。mm_str

2011-05-23 23:16:00 1140

原创 linux高速缓存结构分析

<br />struct buffer_head {<br /> char * b_data;   /* pointer to data block (1024 bytes) */<br /> unsigned long b_blocknr; /* block number */<br /> unsigned short b_dev;  /* device (0 = free) */<br /> unsigned char b_uptodate;<br /> unsigned char b_dirt;  /

2011-05-14 15:40:00 490

原创 0.11 文件系统的数据结构

在Linux中普通文件和目录文件保存在称为块物理设备的磁盘或者磁带上。一套Linux系统支持若干物理盘,每个物理盘可定义一个或者多个文件系统。(类比于微机磁盘分区)。每个文件系统由逻辑块的序列组成,一个逻辑盘空间一般划分为几个用途各不相同的部分,即引导块、超级块、inode区以及数据区等。文件系统逻辑块各部分分布图:其中引导块部分可以不包含代码,但必须存在以保持格式的一致性。超级快:struct super_block { unsigned short s_ninodes;  //节点数 unsigned

2011-05-09 22:46:00 558

原创 0.11 tty_ioctl.c注释

tt_ioctl在涉及到termios的结构操作时,用到了一个技巧,将结构体首地址强转为字符类型,通过put_fs_byte和get_fs_byte来进行赋值,还有verify_area()函数,在内核态操作用户态内存数据结构时,要进行的检查工作,保证写时复制操作。代码:tty是要操作的tty结构,termios是用户态传经来的termios指针保存tty结构中的termios,这里注意在运用强转时,总是对地址进行操作的。static int get_termios(struct tty_struct *

2011-05-09 14:46:00 979

原创 linux 0.11串口程序分析

0.11内核维护着3个终端,一个显示器和键盘,另外两个是串口1,2. 每个终端有维护着3个队列读写和辅助缓冲队列。对于每个缓冲队列,读操作从队列左边取字符,并将队尾指针向右移动。写操作从队列右边写字符,并将队头指针向右移动。任何一个移动到队列尾端则折回到左端从新开始。主要的终端读写函数包括tty_read(),tty_write(),copy_to_cooked().tty_read(),tty_write()在文件系统操作字符设备文件时被调用。例如一个程序读写/dev/tty就会执行系统调用sys_rea

2011-05-06 22:19:00 527

转载 内核中断初始化分析

<br />首先明确下概念:<br />      在Intel的文档中,把中断分为两种.一种是异常,也叫同步同断或者内部中断.一种称之为中断,也叫异常中断或者外部中断.<br />  同步中断指的是由CPU控制单元产生,之所以称之为同步,是因为只有一条指令执行完毕后才会发出中断.例如除法运算中,除数为零的时候,就会产生一个异常<br />  异步中断是由外部设备按照CPU的时钟随机产生的.例如,网卡检测到一个数据到来就会产生一个中断.<br />在init/main.c中:<br />  asmlinka

2011-05-06 10:39:00 501

原创 2.6内核块I/O管理

<br />内核中用到的最小寻址单元是块,块是文件系统的一种抽象,只能基于块来访问文件系统。虽然物理磁盘寻址是按照扇区进行的,但内核执行的所有磁盘操作都是通过块来执行的。块的大小必须是扇区大小的2的整数倍(可以包含多个扇区),并且要小于页面的大小。<br />2.6内核块I/O设计到两个结构体,struct buffer_head和struct bio。当一个块被调入内存中,它要存储在一个缓冲区中,每个缓冲区与一个块对应,它相当于磁盘块在内存中的表示,该缓冲区用buffer_head结构来表示,该结构体在2

2011-05-05 16:03:00 878

原创 PUTCH(c,queue)函数

<br />PUTCH函数原型如下:<br />PUTCH(c,queue)将字符C加入到队列queue中,内核中实现为宏函数:<br />#define PUTCH(c,queue) /<br />(void)({(queue).buf[(queue).head] = (c);INC((queue).head);})<br />注意在对c和queue引用是,必须加上括号<br />#define PUTCH(c,queue) /<br />(void)({(queue).buf[(queue).head]

2011-04-30 11:31:00 433

原创 关于sleep_on()函数的理解

linux内核完全剖析 P283页, 内核函数void sleep_on(struct task_struct **p): {      struct task_struct *tmp;      if(!p)             return;     if (current == &(init_task.task))          panic("task[0] trying to sleep");     tmp = *p;     *p = current;     current->stat

2011-04-22 21:39:00 1663 1

原创 linux块设备读写的底层实现

<br />ll_re_block()函数:内核块设备读写都是通过该函数申请请求项来完成的。该函数首先建立请求项,并插入到指定块设备的请求队列中,实际的读写操作则是用请求项函数request_fn()来完成的--对与硬盘来说是do_hd_request().该函数建立的请求项后,首先会检查对应的请求项队列是否为空,如果为空则设置该请求项为当前请求项,否则利用电梯算法将该请求项加入请求项队列。由于每个do_hd_request()在结束每个请求项处理后,都会通过终端回调函数(read_intr和write_i

2011-04-21 22:07:00 1000

转载 smp_processor_id()

smp_processor_id()用于返回当前处理器的id号unsigned int smp_processor_id(void){    unsigned long preempt_count = preempt_count();    int this_cpu = __smp_processor_id();    cpumask_t this_mask;    if (likely(preempt_count))  //表示preempt_count为1的可能比较大        goto out; 

2011-04-10 23:51:00 1988

转载 kmap_atomic的细节以及改进

kmap_atomic用于高端内存映射,用于紧急的,短时间的映射,它没有使用任何锁,完全靠一个数学公式来避免混乱,它空间有限且虚拟地址固定,这意味着它映射的内存不能长期被占用而不被unmap,kmap_atomic在效率上要比kmap提升不少,然而它和kmap却不是用于同一场合的。不管怎么说,它的设计是很完美的。     kernel可以在多个cpu上同时运行不同的task,然而它们共同使用一个内存地址空间,也就是说,地址空间对于多个cpu看到的是同一个,kmap_atomic使用的是地址空间顶部的一小段地

2011-04-10 11:13:00 1606

原创 llinux中的块设备操作

当内核想快设备发出一个读写请求或其他请求时,ll_rw_block就会根据其参数指明的操作命令和数据缓冲块头中的设备号,利用对应请求项的操作函数do_xx_request建立一个块设备请求项,并利用电梯算法将新生成的请求项插入请求项队列中。1.struct request { int dev;  /* -1 if no request */ int cmd;  /* READ or WRITE */ int errors; unsigned long sector; unsigned long nr_sec

2011-04-07 14:17:00 935

转载 verify_area()

对于80386CPU,在执行特权级0代码时不会理会用户空间中的页面是否是页保护的,因此在执行内核代码时用户空间中数据页面保护标志起不了作用,写时复制机制也就失去了作用。verify_area()就用于此目的。// 对当前进程地址从addr到addr + size这一段空间以页为单位执行写操作前的检测操作。// 由于检测判断是以页面为单位进行操作,因此程序首先需要找出addr所在页面开始地址start,// 然后start加上进程数据段基址,使这个start变换成CPU 4G线性空间中的地址。最后循环

2011-04-05 10:43:00 1335

转载 AT&T汇编格式

<br />因为在linux的内核中,很多跟底层硬件接触的都使用汇编语言,但是Linux不仅使用一种汇编语言,除了Intel的汇编语言之外,还是用AT&T的汇编语言,因此可以说这两个是一个基础,Intel的汇编相信很多学计算机的人都学习过,但是AT&T的就不一定了,个人认为他们的思想都是一样的,只不过是语法不同,初级学习可以看如下的文章(文章转自http://blog.chinaunix.net/u1/59572/showart_1148334.html)<br />一、AT&T 格式Linux 汇编语法格

2011-03-30 12:08:00 803

转载 dup和dup2调用

<br />dup和dup2也是两个非常有用的调用,他们的作用都是用来复制一个文件的描述符。他们经常用来重定向进程的stdin、stdout和stderr。这两个函数的原型如下所示:<br />#include <br />int dup( int oldfd );<br />int dup2( int oldfd, int targetfd )<br />利用函数dup,我们能复制一个描述符。传给该函数一个既有的描述符,他就会返回一个新的描述符,这个新的描述符是传给他的描述符的拷贝。这意味着,这两个描述符

2011-03-28 20:17:00 446

转载 可变参数va_start,va_arg,va_end的用法

一)写一个简单的可变参数的C函数 下面我们来探讨如何写一个简单的可变参数的C函数.写可变参数的 C函数要在程序中用到以下这些宏: void va_start( va_list arg_ptr, prev_param ); type va_arg( va_list arg_ptr, type ); void va_end( va_list arg_ptr ); va_list:用来保存宏va_start、va_arg和va_end所需信息的一种类型。为了访问变长参数列表中的参数,必须声明           

2011-03-28 15:54:00 204

原创 C和C++函数的相互引用----C++中extern “C”含义深层探索[转载]

1.引言  C++语言的创建初衷是“a better C”,但是这并不意味着C++中类似C语言的全局变量和函数所采用的编译和连接方式与C语言完全相同。作为一种欲与C兼容的语言,C++保留了一部分过程 式语言的特点(被世人称为“不彻底地面向对象”),因而它可以定义不属于任何类的全局变量和函数。但是,C++毕竟是一种面向对象的程序设计语言,为了支 持函数的重载,C++对全局函数的处理方式与C有明显的不同。2.从标准头文件说起某企业曾经给出如下的一道面试题:为什么标准头文件都有类似以下的结构? #ifndef _

2011-03-11 10:54:00 268

原创 linux设备驱动(十八)--设备驱动模型(三)各环节整合

PCI设备创建过程

2010-10-28 11:43:00 587

转载 华为面试题算什么,这个背会了外企随便进

我为各位整理出英文面试最常见的五大问题,并且提醒各位一些回答的技巧,希望大家能针对这些问题多演练,当成练习英文面试的重点。 问题一:Could you please describe yourself?(能否请你形容一下自己?)这个问题,一来是想要了解你是什么样的人,二来是想看看你是否知道如何重点式地自我简介。 在回答时,要针对应征工作的性质来凸显自己的特色,可以多用形容词,并且引用过去的工作经验,但是不必提及公司组织的名称,再者,你还可以谈谈未来的生涯规画;但如果你是个社会新鲜人,就可以谈谈在校时的丰功伟

2010-10-28 09:12:00 22080 50

原创 linux设备驱动(十八)--设备驱动模型(二)总线、设备、类

现在开始linux设备模型高级部分。

2010-10-26 11:33:00 661

转载 指针(五)

main函数的形参main函数一般写成main(){}实际上main函数也可以有参数main(int argc,char *argv[]){}使用参数的命令行形式为:命令名 参数1 参数2 ......参数n例如:test.exe的源文件中有如下代码main(int argc,char *argv[]){while(argc-->1)printf("%s/n",*++argv);}在命令行输入test aa bb输出结果为:aabb这里需要说明几点:一、argc的值为3,并不是2,因为它包含了test,但实

2010-10-26 10:44:00 230

转载 指针(四)

函数的指针和指向函数的指针变量可以用指针变量指向整型变量、字符串、数组,也可以指向一个函数。一个函数在编译时被分配一个入口地址,成为函数的指针。每一个函数都占用一段内存单元,有一个起始地址。因此,可以用一个指针变量指向一个函数,通过这个指针变量来访问它指向的函数。指向函数的指针的定义形式为:数据类型 (*指针变量名)(形参表);--(C语言中可以没有形参表,但在C++中必须有)int max(int a,int b){if(a>b)return a;elsereturn b;}void main(){int

2010-10-26 10:41:00 190

转载 指针(三)

<br /><br />C程序中,可以用两种方法访问一个字符串。<br />一、用字符数组存放一个字符串<br />char string[]="This is a String.";<br />和前面介绍的一样,string是数组名,代表字符串数组的首地址。<br />二、用字符指针指向一个字符串<br />char *string="This is a String,too.";<br />C语言对字符串常量是按字符数组处理的,在内存开辟了一个字符数组用来存放字符串常量。<br />string被定义成

2010-10-26 10:05:00 248

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除