探索Linux内核:_read的作用及实现方式 (linux内核_read)
Linux操作系统是目前世界范围内广泛应用的一种开源系统,其内核作为操作系统的核心组成部分承载着操作系统的全部功能,使得操作系统得以运行各种应用程序。在Linux内核中,_read是其中一个重要的函数,其在数据操作和文件读写中扮演着非常重要的角色。本文将从_read函数的作用和实现方式两个方面来探索Linux内核。
一、_read函数的作用
_read是Linux文件系统中的一个函数,主要用于操作文件的读取操作。当我们在系统中进行读操作时,_read函数将会被调用,该函数会检查我们传递给它的参数,找到所期望的数据块,然后将其从磁盘中读出来,并将其存储在用户空间中以供使用。
具体来说,当用户请求_read函数从文件中读取数据时,_read就会进入以下步骤:
1. _read函数会查找文件的索引节点,并获取其相关属性(例如文件大小和块的大小);
2. 接着,_read函数会检查用户请求的数据块是否为当前的块,并根据需要在磁盘中寻找该块;
3. 如果找到了该块,_read函数就会将其从磁盘中读出来,并存储在一个适当的内存缓存区中;
4. _read函数将数据块复制到用户的缓存区中,以便用户可以对其进行操作和使用。
因此,_read函数的作用就是完成了Linux文件系统中读取数据的基本操作,为应用程序提供了必要的数据。
二、_read函数的实现方式
_read函数的实现方式取决于所使用的文件系统和内核版本。在Linux内核的早期版本中,该函数的实现方式是通过调用底层的磁盘读取函数来完成的。但是,在随后的内核版本中,这种方式被认为是不够有效的,因为它对磁盘进行了大量的读取和写入,从而导致了性能下降。
为此,新的实现方式通过使用内存缓存技术来提高性能。在这种情况下,_read函数会将数据块存储在内存缓存中,以便在以后的读操作中直接使用。这种实现方式的基本思路是:在文件系统被挂载时,内存缓存会被预先填充,以便在以后的操作中提供快速访问。
三、
_read是Linux文件系统中非常重要的一个函数,它提供了文件数据的读取功能。理解_read函数的作用和实现方式有助于我们更好地了解Linux内核的工作原理和性能优化方法。虽然_read函数的实现方式几乎是每个内核版本都不同,但是其本质功能没有改变,因此,对_read函数的研究可以使我们更好地理解Linux操作系统。
相关问题拓展阅读:
linux内核同步问题
Linux内核设计与实现 十、内核同步方法
手把手教Linux驱动5-自旋锁、信号量、互斥体概述
==
基础概念:
==
并发
:多个执行单元同时进行或多个执行单元微观串行执行,宏谨拿观并行执行
竞态
:并发的执行单元对共享资源(硬件资源和软件上的全局变量)的访问而导致的竟态状态。
临界资源
:多个进程访问的资源
临界区
:多个进程访问的代码段
==
并发场合:
==
1、单CPU之间进程间的并发
:时间片轮转,调度进程。 A进程访问打印机,时间片用完,OS调度B进程访问打印机。
2、单cpu上进程和中断之间并发
:CPU必须停止当前进程的执行中断;
3、多cpu之间
4、单CPU上中断之间的并发
==
使用偏向:
==
==信号量用于进程之间的同步,进程在信号量保护的临界区代码里面是可以睡眠的(需要进行进程调度),这是与自旋锁更大的区别。==
信号量又称为信号灯,它是用来协调不同进程间的数据对象的,而最主要的应用是共享内存方式的进程间通信。本质上,信号量是一个计数器,它用来记录对某个资源(如共享内存)的存取状况。它负责协调各个进程,以保证他们能够正确、合理的使用公共资源。它和spin lock更大的不同之处就是:无法获取信号量的进程可以睡眠祥李搭,因此会导致系统调度。
1、==用于进程与进程之间的同步==
2、==允许多个进程进入临界区代码执行,临界区代码允许睡眠;==
3、信号量本质是==基于调度器的==,在UP和P下没有区别;进程获取不到信号量将陷入休眠,并让出CPU;
4、不支持进程和中断之间的同步
5、==进程调度也是会消耗系统资源的,如果一个int型共享变量就需要使用信号量,将极大的浪费系统资源==
6、信号量可以用于多个线程,用于资源的计数(有多种状态)
==信号量加锁以及解锁过程:==
sema_init(&sp->dead_sem, 0); /
初始化
/
down(&sema);
临界区代码
up(&sema);
==信号量定义:==
==信号量初始化:==
==dowm函数实现扰高:==
==up函数实现:==
信号量一般可以用来标记可用资源的个数。
举2个生活中的例子:
==dowm函数实现原理解析:==
(1)down
判断sem->count是否 > 0,大于0则说明系统资源够用,分配一个给该进程,否则进入__down(sem);
(2)__down
调用__down_common(sem, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);其中TASK_UNINTERRUPTIBLE=2代表进入睡眠,且不可以打断;MAX_SCHEDULE_TIMEOUT休眠最长LONG_MAX时间;
(3)list_add_tail(&waiter.list, &sem->wait_list);
把当前进程加入到sem->wait_list中;
(3)先解锁后加锁;
进入__down_common前已经加锁了,先把解锁,调用schedule_timeout(timeout),当waiter.up=1后跳出for循环;退出函数之前再加锁;
Linux内核ARM构架中原子变量的底层实现研究
rk3288 原子操作和原子位操作
原子变量适用于只共享一个int型变量;
1、原子操作是指不被打断的操作,即它是最小的执行单位。
2、最简单的原子操作就是一条条的汇编指令(不包括一些伪指令,伪指令会被汇编器解释成多条汇编指令)
==常见函数:==
==以atomic_inc为例介绍实现过程==
在Linux内核文件archarmincludeaatomic.h中。 执行atomic_read、atomic_set这些操作都只需要一条汇编指令,所以它们本身就是不可打断的。 需要特别研究的是atomic_inc、atomic_dec这类读出、修改、写回的函数。
所以atomic_add的原型是下面这个宏:
atomic_add等效于:
result(%0) tmp(%1) (v->counter)(%2) (&v->counter)(%3) i(%4)
注意:根据内联汇编的语法,result、tmp、&v->counter对应的数据都放在了寄存器中操作。如果出现上下文切换,切换机制会做寄存器上下文保护。
(1)ldrex %0,
意思是将&v->counter指向的数据放入result中,并且(分别在Local monitor和Global monitor中)设置独占标志。
(2)add %0, %0, %4
result = result + i
(3)strex %1, %0,
意思是将result保存到&v->counter指向的内存中,
此时 Exclusive monitors会发挥作用,将保存是否成功的标志放入tmp中。
(4) teq %1, #0
测试strex是否成功(tmp == 0 ??)
(5)bne 1b
如果发现strex失败,从(1)再次执行。
Spinlock 是内核中提供的一种比较常见的锁机制,==自旋锁是“原地等待”的方式解决资源冲突的==,即,一个线程获取了一个自旋锁后,另外一个线程期望获取该自旋锁,获取不到,只能够原地“打转”(忙等待)。由于自旋锁的这个忙等待的特性,注定了它使用场景上的限制 —— 自旋锁不应该被长时间的持有(消耗 CPU 资源),一般应用在==中断上下文==。
1、spinlock是一种死等机制
2、信号量可以允许多个执行单元进入,spinlock不行,一次只能允许一个执行单元获取锁,并且进入临界区,其他执行单元都是在门口不断的死等
3、由于不休眠,因此spinlock可以应用在中断上下文中;
4、由于spinlock死等的特性,因此临界区执行代码尽可能的短;
==spinlock加锁以及解锁过程:==
spin_lock(&devices_lock);
临界区代码
spin_unlock(&devices_lock);
==spinlock初始化==
==进程和进程之间同步==
==本地软中断之间同步==
==本地硬中断之间同步==
==本地硬中断之间同步并且保存本地中断状态==
==尝试获取锁==
==
arch_spinlock_t结构体定义如下:
==
==
arch_spin_lock的实现如下:
==
lockval(%0) newval(%1) tmp(%2) &lock->slock(%3) 1 slock的值赋值给lockval;并且(分别在Local monitor和Global monitor中)设置独占标志。
(2)add %1, %0, %4
newval =lockval +(1slock指向的内存中,
此时 Exclusive monitors会发挥作用,将保存是否成功的标志放入tmp中。
(4) teq %2, #0
测试strex是否成功
(5)bne 1b
如果发现strex失败,从(1)再次执行。
通过上面的分析,可知关键在于strex的操作是否成功的判断上。而这个就归功于ARM的Exclusive monitors和ldrex/strex指令的机制。
(6)while (lockval.tickets.next != lockval.tickets.owner)
如何lockval.tickets的next和owner是否相等。相同则跳出while循环,否则在循环内等待判断;
*
(7)wfe()和p_mb() 最终调用#define barrier()
a
volatile
(“”: : :”memory”) *
阻止编译器重排,保证编译程序时在优化屏障之前的指令不会在优化屏障之后执行。
==
arch_spin_unlock的实现如下:
==
退出锁时:tickets.owner++
==
出现死锁的情况:
==
1、拥有自旋锁的进程A在内核态阻塞了,内核调度B进程,碰巧B进程也要获得自旋锁,此时B只能自旋转。 而此时抢占已经关闭,(单核)不会调度A进程了,B永远自旋,产生死锁。
2、进程A拥有自旋锁,中断到来,CPU执行中断函数,中断处理函数,中断处理函数需要获得自旋锁,访问共享资源,此时无法获得锁,只能自旋,产生死锁。
==
如何避免死锁:
==
1、如果中断处理函数中也要获得自旋锁,那么驱动程序需要在拥有自旋锁时禁止中断;
2、自旋锁必须在可能的最短时间内拥有
3、避免某个获得锁的函数调用其他同样试图获取这个锁的函数,否则代码就会死锁;不论是信号量还是自旋锁,都不允许锁拥有者第二次获得这个锁,如果试图这么做,系统将挂起;
4、锁的顺序规则(a) 按同样的顺序获得锁;b) 如果必须获得一个局部锁和一个属于内核更中心位置的锁,则应该首先获取自己的局部锁 ;c) 如果我们拥有信号量和自旋锁的组合,则必须首先获得信号量;在拥有自旋锁时调用down(可导致休眠)是个严重的错误的;)
==
rw(read/write)spinlock:
==
加锁逻辑:
1、假设临界区内没有任何的thread,这个时候任何的读线程和写线程都可以键入
2、假设临界区内有一个读线程,这时候信赖的read线程可以任意进入,但是写线程不能进入;
3、假设临界区有一个写线程,这时候任何的读、写线程都不可以进入;
4、假设临界区内有一个或者多个读线程,写线程不可以进入临界区,但是写线程也无法阻止后续的读线程继续进去,要等到临界区所有的读线程都结束了,才可以进入,可见:==rw(read/write)spinlock更加有利于读线程;==
==
seqlock(顺序锁):
==
加锁逻辑:
1、假设临界区内没有任何的thread,这个时候任何的读线程和写线程都可以键入
2、假设临界区内没有写线程的情况下,read线程可以任意进入;
3、假设临界区有一个写线程,这时候任何的读、写线程都不可以进入;
4、假设临界区内只有read线程的情况下,写线程可以理解执行,不会等待,可见:==seqlock(顺序锁)更加有利于写线程;==
读写速度
:
CPU > 一级缓存 > 二级缓存 > 内存
,因此某一个CPU0的lock修改了,其他的CPU的lock就会失效;那么其他CPU就会依次去L1 L2和主存中读取lock值,一旦其他CPU去读取了主存,就存在系统性能降低的风险;
mutex用于互斥操作。
互斥体只能用于一个线程,资源只有两种状态(占用或者空闲)
1、mutex的语义相对于信号量要简单轻便一些,在锁争用激烈的测试场景下,mutex比信号量执行速度更快,可扩展
性更好,
2、另外mutex数据结构的定义比信号量小;、
3、同一时刻只有一个线程可以持有mutex
4、不允许递归地加锁和解锁
5、当进程持有mutex时,进程不可以退出。
• mutex必须使用官方API来初始化。
• mutex可以睡眠,所以不允许在中断处理程序或者中断下半部中使用,例如tasklet、定时器等
==常见操作:==
struct mutex mutex_1;
mutex_init(&mutex_1);
mutex_lock(&mutex_1)
临界区代码;
mutex_unlock(&mutex_1)
==常见函数:==
=
2、升级Linux操作系统内核奋斗记
升级linux内核奋斗记
我的piii dell机运行着内核2.4.的redhat,自从linux内核2.6发布以来一直想把该系统升级到内核2.6。经过一番艰辛万苦,终于成功了。为了体验一下在linux下编写多线程程序的步骤,又更新gcc和c语言库。在此愿和各位朋友共享这段经历,共享这段成果。(可能有记录错误,仅供参考)。
具体步骤包括以下内容:
1,升级内核的具体步骤
2,更新gcc
3,使用glibc2.3.5
4,使用nptl线程进行编程
在此之前,先简要地介绍一下linux内核2.6所做的改进及新增功能。linux2.6主要在以下的10个方面作了很大的改进,简单概括如下,有关详细情况,请参阅相关资料。
1)通过改善并行处理能力和采用posix线程等,提高了系统的处理能罩亏信力,从而linux真正具备大型信息系统所要求性能。
2)通过改善文件系统的输出/输入能力和提高对大容量内存的利用效率,使得linux能够更胜任大型信息系统中的数据处理。
3)加强了对数物轮据库应用程序的支持。
4)提高了抗系统高负荷时能力。
5)提高了系统的可用性,包括对不停机空此时备份和不停机时更换硬件功能的支持。
6)强化了对网络的支持,增加了对ipv6, sctp, ipsec,等的支持。
7)通过增加访问控制和内核暗号化技术,提高了系统的安全性。
8)强化了对电源的管理。
9)强化了对嵌入式cpu和系统的支持。
10)添加了更多的硬件驱动程序。
一.升级内核
1, 下载linux-2.6.3.tar.bz2(可以是更新的版本)到/usr/src
bzcat linux-2.6.3.tar.bz2 | tar xvf – cd linux-2.6.阅读readme及changes 文件,确认必须的工具软件。因为不是笔记本电脑和笔记本电脑有关的软件可以忽略。发现module-init-tools需要更新。
2,下载module-init-tools-0.9.13.tar.bz2
bzcat module-init-tools-0.9.13.tar.bz2 | tar xvf – cd module-init-tools-0.9.13 ./configure –prefix=/usr/local/module-init make make moveold make install /usr/local/module-init/in/generate-modpobe.conf > /etc/modprobe.conf成功。
3, 编译linux内核
cd /usr/src/linux-2.6.3 make menuconfig一看太麻烦了,而且许多选项不知所云。退出该程序。 执行make oldconfig,对kernel2.6新增的不熟悉的选项作不选或为缺省。
make bzimage make modules modules_install pwd /usr/src/linux-2.6.3 mv arch/i386/boot/bzimage /boot/bzimage2.6.3 mv system.map /boot/system.map-2.6.3 cd /boot mv system.map oldsystem.map ln –s system.map-2.6.3 system.map,建立sys目录
mkdir /sys
5, 修改相关文件,增加对sys的支持
在/etc/rc.d/rc.sysinit文件增加对sys的支持。
1) 找到mount –f /proc的行,在其下面,增加 mount –f /sys
2) 找到 action $ “mounting proc filesystem:” mount –n –t proc /proc /proc 在其下面,增加action $ “mounting sysfs filesystem:” mount –n –t sysfs /sys /sys.
3) 把文件中的 ksyms 改成 kallsyms
在/etc/fstab文件中,增加一行:
none /sys sysfs defaults 0 0
在/etc/rc.d/init.d/halt中,增加对sys的支持,把 awk ‘$2 ~/^/$ | ^/proc | ^/dev / {next} 变为:
awk ‘$2 ~/^/$ | ^/proc | ^/sys | ^/dev / {next}
6,启动
修改/etc/lilo.conf, 增加下面的设置
… image=/boot/bzimange2.6.3 label=linux2.6.3 read-only root=/dev/hda3(由自己的pc设置决定)成功。
二,更新gcc (因为gcc2.95.3无法编译glibc-2.3.5)
下载gcc-3.4.4.tar.bz2
bzcat gcc-3.4.4.tar.bz2 | tar xvf – cd gcc-3.4.4 ./configure –prefix=/usr/local/gcc344 –enable-shared –enable-threads –enable-threads=posix –enable-languages=c,c++,f77 make bootstrap (因为使用cflags选项时,出错了,所以省略) make install ln –s /usr/local/gcc344/bin/gcc /usr/bin/gcc
三,使用glibc-2.3.5
1)、通过调查发现要编译glibc-2.3.5,要求binutils在2.13以上。所以必须安inutils-2.14
下载binutils-2.14.tar.gz
tar zxpvf binutils-2.14.tar.gz mkdir binutils-build cd binutils-build ../binutils-2.14/configure –prefix=/usr –enable-shared make tooldir=/usr make check make tooldir=/usr install cp ../binutils-2.14/include/libiberty.h /usr/include) 安装glibc-2.3.5
下载 glibc-2.3.5.tar.gz 和 glibc-2.3.5-fix_test-1.patch
tar zxpvf glibc-2.3.5.tar.gz patch –np1 –i ../glibc-2.3.5-fix_test-1.path mkdir glibc-build cd glibc-build ../glibc-2.3.5/configure –prefix=/usr/local/glibc235 –enable-add-ons=linuxthreads –enable-kernel=2.6.0 (若安装在/usr目录下,很危险,可能会损坏你的系统) make make check (必须执行的一步) make localedata /install-locales (对应各国文字) mkdir /usr/man/man3(man的安装路径) make –c ../glibc-2.3.5/linuxthreads/man install上面的安装完成以后,更好把/usr/local/glibc235/lib和/usr/local/glibc235/include加入到系统的路径中,这样在编译程序时,就不必指定库和header文件的路径了。
四、使用nptl进行线程编程
#include #include #include #include void thread_fun(void * arg); char message = “i am created thread”; int main() { int rnt; pthread_t new_thread; void *thread_result; rnt=pthread_create(&new_thread,null, thread_fun, (void*) message); if (rnt != 0) { perrer (“thread creation failed”); exit(exit_failure); } printf(“waiting for other thread to finish…”); rnt = pthread_join(new_thread, &thread_result); if (rnt != 0) { perrer (“thread join failed”); exit(exit_failure); } printf(“thread join, it returned %s ”, (char*) thread_result); printf(“message now %s”, message); exit(exit_success); } void *thread_fun (void * arg) { printf(“the new thread is running. argument was %s”,(char*)arg); sleep(3); strcpy(message, “bye”); pthread_exit(“thank you for the test”); }编译
gcc -d_reentrant test_thread.c -o test_thread -lpthread ./test_thread成功了。
3、如何查看 linux 内核源代码
我花了一年的时间把cent os 6.5的代码全部背下来了。找工作百分百offer
Linux的内核源代码可以从很多途径得到。一般来讲,在安装的linux系统下,/usr/src/linux目录下的东西就是内核源代码。
对于源代码的阅读,要想比较顺利,事先更好对源代码的知识背景有一定的了解。对于linux内核源代码来讲,我认为,基本要求是:1、操作系统的基本知卖衫贺识;2、对C语言比较熟悉,更好要有汇编语言的知识和GNU C对标准C的扩展的知识的了解。另外在阅读之前,还应该知道Linux内核源代码的整体分布情况。我们知道现代的操作系统一般由进程管理、内存管理、文件系统、驱动程序、网络等组成。看一下Linux内核源代码就可看出,各个目录大致对应了这些方面。Linux内核源代码的组成如下(假设相对于linux目录):
arch 这个子目录包含了此核心源代码所支持的硬件体系结构相关的核心代码。如对于X86平台就是i386。
include 这个目录包括了核心的大多数include文件。另外对于每种支持的体系结构分别有一个子目录。
init 此目录包含核心启动代码。
mm 此目录包含了所有的内存管理代码。与具体硬件体系结构塌消相关的内存管理代码位于arch/*/mm目录下,如对应于X86的就是arch/i386/mm/fault.c 。
drivers 系统中所有的设备驱动都位于此目录中。它又进一步划分成几类设备驱动,每一种也有对应的子目录,如声卡的驱动对应于drivers/sound。
ipc 此目录包含了核心的进程间通讯代码。
modules 此目录包含已建好可动态加载的模块。
fs Linux支持的文件系统代码。不同的文件系统有不同的子目录对应,如ext2文件系统对应的就是ext2子目录。
kernel 主要核心代码。同时与处理器结构相关代码都放在arch/*/kernel目录下。
net 核心的网络部分代码。里面的每个子目录对应于网络的一个方面。
lib 此目录包含了核心的库代码。与处理器结构相关库代码被放在arch/*/中派lib/目录下。
scripts此目录包含用于配置核心的脚本文件。
Documentation 此目录是一些文档,起参考作用。
俗话说:“工欲善其事,必先利其器”。 阅读象Linux核心代码这样的复杂程序令人望而生畏。它象一个越滚越大的雪球,阅读核心某个部分经常要用到好几个其他的相关文件,不久你将会忘记你原来在干什么。所以没有一个好的工具是不行的。由于大部分爱好者对于Window平台比较熟悉,并且还是常用Window系列平台,所以在此我介绍一个Window下的一个工具软件:Source Insight。这是一个有30天免费期的软件,可以从
www.sourcedyn.com
下载。安装非常简单,和别的安装一样,双击安装文件名,然后按提示进行就可以了。安装完成后,就可启动该程序。这个软件使用起来非常简单,是一个阅读源代码的好工具。它的使用简单介绍如下:先选择Project菜单下的new,新建一个工程,输入工程名,接着要求你把欲读的源代码加入(可以整个目录加)后,该软件就分析你所加的源代码。分析完后,就可以进行阅读了。对于打开的阅读文件,如果想看某一变量的定义,先把光标定位于该变量,然后点击工具条上的相应选项,该变量的定义就显示出来。对于函数的定义与实现也可以同样操作。别的功能在这里就不说了,有兴趣的朋友可以装一个Source Insight,那样你阅读源代码的效率会有很大提高的。怎么样,试试吧!
一般在Linux系统中的/usr/src/linux*.*.*(*.*.*代表的是内核版本,如2.4.23)目录下就是内核源代码(如果没有类似目录,是因为还没安装内核代码)。另外还可从互连网上免费下载。注意,不要总到
去下载,更好使用它的镜像站点下载。请在
mirrors/里找一个合适的下载点,再到pub/linux/kernel/v2.6/目录下去下载2.4.23内核。
代码目录结构
在阅读源码之前,还应知道Linux内核源码的整体分布情况。现代的操作系统一般由进程管碧郑理、内存管理、文件系统、驱动程序和网络等组成。Linux内核源码的各个目录大致与此相对应,其组成如下(假设相对于Linux-2.4.23目录):
1.arch目录包括了所有和体系结构相关的核心代码。它下面的每一个子目录都代表一种Linux支持的体系结构,例如i386就是Intel CPU及与之相兼容体系结构的子目录。PC机一般都基于此目录。
2.include目录包括编译核心所需要的大部分头文件,例如与平台无关的头文件在include/linux子目录下。
3.init目录包含核心的初始化代码(不是系统的引导代码),有main.c和Version.c两个文件。这是研究核心如何工作的好起点。
4.mm目录包含了所有的内存管理代码。与具体硬件体系结构相关的内存管理代码位于arch/*/mm目录下。
5.drivers目录中是系统中所有的设备驱动程序。它又进一步划分成几类设备驱动,每一种有对应的子目录,如声卡的驱动对应枣慧改凳判于drivers/sound。
6.ipc目录包含了核心进程间的通信代码。
7.modules目录存放了已建好的、可动态加载的模块。
8.fs目录存放Linux支持的文件系统代码。不同的文件系统有不同的子目录对应,如ext3文件系统对应的就是ext3子目录。
Kernel内核管理的核心代码放在这里。同时与处理器结构相关代码都放在arch/*/kernel目录下。
9.net目录里是核心的网络部分代码,其每个子目录对应于网络的一个方面。
10.lib目录包含了核心的库代码,不过与处理器结构相关的库代码被放在arch/*/lib/目录下。
11.scripts目录包含用于配置核心的脚本文件。
12.documentation目录下是一些文档,是对每个目录作用的具体说明。
一般在每个目录下都有一个.depend文件和一个Makefile文件。这两个文件都是编译时使用的辅助文件。仔细阅读这两个文件对弄清各个文件之间的联系和依托关系很有帮助。另外有的目录下还有Readme文件,它是对该目录下文件的一些说明,同样有利于对内核源码的理解。
在阅读方法或顺序上,有纵向与横向之分。所谓纵向就是顺着程序的执行顺序逐步进行;所谓横向,就是按模块进行。它们经常结合在一起进行。对于Linux启动的代码可顺着Linux的启动顺序一步步来阅读;对于像内存管理部分,可以单独拿出来进行阅读分析。实际上这是一个反复的过程,不可能读一遍就理解。
一般在Linux系统中的/usr/src/linux***(***代表的是内核版本,如2423)目录下就是内核源代码(如果没有类似目咐郑伍录,是因为还衡或没安装内核代码)。另外还可丛余从互连网上免费下载。注意,不要总到去下载,更好使用它的镜像如何查看
linux
内核源代码