linux 内核编译——修改内核版本号

一、实验前提

    下载2.6.19或更新的Linux内核,配置该内核使其支持NTFS,并在新的内核中修改其版本为Linux NameTestKernelx.x.x,其中,Name是你的名字(汉语拼音);x.x.x是新内核的版本号,最后在你的机器上编译安装这个新内核。(参见《RedHat Enterprise Linux 4入门与提高》第20章。)

       注:本机:Windows 10专业版

VM linux Ubuntu 14.04 LTS

               内核:Linux Ubuntu 4.4.0-21-generic

              新内核:Linux Ubuntu 4.10.1最新稳定版本


二、实验步骤与结果

1、获取root权限:sudo passwd root,再输入密码即可;


2、验证gcc的可用:在你自己的工作目录下,编译链接运行Hello World程序;


3、在http://www.kernel.org上下载指定的内核,或者查找更新的稳定版内核并下载之;


4、准备相关工具(在执行下面的make步骤时,会发现系统有确实库文件,以下为本人安装时缺少的文件):

1)缺乏curse.h文件:用apt-get install libncurses5-dev安装

2)缺乏openssl/opensslv.h文件:用apt-get install libssl-dev安装


5、把源代码解压缩至/usr/src中,最终形成/usr/src/linux x.x.x/目录(x.x.x是新内核的版本号);
(提示:这里的注意点是路径的选择,一般要放在/usr/src/linux x.x.x/目录下面,以满足Makefile对路径设置的初始要求)


6、进入源代码的根目录(/usr/src/linux x.x.x),找到合适的内核配置方法,一般情况下默认即可,即弹出界面后选save退出就可以了;


7、修改 /usr/src/linuxx.x.x/include/linux/version.h文件中的版本信息(此处可修改版本号);

1)在终端输入 gedit  /etc/default/grub,编辑grub,注释掉GRUB_HIDDEN_TIMEOUT=0,然后update-grub;

2)在终端中输入 gedir  /boot/grub/grub.cfg,来编辑grub.cfg,找到menuentry ’’中输入自己需要修改后的内容;


8、编译内核。

命令顺序如下:

1)$sudo makemenuconfig

2)$sudo make

3)$sudo makemodules install

4)$sudo make install


9、重新启动新内核: reboot;


<..................................在编译内核中的其他问题请见下一篇文章...........................................>

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
服务器:Windows 2000及IIS5.0以上,需要ADO数据库、FSO、XMLDOM等系统组件支持和空间的读写权限,具体请查询网络服务商或查看本机配置。客户端:支持Mozilla FireFox 1.0、IE6.0、Opear 8.0及更高版本的浏览器。客户端浏览器需要启用JavaScript脚本支持。升级说明:使用1.2-1.6beta版本的用户,将数据库放入1.6版程序的DATA目录中,在设置完c_custom.asp里的ZC_DATABASE_PATH参数和ZC_BLOG_HOST参数后,使用以前的账号登入后台管理界面,在[备份与更新]栏使用[数据库升级]功能,让旧版的数据库升级为最新版的数据库结构,再将需要保留的附件、模板、样式等放入相应的目录即完成了升级。使用说明:1. 上传完程序后在浏览器中打开首页会自动转到向导页,在向导页调置用户名和密码。其中”BLOG的网络地址”格式是'http://aaa.bbb.ccc/',前面要加 http:// ,后面要加上 / 。管理员可以创建比自己权限低的账号,推荐建立一个“高级用户”供日常使用。2.在[网站设置]中更改你的BLOG名称等等,也包括更换CSS界面样式。在设置完成之后请点[文件重建]以让所有的日志页面都生效。3.先在[分类管理]建立一个分类,再到[文章管理]中添加新日志文章。只有管理员才有分类创建或删除的权限。4.可选用UBB编辑器或是可视编辑器新建和修改日志。在文章提交完成之后再次编辑该文件才能向对方的BLOG发送引用。请自行提取正文的文字做为摘要,系统的自动截断功能有可能会使摘要页面显示不正常。5.什么时候需要点击[索引重建]?[索引重建]让系统刷新缓存和统计数据,同时,生成该BLOG的RSS 2.0和Atom 1.0聚合的XML文件于根目录中。每次发表文章、修改分类等操作后需要点击[索引重建]。6.什么时候需要点击[文件重建]?当你在[网站设置]更改了相应的设置,都需要使用“文件重建”以使每个文章页面更改生效。“文件重建”是一个消耗资源与时间的事件,尤其是BLOG中日志数量众多时。7.关于“导航栏”、“友情链接”等条目请在在后台进入[文件管理]页面直接修改源文件。它们的格式都是:布罗格的烘培机也可在INCLUDE目录中修改相应文件的HTML代码。8.如何让日志显示源代码,包括HTML,ASP,PHP等,请用“[ CODE ] [/ CODE ]”或“[CODE_LITE] [/CODE_LITE]”将源程序包含就行了。UBB代码请参考官方论坛上的介绍。9.附件都上传在UPLOAD目录中,只能上传限定类型的文件。请用IE或FireFox上传全ASCII字符名称的文件。在[网站设置]中可以设置上传文件的种类和大小限制。10.如何在日志中引用附件呢?请用以下格式,系统会自动将相对路径替代成绝对路径。xxx[URL=http://upload/abc.jpg]abc.jpg[/URL] 或 [URL=upload/abc.jpg]abc.jpg[/URL]11. 如何在一个站点(域名)内使用两个及以上的Z-Blog(渡虎谷版)程序?进入后台[网站设置]页,将ZC_BLOG_CLSID设置为不同的值即可。12. Z-Blog(渡虎谷版)的XML-RPC功能如何使用?Z-Blog(渡虎谷版)的XML-RPC接口采用MetaWeblog的API,可以在相应软件和网站调用该接口。相应的XMP-RPC接口URL为: http://yourblog/xml-rpc/index.asp13. 如何应对SPAM的侵扰?每隔一段时间(一个月或更长)在后台设置中更改一次ZC_BLOG_CLSID的值。在网站设置里还有关闭评论和引用的设置。或是采用第三方的插件以达到此目的程序改动列表如下:1、修正了一个不符合W3C标准的地方;2、强制过滤所有可视化编辑器提交的正文中的回车换行符;3、调整所有模版文件编码为UTF-8避免乱码;4、c_html_js.asp可批量读写,并修改了模板;5、修改了自动保存对多编辑器的支持;6、修正了数据库更新代码兼容代码中的表blog_Keyword;7、调整了 TArticle类中部分涉及评论引用的代码;8、调整了WAP文本过滤BUG;9、精简了大量WAP内核代码;10、增加了几个UBB代码的支持;
CnCrypt是一款专门为用户打造的磁盘加密软件,同时支持Windows2000-Win 10之间的所有操作系统。主要为用户提供便捷的电脑磁盘加密功能,能创建加密的“虚拟磁盘文件”(类似虚拟光驱,大小可以自定义),所有加密数据都是经过AES等加密算法的运算后的结果,无法破解。CnCrypt提供多种加密算法,包括:AES-256, Blowfish (448-bit key), CAST5, Serpent, Triple DES, and Twofish,其他特性还有支持FAT32和NTFS分区、隐藏卷标、热键启动等。 主要特性 1 所有加密都是以分区为基础的。 2 真加密,所有加密数据都是经过AES等加密算法的运算后的结果,无法破解(穷举法除外)。 3 能创建加密的“虚拟磁盘文件”(类似虚拟光驱,大小可以自定义) 4 加密单个分区或整个硬盘。 5 加密过程自动、实时、透明(使用加密文件或分区前输入密码,载入后就可以像使用一个普通分区一样使用加密分区。) 6 提供两级方案,以应对被强迫说出密码的情况(如抢劫)。 6.1 隐藏分区(覆盖式密码术,steganography) 6.2 无法探测到CnCrypt 加密分区(加密数据会被认为是随机数据) 7 加密算法:AES-256、Serpent、Twofish。为取得更好加密效果,可以同时使用两种或三种加密算法。操作模式:XTS。 8 多样化的身份认证 8.1支持通常使用的密码认证; 8.2支持密匙文件认证,通过指定的文件作为密匙对数据加密。(密匙文件支持:任何类型的文件)电脑上那么多文件,要是想尝试暴利破解,就等着累死吧。 8.3支持PKCS 11运行库,可以使用硬件口令卡(例如:U盾)进行加密认证。密钥随身携带,从而再次提高了数据的安全性,以此实现更高规格的防暴力破解。 CnCrypt V1.11 修改记录 实现单文件绿色版本,包括安装,创建,加载功能 修正V1.10中存在的一些细节BUG 密钥文件按钮上显示当前密钥文件个数 某些Windows错误弹窗为空白,无法获取到错误信息描述 菜单增加关联资源管理器,取消关联资源管理器选项 资源管理器菜单修改为子菜单方式 属性中增加占用磁盘空间项,可以显示动态卷目前已经占用的磁盘空间 在加密卷右键菜单上增加了创建桌面快捷方式菜单项 Mount命令行增加盘符被占用时自运选择空闲盘符选项,可与指定盘符功能一块用,例如 "/letter X: /letter auto" 增加快速创建加密卷(一键创建加密卷) 便携版本配置文件目录移动到用户数据目录(之前为程序目录) 增加文件日期修改工具 增加加密卷占用磁盘空间压缩功能 CnCrypt V1.10 修改记录 增加加密卷空间扩充工具 恢复了TrueCrypt原有系统加密功能 修正了TrueCrypt安全审计团队审计发现的几个BUG 当有子窗口时用快捷键退出存在的BUG WIN7之后系统修改显示密码选项后*号显示不一样的问题 对多处界面显示进行了修正 创建新加密卷时‘选择文件’按钮修改为‘指定文件’。 文件浏览窗口为非保存模式时,修改指定文件必须存在。 设备浏览窗口中分区前面加了若干空格来区分磁盘和卷。 Format和Mount的历史记录可以实时同步 挂载盘符时可以使用A和B盘符 盘符列表右键菜单增加了‘打开文件所在位置’功能 增加了检查更新功能,该功能不会自动连接网络,除非用户手动进行操作。 收藏加密卷中存在同样加密卷时进行提醒 对主菜单布局进行了调整 对中文进行了更好的优化 增加了CnCrypt加密方式,同时继续兼容TrueCrypt加密方式 对磁盘大小输入框进行输入验证 自动加载所有设备加密卷时,跳过对系统所在磁盘和系统分区的检测,节省一定时间。 密钥文件按钮上显示当前密钥文件个数 CnCrypt V1.00 修改记录 基于TrueCrypt7.1a的主要修改 完美支持win2000-win10的所有32位和64位版本。 增加了便携磁盘加密卷创建和加载功能(不会出现“未格式化”的提示) 增加了与Windows资源管理器的集成(加载加密卷,保存至加密卷,粉碎选择文件) 去除了有关系统盘\系统驱动器部分(UEFI之后已无法支持之前实现方式) 增加加密卷擦除功能 增加密码生成器功能 增加了密码输入软键盘功能 增加了磁盘痕迹擦除工具 增加了悬浮框,支持拖放加载,右键功能菜单等。 托盘菜单支持快速加载,支持加载历史记录,加载收藏卷等功能。 加密卷创建向导增加了向导步聚显示 界面细节的诸多优化 内核驱动一些BUG的处理 安装包体积缩小至1.67M,便携压缩包缩小至0.9M 界面完美支持中文 界面使用了操作系统风格 在界面中增加了Banner 对加密卷收藏夹界面进行较大修改 对语言选择界面进行较大
其中包含 AccessChk 为了确保创建安全的环境,Windows 管理员通常需要了解特定用户或用户组对文件、目录、注册表项和 Windows 服务等资源具有哪种访问权限。AccessChk 能够通过直观的界面和输出快速回答这些问题。 AccessEnum 这一简单但强大的安全工具可以向您显示,谁可以用何种访问权限访问您系统中的目录、文件和注册表项。使用此工具可查找权限漏洞。 AdExplorer Active Directory Explorer 是一个高级的 Active Directory (AD) 查看器和编辑器。 AdInsight 一种 LDAP(轻型目录访问协议)实时监视工具,旨在对 Active Directory 客户端应用程序进行故障排除。 AdRestore 恢复已删除的 Server 2003 Active Directory 对象。 Autologon 登录过程中跳过密码屏幕。 Autoruns 查看哪些程序被配置为在系统启动和您登录时自动启动。Autoruns 还能够完整列出应用程序可以配置自动启动设置的注册表和文件位置。 BgInfo 此完全可配置程序会自动生成桌面背景,其中包含有关系统的 IP 地址、计算机名称、网络适配器及更多内容的重要信息。 BlueScreen 此屏幕保护程序不仅精确模拟“蓝屏”,而且也模拟重新启动(完成 CHKDSK),并可在 Windows NT 4、Windows 2000、Windows XP、Server 2003 和 Windows 9x 上工作。 CacheSet CacheSet 是一个允许您利用 NT 提供的功能来控制缓存管理器的工作集大小的程序。它与 NT 的所有版本都兼容。 ClockRes 查看系统时钟的分辨率,亦即计时器最大分辨率。 Contig 您是否希望迅速对您频繁使用的文件进行碎片整理?使用 Contig 优化单个的文件,或者创建连续的新文件。 Coreinfo Coreinfo 是一个新的命令行实用工具,可向您显示逻辑处理器与物理处理器之间的映射、NUMA 节点和它们所处的插槽,以及分配给每个逻辑处理器的缓存。 Ctrl2cap 这是一个内核模式的驱动程序,可在键盘类驱动程序上演示键盘输入过滤,以便将 Caps-Lock 转变为控制键。在此级别过滤允许在 NT 刚好要“看到”键之前变换和隐藏键。Ctrl2cap 还显示如何使用 NtDisplayString() 打印初始化蓝屏的消息。 DebugView Sysinternals 的另一个优先程序:此程序截取设备驱动程序对 DbgPrint 的调用和 Win32 程序生成的 OutputDebugString。它允许在不使用活动的调试器的情况下,在本地计算机上或通过 Internet 查看和记录调试会话输出。 Desktops 使用这一新的实用工具可以创建最多四个虚拟桌面,使用任务栏界面或热键预览每个桌面上的内容并在这些桌面之间轻松地进行切换。 Disk2vhd Disk2vhd 可简化从物理系统到虚拟机 (p2v) 的迁移。 DiskExt 显示卷磁盘映射。 Diskmon 此实用工具会捕捉所有硬盘活动,或者在您的系统任务栏中象软件磁盘活动灯一样工作。 DiskView 图形磁盘扇区实用工具。 Disk Usage (DU) 按目录查看磁盘使用情况。 EFSDump 查看加密文件的信息。 Handle 此易用命令行实用工具将显示哪些进程打开了哪些文件,以及更多其他信息。 Hex2dec 将十六进制数字转换为十进制及反向转换。 接合点 创建 Win2K NTFS 符号链接。 LDMDump 转储逻辑磁盘管理器在磁盘上的数据库内容,其中说明了 Windows 2000 动态磁盘的分区情况。 ListDLLs 列出所有当前加载的 DLL,包括加载位置及其版本号。2.0 版将打印已加载模块的完整路径名。 LiveKd 使用 Microsoft 内核调试程序检查真实系统。 LoadOrder 查看设备加载到 WinNT/2K 系统中的顺序。 LogonSessions 列出系统中的活动登录会话。 MoveFile 使您可以安排在系统下一次重新启动时执行移动和删除命令。 NTFSInfo 用 NTFSInfo 可以查看有关 NTFS 卷的详细信息,包括主文件表 (MFT) 和 MFT 区的大小和位置,以及 NTFS 元数据文件的大小。 PageDefrag 对您的分页文件和注册表配置单元进行碎片整理。 PendMoves 枚举在系统下一次启动时所要执行的文件重命名和删除命令的列表。 PipeList 显示系统上的命名管道,包括每个管道的最大实例数和活动实例数。 PortMon 通过高级监视工具监视串行端口和并行端口的活动。它能识别所有的标准串行和并行 IOCTL,甚至可以显示部分正在发送和接收的数据。3.x 版具有强大的新 UI 增强功能和高级筛选功能。 ProcDump 这一新的命令行实用工具旨在捕获其他方式难以隔离和重现 CPU 峰值的进程转储。该工具还可用作用于创建进程转储的一般实用工具,并可以在进程具有挂起的窗口或未处理的异常时监视和生成进程转储。 Process Explorer 找出进程打开了哪些文件、注册表项和其他对象以及已加载哪些 DLL 等信息。这个功能异常强大的实用工具甚至可以显示每个进程的所有者。 Process Monitor 实时监视文件系统、注册表、进程、线程和 DLL 活动。 ProcFeatures 这一小程序会报告处理器和 Windows 对“物理地址扩展”和“无执行”缓冲区溢出保护的支持情况。 PsExec 在远程系统上执行进程。 PsFile 查看远程打开的文件。 PsGetSid 显示计算机或用户的 SID。 PsInfo 获取有关系统的信息。 PsKill v1.13(2009 年 12 月 1 日) 终止本地或远程进程。 PsList 显示有关进程和线程的信息。 PsLoggedOn 显示登录到某个系统的用户。 PsLogList 转储事件日志记录。 PsPasswd 更改帐户密码。 PsService 查看和控制服务。 PsShutdown 关闭并重新启动(可选)计算机。 PsSuspend 挂起和继续进程。 PsTools PsTools 套件包括一些命令行程序,可列出本地或远程计算机上运行的进程、远程运行进程、重新启动计算机、转储事件日志,以及执行其他任务。 RegDelNull 扫描并删除包含嵌入空字符的注册表项,标准注册表编辑工具不能删除这种注册表项。 RegJump 跳至 Regedit 中指定的注册表路径。 RootkitRevealer 扫描系统以找出基于 Rootkit 的恶意软件。 SDelete 安全地覆盖敏感文件,并使用此符合 DoD 的安全删除程序清理先前删除文件所在的可用空间。 ShareEnum 扫描网络上的文件共享并查看其安全设置,以关闭安全漏洞。 ShellRunas 通过方便的 shell 上下文菜单项,作为另一个用户启动程序。 Sigcheck 转储文件版本信息并检查系统中的映像是否已进行数字签名。 Streams 显示 NTFS 备用数据流。 Strings 在二进制映像中搜索 ANSI 和 UNICODE 字符串。 Sync 将缓存数据刷新到磁盘。 TCPView 活动套接字命令行查看器。 VMMap VMMap 是进程虚拟和物理内存分析实用工具。 VolumeId 设置 FAT 或 NTFS 驱动器的卷 ID。 Whois 查看 Internet 地址的所有者。 WinObj 基本对象管理器命名空间查看器。 ZoomIt 在屏幕上进行缩放和绘图的演示实用工具。
目录树 下面再给个样例 ├─Makefile │ ├─boot │ bootsect.s │ head.s │ setup.s │ ├─fs │ bitmap.c │ block_dev.c │ buffer.c │ char_dev.c │ exec.c │ fcntl.c │ file_dev.c │ file_table.c │ inode.c │ ioctl.c │ Makefile │ namei.c │ open.c │ pipe.c │ read_write.c │ stat.c │ super.c │ truncate.c │ ├─include │ │ a.out.h │ │ const.h │ │ ctype.h │ │ errno.h │ │ fcntl.h │ │ signal.h │ │ stdarg.h │ │ stddef.h │ │ string.h │ │ termios.h │ │ time.h │ │ unistd.h │ │ utime.h │ │ │ ├─asm │ │ io.h │ │ memory.h │ │ segment.h │ │ system.h │ │ │ ├─linux │ │ config.h │ │ fs.h │ │ hdreg.h │ │ head.h │ │ kernel.h │ │ mm.h │ │ sched.h │ │ sys.h │ │ tty.h │ │ │ └─sys │ stat.h │ times.h │ types.h │ utsname.h │ wait.h │ ├─init │ main.c │ ├─kernel │ │ asm.s │ │ exit.c │ │ fork.c │ │ mktime.c │ │ panic.c │ │ printk.c │ │ sched.c │ │ signal.c │ │ sys.c │ │ system_call.s │ │ vsprintf.c │ │ │ ├─blk_drv │ │ blk.h │ │ floppy.c │ │ hd.c │ │ ll_rw_blk.c │ │ Makefile │ │ ramdisk.c │ │ │ ├─chr_drv │ │ console.c │ │ keyboard.S │ │ Makefile │ │ rs_io.s │ │ serial.c │ │ tty_io.c │ │ tty_ioctl.c │ │ │ └─math │ Makefile │ math_emulate. │ ├─lib │ close.c │ ctype.c │ dup.c │ errno.c │ execve.c │ Makefile │ malloc.c │ open.c │ setsid.c │ string.c │ wait.c │ write.c │ _exit.c │ ├─mm │ Makefile │ memory.c │ page.s │ └─tools build.c 样例 main。c 用sourceinsight软件阅读 很方便 /* * linux/init/main.c * * (C) 1991 Linus Torvalds */ #define __LIBRARY__ // 定义该变量是为了包括定义在unistd.h 中的内嵌汇编代码等信息。 #include // *.h 头文件所在的默认目录是include/,则在代码中就不用明确指明位置。 // 如果不是UNIX 的标准头文件,则需要指明所在的目录,并用双引号括住。 // 标准符号常数与类型文件。定义了各种符号常数和类型,并申明了各种函数。 // 如果定义了__LIBRARY__,则还包括系统调用号和内嵌汇编代码_syscall0()等。 #include // 时间类型头文件。其中最主要定义了tm 结构和一些有关时间的函数原形。 /* * we need this inline - forking from kernel space will result * in NO COPY ON WRITE (!!!), until an execve is executed. This * is no problem, but for the stack. This is handled by not letting * main() use the stack at all after fork(). Thus, no function * calls - which means inline code for fork too, as otherwise we * would use the stack upon exit from 'fork()'. * * Actually only pause and fork are needed inline, so that there * won't be any messing with the stack from main(), but we define * some others too. */ /* * 我们需要下面这些内嵌语句 - 从内核空间创建进程(forking)将导致没有写时复制(COPY ON WRITE)!!! * 直到一个执行execve 调用。这对堆栈可能带来问题。处理的方法是在fork()调用之后不让main()使用 * 任何堆栈。因此就不能有函数调用 - 这意味着fork 也要使用内嵌的代码,否则我们在从fork()退出 * 时就要使用堆栈了。 * 实际上只有pause 和fork 需要使用内嵌方式,以保证从main()中不会弄乱堆栈,但是我们同时还 * 定义了其它一些函数。 */ static inline _syscall0 (int, fork) // 是unistd.h 中的内嵌宏代码。以嵌入汇编的形式调用 // Linux 的系统调用中断0x80。该中断是所有系统调用的 // 入口。该条语句实际上是int fork()创建进程系统调用。 // syscall0 名称中最后的0 表示无参数,1 表示1 个参数。 static inline _syscall0 (int, pause) // int pause()系统调用:暂停进程的执行,直到 // 收到一个信号。 static inline _syscall1 (int, setup, void *, BIOS) // int setup(void * BIOS)系统调用,仅用于 // linux 初始化(仅在这个程序中被调用)。 static inline _syscall0 (int, sync) // int sync()系统调用:更新文件系统。 #include // tty 头文件,定义了有关tty_io,串行通信方面的参数、常数。 #include // 调度程序头文件,定义了任务结构task_struct、第1 个初始任务 // 的数据。还有一些以宏的形式定义的有关描述符参数设置和获取的 // 嵌入式汇编函数程序。 #include // head 头文件,定义了段描述符的简单结构,和几个选择符常量。 #include // 系统头文件。以宏的形式定义了许多有关设置或修改 // 描述符/中断门等的嵌入式汇编子程序。 #include // io 头文件。以宏的嵌入汇编程序形式定义对io 端口操作的函数。 #include // 标准定义头文件。定义了NULL, offsetof(TYPE, MEMBER)。 #include // 标准参数头文件。以宏的形式定义变量参数列表。主要说明了-个 // 类型(va_list)和三个宏(va_start, va_arg 和va_end),vsprintf、 // vprintf、vfprintf。 #include #include // 文件控制头文件。用于文件及其描述符的操作控制常数符号的定义。 #include // 类型头文件。定义了基本的系统数据类型。 #include // 文件系统头文件。定义文件表结构(file,buffer_head,m_inode 等)。 static char printbuf[1024]; // 静态字符串数组。 extern int vsprintf (); // 送格式化输出到一字符串中(在kernel/vsprintf.c,92 行)。 extern void init (void); // 函数原形,初始化(在168 行)。 extern void blk_dev_init (void); // 块设备初始化子程序(kernel/blk_drv/ll_rw_blk.c,157 行) extern void chr_dev_init (void); // 字符设备初始化(kernel/chr_drv/tty_io.c, 347 行) extern void hd_init (void); // 硬盘初始化程序(kernel/blk_drv/hd.c, 343 行) extern void floppy_init (void); // 软驱初始化程序(kernel/blk_drv/floppy.c, 457 行) extern void mem_init (long start, long end); // 内存管理初始化(mm/memory.c, 399 行) extern long rd_init (long mem_start, int length); //虚拟盘初始化(kernel/blk_drv/ramdisk.c,52) extern long kernel_mktime (struct tm *tm); // 建立内核时间(秒)。 extern long startup_time; // 内核启动时间(开机时间)(秒)。 /* * This is set up by the setup-routine at boot-time */ /* * 以下这些数据是由setup.s 程序在引导时间设置的(参见第2 章2.3.1 节中的表2.1)。 */ #define EXT_MEM_K (*(unsigned short *)0x90002) // 1M 以后的扩展内存大小(KB)。 #define DRIVE_INFO (*(struct drive_info *)0x90080) // 硬盘参数表基址。 #define ORIG_ROOT_DEV (*(unsigned short *)0x901FC) // 根文件系统所在设备号。 /* * Yeah, yeah, it's ugly, but I cannot find how to do this correctly * and this seems to work. I anybody has more info on the real-time * clock I'd be interested. Most of this was trial and error, and some * bios-listing reading. Urghh. */ /* * 是啊,是啊,下面这段程序很差劲,但我不知道如何正确地实现,而且好象它还能运行。如果有 * 关于实时时钟更多的资料,那我很感兴趣。这些都是试探出来的,以及看了一些bios 程序,呵! */ #define CMOS_READ(addr) ({ \ // 这段宏读取CMOS 实时时钟信息。 outb_p (0x80 | addr, 0x70); \ // 0x70 是写端口号,0x80|addr 是要读取的CMOS 内存地址。 inb_p (0x71); \ // 0x71 是读端口号。 } ) #define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10) // 将BCD 码转换成数字。 static void time_init (void) // 该子程序取CMOS 时钟,并设置开机时间??startup_time(秒)。 { struct tm time; do { time.tm_sec = CMOS_READ (0); // 参见后面CMOS 内存列表。 time.tm_min = CMOS_READ (2); time.tm_hour = CMOS_READ (4); time.tm_mday = CMOS_READ (7); time.tm_mon = CMOS_READ (8); time.tm_year = CMOS_READ (9); } while (time.tm_sec != CMOS_READ (0)); BCD_TO_BIN (time.tm_sec); BCD_TO_BIN (time.tm_min); BCD_TO_BIN (time.tm_hour); BCD_TO_BIN (time.tm_mday); BCD_TO_BIN (time.tm_mon); BCD_TO_BIN (time.tm_year); time.tm_mon--; startup_time = kernel_mktime (&time); } static long memory_end = 0; // 机器具有的内存(字节数)。 static long buffer_memory_end = 0; // 高速缓冲区末端地址。 static long main_memory_start = 0; // 主内存(将用于分页)开始的位置。 struct drive_info { char dummy[32]; } drive_info; // 用于存放硬盘参数表信息。 void main (void) /* This really IS void, no error here. */ { /* The startup routine assumes (well, ...) this */ /* 这里确实是void,并没错。在startup 程序(head.s)中就是这样假设的。 */ // 参见head.s 程序第136 行开始的几行代码。 /* * Interrupts are still disabled. Do necessary setups, then * enable them */ /* * 此时中断仍被禁止着,做完必要的设置后就将其开启。 */ // 下面这段代码用于保存: // 根设备号 ??ROOT_DEV; 高速缓存末端地址??buffer_memory_end; // 机器内存数??memory_end;主内存开始地址 ??main_memory_start; ROOT_DEV = ORIG_ROOT_DEV; drive_info = DRIVE_INFO; memory_end = (1 << 20) + (EXT_MEM_K < 16 * 1024 * 1024) // 如果内存超过16Mb,则按16Mb 计。 memory_end = 16 * 1024 * 1024; if (memory_end > 12 * 1024 * 1024) // 如果内存>12Mb,则设置缓冲区末端=4Mb buffer_memory_end = 4 * 1024 * 1024; else if (memory_end > 6 * 1024 * 1024) // 否则如果内存>6Mb,则设置缓冲区末端=2Mb buffer_memory_end = 2 * 1024 * 1024; else buffer_memory_end = 1 * 1024 * 1024; // 否则则设置缓冲区末端=1Mb main_memory_start = buffer_memory_end; // 主内存起始位置=缓冲区末端; #ifdef RAMDISK // 如果定义了虚拟盘,则主内存将减少。 main_memory_start += rd_init (main_memory_start, RAMDISK * 1024); #endif // 以下是内核进行所有方面的初始化工作。阅读时最好跟着调用的程序深入进去看,实在看 // 不下去了,就先放一放,看下一个初始化调用 -- 这是经验之谈?。 mem_init (main_memory_start, memory_end); trap_init (); // 陷阱门(硬件中断向量)初始化。(kernel/traps.c,181 行) blk_dev_init (); // 块设备初始化。 (kernel/blk_dev/ll_rw_blk.c,157 行) chr_dev_init (); // 字符设备初始化。 (kernel/chr_dev/tty_io.c,347 行) tty_init (); // tty 初始化。 (kernel/chr_dev/tty_io.c,105 行) time_init (); // 设置开机启动时间??startup_time(见76 行)。 sched_init (); // 调度程序初始化(加载了任务0 的tr, ldtr) (kernel/sched.c,385) buffer_init (buffer_memory_end); // 缓冲管理初始化,建内存链表等。(fs/buffer.c,348) hd_init (); // 硬盘初始化。 (kernel/blk_dev/hd.c,343 行) floppy_init (); // 软驱初始化。 (kernel/blk_dev/floppy.c,457 行) sti (); // 所有初始化工作都做完了,开启中断。 // 下面过程通过在堆栈中设置的参数,利用中断返回指令切换到任务0。 move_to_user_mode (); // 移到用户模式。 (include/asm/system.h,第1 行) if (!fork ()) { /* we count on this going ok */ init (); } /* * NOTE!! For any other task 'pause()' would mean we have to get a * signal to awaken, but task0 is the sole exception (see 'schedule()') * as task 0 gets activated at every idle moment (when no other tasks * can run). For task0 'pause()' just means we go check if some other * task can run, and if not we return here. */ /* 注意!! 对于任何其它的任务,'pause()'将意味着我们必须等待收到一个信号才会返 * 回就绪运行态,但任务0(task0)是唯一的意外情况(参见'schedule()'),因为任务0 在 * 任何空闲时间里都会被激活(当没有其它任务在运行时),因此对于任务0'pause()'仅意味着 * 我们返回来查看是否有其它任务可以运行,如果没有的话我们就回到这里,一直循环执行'pause()'。 */ for (;;) pause (); } static int printf (const char *fmt, ...) // 产生格式化信息并输出到标准输出设备stdout(1),这里是指屏幕上显示。参数'*fmt'指定输出将 // 采用的格式,参见各种标准C 语言书籍。该子程序正好是vsprintf 如何使用的一个例子。 // 该程序使用vsprintf()将格式化的字符串放入printbuf 缓冲区,然后用write()将缓冲区的内容 // 输出到标准设备(1--stdout)。 { va_list args; int i; va_start (args, fmt); write (1, printbuf, i = vsprintf (printbuf, fmt, args)); va_end (args); return i; } static char *argv_rc[] = { "/bin/sh", NULL}; // 调用执行程序时参数的字符串数组。 static char *envp_rc[] = { "HOME=/", NULL}; // 调用执行程序时的环境字符串数组。 static char *argv[] = { "-/bin/sh", NULL}; // 同上。 static char *envp[] = { "HOME=/usr/root", NULL}; void init (void) { int pid, i; // 读取硬盘参数包括分区表信息并建立虚拟盘和安装根文件系统设备。 // 该函数是在25 行上的宏定义的,对应函数是sys_setup(),在kernel/blk_drv/hd.c,71 行。 setup ((void *) &drive_info); (void) open ("/dev/tty0", O_RDWR, 0); // 用读写访问方式打开设备“/dev/tty0”, // 这里对应终端控制台。 // 返回的句柄号0 -- stdin 标准输入设备。 (void) dup (0); // 复制句柄,产生句柄1 号 -- stdout 标准输出设备。 (void) dup (0); // 复制句柄,产生句柄2 号 -- stderr 标准出错输出设备。 printf ("%d buffers = %d bytes buffer space\n\r", NR_BUFFERS, NR_BUFFERS * BLOCK_SIZE); // 打印缓冲区块数和总字节数,每块1024 字节。 printf ("Free mem: %d bytes\n\r", memory_end - main_memory_start); //空闲内存字节数。 // 下面fork()用于创建一个子进程(子任务)。对于被创建的子进程,fork()将返回0 值, // 对于原(父进程)将返回子进程的进程号。所以180-184 句是子进程执行的内容。该子进程 // 关闭了句柄0(stdin),以只读方式打开/etc/rc 文件,并执行/bin/sh 程序,所带参数和 // 环境变量分别由argv_rc 和envp_rc 数组给出。参见后面的描述。 if (!(pid = fork ())) { close (0); if (open ("/etc/rc", O_RDONLY, 0)) _exit (1); // 如果打开文件失败,则退出(/lib/_exit.c,10)。 execve ("/bin/sh", argv_rc, envp_rc); // 装入/bin/sh 程序并执行。 _exit (2); // 若execve()执行失败则退出(出错码2,“文件或目录不存在”)。 } // 下面是父进程执行的语句。wait()是等待子进程停止或终止,其返回值应是子进程的进程号(pid)。 // 这三句的作用是父进程等待子进程的结束。&i 是存放返回状态信息的位置。如果wait()返回值不 // 等于子进程号,则继续等待。 if (pid > 0) while (pid != wait (&i)) /* nothing */ ; // 如果执行到这里,说明刚创建的子进程的执行已停止或终止了。下面循环中首先再创建一个子进程, // 如果出错,则显示“初始化程序创建子进程失败”的信息并继续执行。对于所创建的子进程关闭所有 // 以前还遗留的句柄(stdin, stdout, stderr),新创建一个会话并设置进程组号,然后重新打开 // /dev/tty0 作为stdin,并复制成stdout 和stderr。再次执行系统解释程序/bin/sh。但这次执行所 // 选用的参数和环境数组另选了一套(见上面165-167 行)。然后父进程再次运行wait()等待。如果 // 子进程又停止了执行,则在标准输出上显示出错信息“子进程pid 停止了运行,返回码是i”,然后 // 继续重试下去…,形成“大”死循环。 while (1) { if ((pid = fork ()) < 0) { printf ("Fork failed in init\r\n"); continue; } if (!pid) { close (0); close (1); close (2); setsid (); (void) open ("/dev/tty0", O_RDWR, 0); (void) dup (0); (void) dup (0); _exit (execve ("/bin/sh", argv, envp)); } while (1) if (pid == wait (&i)) break; printf ("\n\rchild %d died with code %04x\n\r", pid, i); sync (); } _exit (0); /* NOTE! _exit, not exit() */ }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

c_zyer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值