Linux操作系统与应用 第一章_第1页
Linux操作系统与应用 第一章_第2页
Linux操作系统与应用 第一章_第3页
Linux操作系统与应用 第一章_第4页
Linux操作系统与应用 第一章_第5页
已阅读5页,还剩49页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第一章操作系统概述认识操作系统操作系统的发展开放源代码的Unix/Linux操作系统Linux内核Linux内核源代码

Linux

内核模块编程入门Linux

内核中链表的实现及应用不同角度看到的操作系统操作系统整体看操作系统设计者使用者普通开发者认识操作系统打开计算机,首先跳入眼帘的是什么?要拷贝一个文件,具体的拷贝操作是谁完成的?你需要知道文件存放在何处吗?柱面、磁道、扇区描述什么?数据的搬动过程怎样进行繁琐留给自己,简单留给用户

操作系统穿上华丽的外衣-图形界面操作系统穿上朴素的外衣-字符界面<>认识操作系统-从使用者的角度看拷贝命令的C语言实现片断<>inf=open(“/floppy/TEST”,O_RDONLY,0);out=open(“/mydir/test”,O_WRONLY,0600);do{l=read(inf,buf,4096);write(outf,buf,l);}while(l);close(outf);close(inf);认识操作系统-从程序开发者的角度看

<>浏览器信息管理文件管理系统游戏

编译程序编辑程序命令解释程序

操作系统

CPU、内存、I/O接口硬件内核认识操作系统-从所处位置看操作系统是其它所有用户程序运行的基础。

<>#include<stdio.h>main(){printf(“Helloworld\n”)}用户告诉操作系统执行test程序操作系统通过文件名找到该程序检查其类型,检查程序首部,找出代码和数据存放的地址文件系统找到第一个磁盘块操作系统建立程序的执行环境操作系统把程序从磁盘装入内存,并跳到程序开始处执行该程序的执行过程简述如下:操作系统检查字符串的位置是否正确操作系统找到字符串被送往的设备操作系统将字符串送往输出设备窗口系统确定这是一个合法的操作,然后将字符串转换成像素窗口系统将像素写入存储映像区视频硬件将像素表示转换成一组模拟信号控制显示器(重画屏幕)显示器发射电子束。你在屏幕上看到Helloworld。从中看到什么认识操作系统-从程序执行看从操作系统设计者的角度看操作系统的设计目标是什么?尽可能地方便用户使用计算机让各种软件资源和硬件资源高效而协调地运转起来。计算机的硬件资源和软件资源各指什么?假设在一台计算机上有三道程序同时运行,并试图在一台打印机上输出运算结果,必须考虑哪些问题?从操作系统设计者的角度考虑,一个操作系统必须包含以下几部分操作系统接口CPU管理内存管理设备管理文件管理<>认识操作系统-从设计者角度看操作系统是计算机系统中的一个系统软件,是一些程序模块的集合——它们能以尽量有效、合理的方式组织和管理计算机的软硬件资源,合理的组织计算机的工作流程,控制程序的执行并向用户提供各种服务功能,使得用户能够灵活、方便、有效的使用计算机,使整个计算机系统能高效、顺畅地运行。<>认识操作系统-定义<>操作系统的组成(1)

通常意义上的操作系统被认为是整个系统中负责完成最基本的功能和系统管理的部分。除了内核,这些部分还应该包括启动引导程序、命令行shell或者其他种类的用户界面、基本的文件管理工具和系统工具等。实际上,人们在得到操作系统的同时,更需要的是构架于其上的应用软件,从而完成所需的实际功能。为此,操作系统一般要和应用软件绑定发行和出售。这样的软件包在linux领域被称作发布版。

<>操作系统的组成(2)

从开发者的角度看,操作系统本质上是大型软件包,因此结构组织不会与其它大型软件迥异:操作系统的设计采用分层结构,越向上层抽象程度越高,越接近用户;越向下层,越靠近硬件,抽象也越接近硬件。上层软件依靠下层软件提供的服务,而且上层软件自身还提供附加服务。因此,操作系统的结构整体总体呈现倒金字塔形。用一组简单的公式描述操作系统的组成要素:操作系统=内核+系统程序系统程序=编译环境+API(应用程序接口)+AUI(用户接口)编译环境=编译程序+链接程序+装载程序API=shell+系统服务例程+应用程序对于整个软件系统:软件系统=操作系统+AUI操作系统的演变单道批处理系统

串行执行预先组织好的一组任务

提高了系统效率。多道批处理系统可以交错运行多个程序再次提高系统效率。分时系统将处理器的运行时间分成数片,均分或依照一定权重派发给系统中的用户使用

快速响应

<>操作系统的发展硬件角度下的操作系发展轨迹年

特点

操作系统特点

机械计算机时代17世纪~20世纪初

1)纯机械结构,低速

2)只能进行简单的数学运算

纯手工操作

从计算尺至差分机到分析机发展了数百年第一代计算机

1946年~50年代末电子管计算机

1)体积大、能耗高、故障多、价格贵

2)难以普及应用

无操作系统

(程序按机器码编写,载体从插件板到卡片与纸带)

1906年发明电子管

1946ENIAC研制成功

(第一台电子管计算机)年

特点

操作系统特点

第二代计算机

50年代末~60年代中期

晶体管计算机

1)采用印刷电路

2)稳定性与可靠性大大提高

3)批量生产成为可能

4)进入实际应用领域但数量有限1)单道批处理系统

2)操作系统以监督软件形式出现

3)任务按顺序方式处理

1947年发明晶体管

第三代计算机

60年代中期~70年代初

集成电路计算机

1)体积减小,性价比迅速提高

2)小型计算机发展迅速

3)进入商业应用

4)尚不适合家庭应用的需求1)涌现大批操作系统

多道批处理系统、分时系统和实时系统

2)奠定了现代操作系统的基本框架

1958年发明集成电路

1971年INTEL发明微处理器

硬件角度下的操作系统发展轨迹分析在硬件的性价比较低的时候,操作系统设计追求什么?

在硬件性价比越来越高后,操作系统的设计开始追求的目标是什么?计算机开始普及后,操作系统的设计开始追求?从第三代到第四代计算机,操作系统的发展逐渐摆脱追随硬件发展的状况,形成自己的理论体系进入第四代系统后,分布式系统和多处理器系统虽然极大的扩充了操作系统理论,但系统结构并没有变化,只是各功能模块得以进一步完善。<>操作系统的发展硬件角度下操作系统发展的分析<>主流操作系统

系统特点

计算机语言背

手工操作

无编程语言直接使用机器代码

1936年图灵提出图灵机

单道批处理系统

作业运行的监督程序

编程语言雏形期

1957年FORTRAN语言开发成功多道批处理

分时系统

实时系统

多处理系统

操作系统结构确立,分为处理机管理、内存管理、设备管理、文件管理等模块

1)编程语言大量涌现

2)结构化程序设计

3)C语言逐渐

60年代的软件危机导致软件工程的发展

1969年Unix诞生

1972年C语言推出

主流操作系统

系统特点

计算机语言背

类Unix系列

WINDOWS系列

人机交互成为主题

1)可视化界面

2)多媒体技

面向对象语言成为主流

80年代中期开始面向对象技术逐步发展网络操作系统

分布式操作系统微内核技术兴起

1)JAVA语言

2)脚本语言兴起1995年JAVA推出

嵌入式系统

单内核与微内核竞争激烈编程工具向跨平台方向发

1991年免费的操作系统Linux发布

软件角度下的操作系统发展轨迹

分析程序设计理论约束着操作系统设计。操作系统的发展滞后于计算机语言的发展,从结构化设计到对象化设计,操作系统总是最后应用新编程理论的软件之一。至今操作系统对于是否需要彻底对象化(即微内核化),还处于徘徊时期,仍在探索单内核与微内核的最佳结合方式。人机交互技术主要是为用户考虑,这是对操作系统设计进行的变革。以Linux为代表的开源软件的出现,打破了带有神秘色彩的传统的封闭式开发模式。<>软件角度下的操作系统发展轨迹分析

<>讲究效率的单模块操作系统进程管理内存管理设备管理文件管理模块之间可以互相调用的单模块结构<>讲究效率的单模块操作系统模块之间直接调用函数,除了函数调用的开销外,没有额外开销。庞大的操作系统有数以千计的函数复杂的调用关系势必导致操作系统维护的困难<>追求简洁的微内核操作系统客户进程进程服务器内存服务器文件服务器…微内核<>追求简洁的微内核操作系统内核与各个服务器之间通过通信机制进行交互,这使得微内核结构的效率大大折扣。内核发出请求,服务器做出应答为各个服务器模块的相对独立性,使得其维护相对容易<>历史悠久的Unix在MULTICS(1969)的肩上制研制者KenThompson和DennisM.Ritchie

Unix的诞生还伴有C语言呱呱落地Unix是现代操作系统的代表:安全、可靠、强大的计算能力Unix的商业化是一把双刃剑

<>自由而奔放的黑马-Linux诞生于学生之手成长于Internet壮大于自由而开放的文化<>Linux之父-LinusTorvalds芬兰、赫尔辛基大学、1990起始于写两个进程然后写驱动程序、文件系统、任务切换程序,从而形成一个操作系统邹形<>Linux得以流行的原因之一

-遵循POSIX标准POSIX表示可移植操作系统接口(PortableOperatingSystemInterface)

POSIX是在Unix标准化过程中出现的产物。

POSIX1003.1标准定义了一个最小的Unix操作系统接口

任何操作系统只有符合这一标准,才有可能运行Unix程序

<>Linux的肥沃土壤-GNUGNU是GNUIsNotUnix的递归缩写,是自由软件基金会的一个项目

GNU项目产品包括emacs编辑器、著名的GNUC和Gcc编译器等,这些软件叫做GNU软件。GNU软件和派生工作均适用GNU通用公共许可证,即GPL(GeneralPublicLicense

)Linux的开发使用了众多的GUN工具<>GPL-开源软件的法律GPL允许软件作者拥有软件版权但GPL规定授予其他任何人以合法复制、发行和修改软件的权利。<>Linux系统或发布版

符合POSIX标准的操作系统内核、Shell和外围工具。C语言编译器和其他开发工具及函数库XWindow窗口系统各种应用软件,包括字处理软件、图象处理软件等。<>开放与协作的开发模式

世界各地软件爱好者集体智慧的结晶提供源代码,遵守GPL。经历了各种各样的测试与考验,软件的稳定性好。开发人员凭兴趣去开发,热情高,具有创造性。<>Linux内核

Linus领导下的开发小组开发出的系统内核

是所有Linux发布版本的核心

内核开发人员一般在百人以上,任何自由程序员都可以提交自己的修改工作。

采用邮件列表来进行项目管理、交流、错误报告有大量的用户进行测试,正式发布的代码质量高

<>Linux内核的技术特点

linux内核被设计成单内核结构,这是相对微内核而言的

2.6版本以前的linux内核是单线程结构,是非抢占式的内核结构linux内核支持动态加载内核模块

Linux内核被动地提供服务linux内核采用了虚拟内存技术,使得内存空间达到4GBlinux文件系统实现了一种UNIX风格的抽象文件模型——虚拟文件系统(VirtualFilesystermSwitch,VFS)linux提供了一套很有效的延迟机制——下半部分、软中断tasklet和2.6版本新引进的工作队列等。<>整个系统的核心-内核

硬件系统调用接口应用程序进程1应用程序进程2应用程序进程3Linux内核用户进程

内核子系统系统调用<>整个系统的核心-内核

用户进程—运行在Linux内核之上的一个庞大软件集合。系统调用—内核的出口,用户程序通过它使用内核提供的功能。

Linux内核—操作系统的灵魂,负责管理磁盘上的文件、内存,负责启动并运行程序,负责从网络上接收和发送数据包等等。硬件—包括了Linux安装时需要的所有可能的物理设备。例如,CPU、内存、硬盘、网络硬件等等。<>内核子系统<>内核子系统进程调度-控制着进程对CPU的访问。内存管理-允许多个进程安全地共享主内存区域虚拟文件系统-隐藏各种不同硬件的具体细节,为所有设备提供统一的接口。网络-提供了对各种网络标准协议的存取和各种网络硬件的支持。进程间通信(IPC)-支持进程间各种通信机制,包括共享内存、消息队列及管道等。Linux内核版本树

0.01

Linux(第一版)

0.13版

|

产品化版本

实验版本

1.0.0

1.1.0(1.0.0的拷贝)

1.0.X(修改)

1.1.X(增加新功能,进行测试)

1.1.95(成为1.2.0)内核源代码结构Linux内核源代码分析工具

Linux超文本交叉代码检索工具

http://lxr.linux.no/

Windows平台下的源代码阅读工具SourceInsightLinux内核模块编程入门

认识内核模块

内核模块是linux内核向外部提供的一个插口,是内核的一部分,但是并没有被编译到内核里面去,其全称为动态可加载内核模块(LoadableKernelModule,LKM),简称模块。为什么要使用模块?

linux内核之所以提供模块机制,是因为它本身是一个单内核。而单内核的最大优点就是效率高,因为所有的内容都集成在一起,但其缺点是可扩展性和可维护性相对较差,模块机制就是为了弥补这一缺陷。Linux内核模块编程入门

模块的定义

模块是具有独立功能的程序,它可以被单独编译,但不能独立运行。它在运行时被链接到内核作为内核的一部分在内核空间运行,这与运行在用户空间的进程是不同的。模块通常由一组函数和数据结构组成,用来实现一种文件系统、一个驱动程序或者其他内核上层的功能。编写简单的内核模块

模块和内核都在内核空间运行,模块编程在一定意义上说就是内核编程。一个内核模块应该至少有两个函数,第一个为module_init(),是模块加载函数,当模块被插入到内核时调用它;第二个为module_exit(),是模块卸载函数,当模块从内核移走时调用它。Linux内核模块编程入门

简单的内核模块实例:

任何模块都要包含的三个头文件:#include<linux/module.h>#include<linux/kernel.h>#incldue<linux/init.h>说明:module.h头文件包含了对模块的版本控制;kernel.h包含了常用的内核函数;init.h包含了宏__init和__exit,宏__init告诉编译程序相关的函数和变量仅用于初始化,编译程序将标有__init的所有代码存储到特殊的内存段中,初始化结束就释放这段内存。在此使用了printk()函数,该函数是由内核定义的,功能和C库中的printf()类似,它把要打印的日志输出到终端或系统日志。字符串中的<1>是输出的级别,表示立即在终端输出。Linux内核模块编程入门

内核模块的Makefile文件

内核模块不是独立的可执行文件,但在运行时其目标文件被链接到内核中。只有超级用户才能加载和卸载模块。给前面的程序起名叫module_example.c,那么其对应的Makefile文件的基本内容如下:obj-m:=这个赋值语句的含义是说明要使用目标文件module_example.o建立一个模块,最后生成的模块名为module_example.ko。.o文件是经过编译和汇编,而没有经过链接的中间文件。注:makefile文件中,若某一行是命令,则它必须以一个Tab键开头。Linux内核模块编程入门

运行代码当编译好模块,就可以用insmod命令将新的模块插入到内核中,如:

insmodmodule_example.ko然后,可以用lsmod命令查看模块是否正确地插入到了内核中。模块的输出由printk()产生。该函数默认打印系统文件/var/log/messages的内容。卸载模块时,使用rmmod命令加上在insmod中看到的模块名,就可以从内核中移除该模块:

rmmodmodule_exampleLinux内核模块编程入门

应用程序与内核模块的比较

C语言应用程序内核模块程序使用函数Libc库内核函数运行空间用户空间内核空间运行权限普通用户超级用户入口函数main()module_init()出口函数exit()module_cleanup()编译gcc–cmake连接gccinsmod运行直接运行insmod调试gdbkdbug,kdb,kgdb等Linux内核中链表的实现及应用为什么要用链表?①与数组相比,链表中可以动态插入或删除元素,在编译时不必知道要创建的元素个数。②在内存无需占用连续的内存单元。③每个元素都包含一个指向下一个元素的指针,当有元素加入链表或者从链表中删除元素时,只需要调整下一个节点的指针就可以了。Linux内核中链表的实现及应用通过前趋(prev)和后继(next)两个指针域,就可以从两个方向遍历双链表,这使得遍历链表的代价减少。链表的演化

在C语言中,一个基本的双向链表定义如下:structmy_list{ void*mydata; structmy_list*next; structmy_list*prev; };Linux内核中链表的实现及应用链表的定义linux内核对链表的实现方式与众不同,不是在链表中包含数据,而是在数据结构中包含链表。其具体的定义如下:

structlist_head{

structlist_head*next,*prev;

};这个不含数据结构的通用双向链表可以嵌入到任何结构中。说明:1.list域隐藏了链表的指针特性2.structlist_head可以位于结构的任何位置,可以给其起任何名字3.在一个结构中可以有多个list域

以structlist_head为基本对象,可以对链表进行插入、删除、合并以及遍历等各种操作。

Linux内核中链表的实现及应用链表的声明和初始化structlist_head只定义了链表节点,并没有专门定义链表头,那么一个链表结构是如何建立起来的?内核代码list.h中定义了两个宏:#defineLIST_HEAD_INIT(name){&(name),&(name)}/*仅初始化*/#defineLIST_HEAD(name)structlist_headname= LIST_HEAD_INIT(name)

/*声明并初始化*/

当我们调用LIST_HEAD(name)声明一个名为name的链表头时,它的next和prev指针都初始化指向自己。这样,我们就有了一个空链表,因为linux用头指针的next是否指向自己来判断链表是否为空:staticinlineintlist_empty(conststructlist_head*head){

returnhead->next==head;}Linux内核中链表的实现及应用在链表中增加一个节点在include/linux/list.h中增加结点的函数为:

staticinlinevoidlist_add();staticinlinevoidlist_add_tail();

在内核代码中,函数名前加两个下划线表示内部函数。list_add()和list_add_tail()均调用__list_add()真正实现头插和尾插。staticinlinevoid__list_add(structlist_head*new,structlist_head*prev,structlist_head*next){next->prev=new;new->next=next;new->prev=prev;prev->next=new;}staticinlinevoidlist_add(structlist_head*new,

structlist_head*head){__list_add(new,head,head->next);}该函数向指定链表的head结点后插入new结点。因为是循环链表,而且通常没有首尾结点的概念,所以可以将任何结点传给head。若传最后一个元素给head,该函数就可以实现一个栈。Linux内核中链表的实现及应用

list_add_tail()的内核实现:

staticinlinevoidlist_add_tail(structlist_head*new,structlist_head*head){__list_add(new,head->prev,head);}

list_add_tail()函数向指定链表的head结点前插入new结点。说明:关于staticinline关键字。

“static”加在函数前,表示这个函数是静态函数,所谓静态函数,实际上是对函数作用域的限制,指该函数的作用域仅局限于本文件。所以说,static具有信息隐藏的作用。而关键字"inline“加在函数前,说明这个函数对编译程序是可见的,也就是说编译程序在调用这个函数时就立即展开该函数。Linux内核中链表的实现及应用

链表的遍历

这种链表只是找到了一个个结点在链表中的偏移位置pos,如下图(a)。那么如何通过pos获得结点的起始地址,从而可以引用结点中的域呢?(a)(b)list.h中定义了晦涩难懂的list_entry()宏:#definelist_entry(ptr,type,member)\

((type*)(

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论