网易云课堂学习

可执行程序的装载

可执行程序的产生过程:预处理-----> 编译 ----> 汇编 ----> 链接

以hello.c文件为例进行分析,编译步骤如下


vi hello.c
gcc -E -o hello.cpp hello.c -m32
vi hello.cpp
gcc -x cpp-outout -S -o hello.s hello.cpp -m32
vi hello.s
gcc -x assembler -c hello.s -o hello.o -m32
vi hello.o
gcc -o hello hello.o -m32
vi hello
gcc -o hello.static hello.o -m32 -static

结果如下图





编程使用exec*库函数加载一个可执行文件.

静态链接和动态链接的区别

动态库链接时,会在运行时选择需要的部分进行编译,生成的可执行文件会比较小,而且容易后续的更新。静态编译会把所有的函数等都嵌入到可执行文件中,可以直接在任何电脑上直接运行.在静态连接程序中,所有的程序代码包好在一个可执行模块中。因为库程序静态连接到应用程序中,库的引用效率更高。静态连接增加应用程序文件的大小,如果系统同时还运行其他的应用程序时,静态连接也会增加内存中代码的大小。

加载方式上:

1.静态库只能使用静态加载方式,静态加载就是编译、链接的时候把静态库代码拷贝到程序中。

2.动态库可以使用“静态加载”和“动态加载”,静态加载就是在程序启动的时候把库所有的内容加载到内存,动态加载就是用到哪个函数所在的模块就加载对应的库就行。(这是因为,动态库可能也很大,一口气全部加载也是非常耗时,所以运行时用到谁就加载谁,就是动态加载)。

静态库、共享库以及动态加载库

(1) 静态库

静态库是一些目标文件的集合,库文件以”.a”结尾,连接器会将应用程序所需要用到的代码拷贝到应用程序中.

静态库的优缺点:

静态库增加了应用程序的大小,另外在处理静态库更新问题上需要花费更多的重编译代价(recompile),但是理论上,静态库应该比共享库或者动态加载库运行更快(1-5%),因为它减少了在程序运行才去加载库的开销。

(2) 共享库:

与静态库不同的是,共享库在链接阶段并不需要拷贝所需使用的代码,而只是做些参考标记,然后在程序启动时加载所需要的库文件,因此,对比静态库,链接共享库的应用程序小得多。

共享库的优缺点:

对比静态库,共享库在链接阶段只是对所需代码做些标识,在程序启动时才会加载,这样减少了目标应用程序的大小,通过soname,可以做到多版本的兼容,这样每次升级也不需要将原代码全部重新编译,免除了在升级过程中重编译带来的开销;但是,因为需要在程序运行阶段加载共享库,这样势必需要付出运行期间的库加载代价。

(3)动态加载库 (Dynamically loaded libraries)

是指在程序运行过程中可以加载的函数库,而不像共享库是在程序启动的时候加载。DLL对实现插件和模块非常实用,因为它们运行程序在允许时等待插件的加载,动态加载库有自己的一套API接口去完成打开、查找符号,处理出错、关闭加载库等功能。

进程的切换和系统的一般执行过程

不同类型的进程有不同的调度需求

第一种分类:

(1)I/O-bound

  • 频繁的进行I/O
  • 通常会话费很多时间等待I/O操作完成

    (2)CPU-bound
  • 计算密集型
  • 需要大量的CPU时间进行运算
第二种分类:

(1)批处理进程

  • 不必与用户交互,通常在后台运行
  • 不必很快响应
  • 典型的批处理程序:编译程序、科学计算

    (2)实时进程
  • 有实时需求,不必被低优先级的进程阻塞
  • 响应时间要短、要稳定
  • 典型实时进程:视频/音频、机械控制等

    (3)交互式进程
  • 需要经常与用户交互,因此要花很多时间等待用户输入操作
  • 相应时间要快,平均延迟要低于50-150ms
  • 典型的交互式进程:shell、文本编辑程序、图形应用程序等

进程调度算法

(1)先进先出算法:

算法总是把处理机分配给最先进入就绪队列的进程,一个进程一旦分得处理机,便一直执行下去,直到该进程完成或阻塞时,才释放处理机。

(2)短进程优先

最短CPU运行期优先调度算法(SCBF--Shortest CPU Burst First)

该算法虽可获得较好的调度性能,但难以准确地知道下一个CPU执行期,而只能根据每一个进程的执行历史来预测。

(3)轮转法:

前几种算法主要用于批处理系统中,不能作为分时系统中的主调度算法,在分时系统中,都采用时间片轮转法。

简单轮转法:系统将所有就绪进程按FIFO规则排队,按一定的时间间隔把处理机分配给队列中的进程。这样,就绪队列中所有进程均可获得一个时间片的处理机而运行。

多级队列方法:将系统中所有进程分成若干类,每类为一级。

(4)多级反馈队列

多级反馈队列方式是在系统中设置多个就绪队列,并赋予各队列以不同的优先权。

Linux中进程的优先级是动态的,较长时间未分配到CPU的进程,优先级会升高;已经在CPU上运行了较长时间的进程,优先级会下降。

进程的调度时机与进程的切换


操作系统原理中介绍了大量进程调度算法,这些算法从实现的角度看仅仅是从运行队列中选择一个新进程,选择的过程中运用了不同的策略而已。 对于理解操作系统的工作机制,反而是进程的调度时机与进程的切换机制更为关键。

进程调度的时机

  • 中断处理过程(包括时钟中断、I/O中断、系统调用和异常)中,直接调用schedule(),或者返回用户态时根据need_resched标记调用schedule();
  • 内核线程(特殊的进程,只有内核态没有用户态)可以直接调用schedule()进行进程切换,也可以在中断处理过程中进行调度,也就是说内核线程作为一类的特殊的进程可以主动调度,也可以被动调度;
  • 用户态进程无法实现主动调度,仅能通过陷入内核态后的某个时机点进行调度,即在中断处理过程中进行调度。

进程的切换

  • 为了控制进程的执行,内核必须有能力挂起正在CPU上执行的进程,并恢复以前挂起的某个进程的执行,这叫做进程切换、任务切换、上下文切换;
  • 挂起正在CPU上执行的进程,与中断时保存现场是不同的,中断前后是在同一个进程上下文中,只是由用户态转向内核态执行;
  • 进程上下文包含了进程执行需要的所有信息
  • 用户地址空间:包括程序代码,数据,用户堆栈等
  • 控制信息:进程描述符,内核堆栈等
  • 硬件上下文(注意中断也要保存硬件上下文只是保存的方法不同)
  • schedule()函数选择一个新的进程来运行,并调用context_switch进行上下文的切换,这个宏调用switch_to来进行关键上下文切换
  • next = pick_next_task(rq, prev);//进程调度算法都封装这个函数内部
  • context_switch(rq, prev, next);//进程上下文切换
  • switch_to利用了prev和next两个参数:prev指向当前进程,next指向被调度的进程

使用gdb跟踪调用schedule函数

在time系统调用返回前,调用schedule(),在schedule设置断点:

Linux系统的一般执行过程

最一般的情况:正在运行的用户态进程X切换到运行用户态进程Y的过程

  1. 正在运行的用户态进程X
  2. 发生中断——save cs:eip/esp/eflags(current) to kernel stack,then load cs:eip(entry of a specific ISR) and ss:esp(point to kernel stack).
  3. SAVE_ALL //保存现场
  4. 中断处理过程中或中断返回前调用了schedule(),其中的switch_to做了关键的进程上下文切换
  5. 标号1之后开始运行用户态进程Y(这里Y曾经通过以上步骤被切换出去过因此可以从标号1继续执行)
  6. restore_all //恢复现场
  7. iret - pop cs:eip/ss:esp/eflags from kernel stack
  8. 继续运行用户态进程Y

几种特殊情况

  • 通过中断处理过程中的调度时机,用户态进程与内核线程之间互相切换和内核线程之间互相切换,与最一般的情况非常类似,只是内核线程运行过程中发生中断没有进程用户态和内核态的转换;
  • 内核线程主动调用schedule(),只有进程上下文的切换,没有发生中断上下文的切换,与最一般的情况略简略;
  • 创建子进程的系统调用在子进程中的执行起点及返回用户态,如fork;
  • 加载一个新的可执行程序后返回到用户态的情况,如execve;

虚拟文件系统

虚拟文件系统中(VFS)有四个主要的对象类型

超级块对象:代表一个具体的已安装文件系统;

索引节点对象:代表一个具体文件;

目录项对象:代表一个目录项,是路径的一个组成部分;

文件对象:代表由进程打开的文件

块I/O层

块设备中最小的可寻址单元是扇区。扇区是设备的最小寻址单元;块是文件系统的最小寻址单元。块包含一个或多个扇区,但大小不能超过一个页面,所以一个页面可以容纳一个或多个内存的块。

目前内核中块I/O操作的基本容器由bio结构体表示,它代表了正在现场的(活动的)以片段链表形式组织的块I/O操作。

磁盘寻址是整个计算机系统中最慢的操作之一,所以尽量缩短寻址时间是提高系统性能的关键。

I/O调度程序通过两种方法减少磁盘寻址时间:合并和排序。

出现的问题

在使用gdb跟踪分析一个execve系统调用内核处理函数sys_execve的过程中,需要在执行exec命令的时候同时输出“hello world!”,需要修改Makefile文件里面的代码,使系统在执行exec命令的时候同时执行hello.c文件。



只需要把Makefile文件里的“cp hello ../rootfs/”这行代码去掉就能解决问题,但是我还是不理解具体原因。!

20169219《linux内核原理与分析》第九周作业的更多相关文章

  1. 20169219 linux内核原理与分析第二周作业

    "linux内核分析"的第一讲主要讲了计算机的体系结构,和各寄存器之间对数据的处理过程. 通用寄存器 AX:累加器 BX:基地址寄存器 CX:计数寄存器 DX:数据寄存器 BP:堆 ...

  2. 2019-2020-1 20199303<Linux内核原理与分析>第二周作业

    2019-2020-1 20199303第二周作业 1.汇编与寄存器的学习 寄存器是中央处理器内的组成部份.寄存器是有限存贮容量的高速存贮部件,它们可用来暂存指令.数据和位址.在中央处理器的控制部件中 ...

  3. 2019-2020-1 20199314 <Linux内核原理与分析>第二周作业

    1.基础学习内容 1.1 冯诺依曼体系结构 计算机由控制器.运算器.存储器.输入设备.输出设备五部分组成. 1.1.1 冯诺依曼计算机特点 (1)采用存储程序方式,指令和数据不加区别混合存储在同一个存 ...

  4. Linux内核原理与分析-第一周作业

    本科期间,学校开设过linux相关的课程,当时的学习方式主要以课堂听授为主.虽然老师也提供了相关的学习教材跟参考材料,但是整体学下来感觉收获并不是太大,现在回想起来,主要还是由于自己课下没有及时动手实 ...

  5. 2019-2020-1 20199314 <Linux内核原理与分析>第一周作业

    前言 本周对实验楼的Linux基础入门进行了学习,目前学习到实验九完成到挑战二. 学习和实验内容 快速学习了Linux系统的发展历程及其简介,学习了下的变量.用户权限管理.文件打包及压缩.常用命令的和 ...

  6. Linux内核原理与分析-第二周作业

    写之前回看了一遍秒速五厘米:如果

  7. 2020-2021-1 20209307 《Linux内核原理与分析》第九周作业

    这个作业属于哪个课程 <2020-2021-1Linux内核原理与分析)> 这个作业要求在哪里 <2020-2021-1Linux内核原理与分析第九周作业> 这个作业的目标 & ...

  8. 2018-2019-1 20189221《Linux内核原理与分析》第一周作业

    Linux内核原理与分析 - 第一周作业 实验1 Linux系统简介 Linux历史 1991 年 10 月,Linus Torvalds想在自己的电脑上运行UNIX,可是 UNIX 的商业版本非常昂 ...

  9. 2018-2019-1 20189221 《Linux内核原理与分析》第九周作业

    2018-2019-1 20189221 <Linux内核原理与分析>第九周作业 实验八 理理解进程调度时机跟踪分析进程调度与进程切换的过程 进程调度 进度调度时机: 1.中断处理过程(包 ...

  10. 2019-2020-1 20199329《Linux内核原理与分析》第九周作业

    <Linux内核原理与分析>第九周作业 一.本周内容概述: 阐释linux操作系统的整体构架 理解linux系统的一般执行过程和进程调度的时机 理解linux系统的中断和进程上下文切换 二 ...

随机推荐

  1. [TopCoder12727]FoxAndCity

    vjudge 题意 你有一张\(n\)点的无向图,每个点有一个点权\(w_i\).图中原来存在一些边,你可以任意给这张图加上一些边. 记点\(i\)到点\(1\)的距离为\(d_i\),你需要最小化\ ...

  2. server2012/win8 卸载.net framework 4.5后 无法进入系统桌面故障解决【转】

    都重装过一次了,第二次被坑了,真的是痛苦的经历 只剩下的cmd什么命令都不能执行啊,powershell也执行不了呀[网上都是说powershell切换的] 故障:服务器装的是windows2012 ...

  3. UDP10040 和 setsockopt设置大全

    今天无意之中碰到 UDP 10040 错误  原来是缓冲区不够,以下转载的解决方法以供不时之需.   1.closesocket(一般不会立即关闭而经历TIME_WAIT的过程)后想继续重用该sock ...

  4. angular input=file ng-change事件

    首先 ng-change事件要与ng-model绑定  但是 当input 的  type=file时   ngchange事件是失效的  我们可以用图中的onchange事件去代替 其次 如果想在这 ...

  5. SVN 命令使用-***

    1.检出到某一版本: svn checkout -r 974  svn://220.231.xx.xx/仓库名 svn checkout  svn://220.231.xx.xx/仓库名 svn ex ...

  6. [转]ubuntu11.04配置nfs--解决mount.nfs: access denied问题

    总算通过了nfs的localhost测试. 配置很简单,下面摘自网络,并且整理下: 1 安装nfs #apt-get install nfs-kernel-server #apt-get instal ...

  7. Django基础(五)

    Django admin 自带的验证: from django.contrib.auth.decorators import login_required from django.contrib.au ...

  8. MySQL mysqldump与innobackupex 组合备份

    此脚本,在01点进行一次逻辑全备份,03点进行一次物理全备份,中午12点进行一次增量物理备份 #! /bin/bash #05 01,03,12 * * * mysql /data/mysqldata ...

  9. linux下面的挂载点讲解

    linux.unix这类操作系统将系统中的一切都作为文件来管理.在windows中我们常见的硬件设备.磁盘分区等,在linux.unix中都被视作文件,对设备.分区的访问就是读写对应的文件.挂载点实际 ...

  10. [机器学习基础]矩阵基础和numpy

    矩阵定义:[摘自百度百科] 由 m × n 个数aij排成的m行n列的数表称为m行n列的矩阵,简称m × n矩阵.记作: 这m×n 个数称为矩阵A的元素,简称为元,数aij位于矩阵A的第i行第j列,称 ...