笔记
哪个关键字可以对对象加互斥锁?(A)
synchronized 关键字 : 用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这个段代码。
**volatile:**用来确保将变量的跟新操作通知到其他线程,当把变量声明为volatile类型后,编译器与运行时都会注意到这个变量是共享的,因此不会将该变量上的操作与其他内存操作一起重排序。然而,在访问volatile变量时不会执行加锁操作,因此也就不会使执行线程阻塞,因此volatile变量是一种比 synchronized关键字更轻量级的同步机制。
**serialize:**Java 对象序列化为二进制文件。
static关键字: static关键字可以修饰变量,方法,静态代码块。
静态变量:
由static修饰的变量称为静态变量
静态变量属于类,而不属于某个对象
静态变量它的副本只有一个(静态变量在类中只加载一)
静态方法:
在静态方法中只能调用静态变量和静态方法
在非静态方法中,可以调用静态方法或者变量。
在静态方法中不能使用this和super关键字。
静态代码块
作用:用来给静态成员变量初始化
数组的声明
关于多线程和多进程,下面描述正确的是():
**A.**子进程得到的是除了代码段是与父进程共享以外,其他所有的都是得到父进程的一个副本,子进程的所有资源都继承父进程,得到父进程资源的副本,子进程可获得父进程的所有堆和栈的数据,但二者并不共享地址空间。两个是单独的进程,继承了以后二者就没有什么关联了,子进程单独运行;进程的线程之间共享由进程获得的资源,但线程拥有属于自己的一小部分资源,就是栈空间,保存其运行状态和局部自动变量的。
**B.**线程之间共享进程获得的数据资源,所以开销小,但不利于资源的管理和保护;而进程执行开销大,但是能够很好的进行资源管理和保护。
**C.**线程的通信速度更快,切换更快,因为他们共享同一进程的地址空间。
**D.**一个进程可以有多个线程,线程是进程的一个实体,是CPU调度的基本单位。
hashMap在单线程中使用大大提高效率,在多线程的情况下使用hashTable来确保安全。hashTable中使用synchronized关键字来实现安全机制,但是synchronized是对整张hash表进行锁定即让线程独享整张hash表,在安全同时造成了浪费。concurrentHashMap采用分段加锁的机制来确保安全
考察点1:重载静态多分派——根据传入重载方法的参数类型,选择更加合适的一个重载方法
考察点2:static方法不能被子类覆写,在子类中定义了和父类完全相同的static方法,则父类的static方法被隐藏,Son.staticmethod()或new Son().staticmethod()都是调用的子类的static方法,如果是Father.staticmethod()或者Father f = new Son(); f.staticmethod()调用的都是父类的static方法。
考察点3:此题如果都不是static方法,则最终的结果是A. 调用子类的getType,输出collection
非抽象类实现接口后,必须实现接口中的所有抽象方法,除了abstract外,方法头必须完全一致.(错误)
实际上这道题考查的是两同两小一大原则:
方法名相同,参数类型相同
子类返回类型小于等于父类方法返回类型, 子类抛出异常小于等于父类方法抛出异常, 子类访问权限大于等于父类方法访问权限。
1.String对象的两种创建方式: 第一种方式: String str1 = "aaa"; 是在常量池中获取对象("aaa" 属于字符串字面量,因此编译时期会在常量池中创建一个字符串对象),
第二种方式: String str2 = new String("aaa") ; 一共会创建两个字符串对象一个在堆中,一个在常量池中(前提是常量池中还没有 "aaa" 字符串对象)。
System.out.println(str1==str2);//false
2.String类型的常量池比较特殊。它的主要使用方法有两种: 直接使用双引号声明出来的String对象会直接存储在常量池中。 如果不是用双引号声明的String对象,可以使用 String 提供的 intern 方法。 String.intern() 是一个 Native 方法,它的作用是: 如果运行时常量池中已经包含一个等于此 String 对象内容的字符串,则返回常量池中该字符串的引用; 如果没有,则在常量池中创建与此 String 内容相同的字符串,并返回常量池中创建的字符串的引用。 String s1 = new String("AAA"); String s2 = s1.intern(); String s3 = "AAA"; System.out.println(s2);//AAA System.out.println(s1 == s2);//false,因为一个是堆内存中的String对象一个是常量池中的String对象, System.out.println(s2 == s3);//true, s2,s3指向常量池中的”AAA“
ServerSocket (int port)
创建一个serversocket 绑定在特定的端口
Socket(InetAddress address, int port)
创建一个socket流,连接到特定的端口和ip地址
Collection 是对象集合, Collection 有两个子接口 List 和 Set,
List 可以通过下标 (1,2..) 来取得值,值可以重复,而 Set 只能通过游标来取值,并且值是不能重复的
ArrayList , Vector , LinkedList 是 List 的实现类
ArrayList 是线程不安全的, Vector 是线程安全的,这两个类底层都是由数组实现的
LinkedList 是线程不安全的,底层是由链表实现的
Map 是键值对集合
HashTable 和 HashMap 是 Map 的实现类
HashTable 是线程安全的,不能存储 null 值
HashMap 不是线程安全的,可以存储 null 值
IO流
A.类的成员变量包括实例变量和类变量(静态变量),成员方法包括实例方法和类方法(静态方法)。 **A正确
B.类变量(静态变量)用关键字static声明,B错误
**C.方法中的局部变量在****方法被调用加载时开始入栈时创建,方法入栈创建栈帧包括局部变量表操作数栈,局部变量表存放局部变量,并非在执行该方法时被创建,C错误**
D.局部变量被使用前必须初始化,否则程序报错。D正确
重载
方法重载:方法名称相同,参数列表不同(可以是参数的类型,个数,顺序不同)
1.方法名必须相同; 2.方法返回类型,修饰符可不同; 3.参数类型或个数或顺序要不同。
Java运行时内存
1. 程序计数器,线程私有。可以看作是当前线程所执行的字节码的行号指示器,字节码解释器工作时就是通过改变整个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等功能。
由于JVM的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器(对于多核处理器来说是一个内核**)都只会执行一条线程中的指令。因此为了线程切换后能恢复到正确的执行位置,每条线程都需要一个独立的程序计数器,各条线程之间计数器互不影响,独立存储,所以线程私有。**
程序计数器是唯一一个在Java虚拟机规范中没有规定任何OOM的区域。
2. Java虚拟机栈,线程私有。生命周期和线程相同。虚拟机栈描述的是Java方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧。每个方法从调用到执行完成的过程,就对应着一个栈帧在虚拟机中入栈到出栈的过程。
3. 本地方法栈,线程私有。和虚拟机栈的区别就在于一个是为了执行Java方法服务,一个是为了虚拟机使用到的Native方法服务。
4. 堆,线程共享。存放对象实例和数组。
5. 方法区,线程共享。存放已经被JVM加载的类信息,常量,静态变量,即时编译器编译后的代码。
访问权限:
private | default | protected | public | |
---|---|---|---|---|
同一个类中 | √ | √ | √ | √ |
同一个包中 | √ | √ | √ | |
子类中 | √ | √ | ||
全局范围内 | √ |
( 1 )对于外部类而言,它也可以使用访问控制符修饰,但外部类只能有两种访问控制级别: public 和默认。因为外部类没有处于任何类的内部,也就没有其所在类的内部、所在类的子类两个范围,因此 private 和 protected 访问控制符对外部类没有意义。
( 2 )内部类的上一级程序单元是外部类,它具有 4 个作用域:同一个类( private )、同一个包( protected )和任何位置( public )。
( 3 ) 因为局部成员的作用域是所在方法,其他程序单元永远不可能访问另一个方法中的局部变量,所以所有的局部成员都不能使用访问控制修饰符修饰。
java对象初始化顺序
先说结论:
- 父类静态代码块,父类静态成员变量(同级,按代码顺序执行)
- 子类静态代码块,子类静态成员变量(同级,按代码顺序执行)
- 父类普通代码块,父类普通成员变量(同级,按代码顺序执行)
- 父类构造方法
- 子类普通代码块,子类普通成员变量(同级,按代码顺序执行)
- 子类构造方法
注意点:
- 静态内容只在类加载时执行一次,之后不再执行。
- 默认调用父类的无参构造方法,可以在子类构造方法中利用super指定调用父类的哪个构造方法。
join()的作用是:“等待该线程终止”,这里需要理解的就是该线程是指的主线程等待子线程的终止。也就是在子线程调用了join()方法后面的代码,只有等到子线程结束了才能执行。
A.程序计数器是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的信号指示器(偏移地址),Java编译过程中产生的字节码有点类似编译原理的指令,程序计数器的内存空间存储的是当前执行的字节码的偏移地址,每一个线程都有一个独立的程序计数器(程序计数器的内存空间是线程私有的),因为当执行语句时,改变的是程序计数器的内存空间,因此它不会发生内存溢出 ,并且程序计数器是jvm虚拟机规范中唯一一个没有规定 *OutOfMemoryError* 异常 的区域;
B.java虚拟机栈:线程私有,生命周期和线程一致。描述的是 Java 方法执行的内存模型:每个方法在执行时都会床创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行结束,就对应着一个栈帧从虚拟机栈中入栈到出栈的过程。 没有类信息,类信息是在方法区中
C.java堆:对于绝大多数应用来说,这块区域是 JVM 所管理的内存中最大的一块。线程共享,主要是存放对象实例和数组
D.方法区:属于共享内存区域,存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
1. 只看尖括号里边的!!明确点和范围两个概念*
- 如果尖括号里的是一个类,那么尖括号里的就是一个点,比如List,List,List
- 如果尖括号里面带有问号,那么代表一个范围, 代表小于等于A的范围,代表大于等于A的范围,代表全部范围
- 尖括号里的所有点之间互相赋值都是错,除非是俩相同的点
- 尖括号小范围赋值给大范围,对,大范围赋值给小范围,错。如果某点包含在某个范围里,那么可以赋值,否则,不能赋值
- List<?>和List 是相等的,都代表最大范围----------------------------------------------------------------------------------
- 补充:List既是点也是范围,当表示范围时,表示最大范围
Java多线程实现方式主要有四种:
1、继承Thread类
2、实现Runnable接口
3、实现Callable接口通过FutureTask包装器来创建Thread线程
4、使用ExecutorService、Callable、Future实现有返回结果的多线程。
中间件是一种独立的系统软件或服务程序,分布式应用软件借助这种软件在不同的技术之间共享资源。中间件位于客户机/ 服务器的操作系统之上,管理计算机资源和网络通讯。是连接两个独立应用程序或独立系统的软件。相连接的系统,即使它们具有不同的接口,但通过中间件相互之间仍能交换信息。执行中间件的一个关键途径是信息传递。通过中间件,应用程序可以工作于多平台或OS环境。
(简单来说,中间件并不能提高内核的效率,一般只是负责网络信息的分发处理)
------------知识点------------
Java表达式转型规则由低到高转换:
1、所有的byte,short,char型的值将被提升为int型;
2、如果有一个操作数是long型,计算结果是long型;
3、如果有一个操作数是float型,计算结果是float型;
4、如果有一个操作数是double型,计算结果是double型;
5、被fianl修饰的变量不会自动改变类型,当2个final修饰相操作时,结果会根据左边变量的类型而转化
1.start方法
用 start方法来启动线程,是真正实现了多线程, 通过调用Thread类的start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦得到cpu时间片,就开始执行run()方法。但要注意的是,此时无需等待run()方法执行完毕,即可继续执行下面的代码。所以run()方法并没有实现多线程。
2.run方法
run()方法只是类的一个普通方法而已,如果直接调用Run方法,程序中依然只有主线程这一个线程,其程序执行路径还是只有一条,还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码。
网卡 | 作用于 | 物理层 |
---|---|---|
中继器 | 物理层 | |
集线器 | 物理层 | |
网桥 | 数据链路层 | |
交换机 | 数据链路层 | |
路由器 | 网络层 |
使用tcp协议的应用层协议主要有:smtp,ftp,http,telnet;其他大部分使用udp
单道批处理注重顺序性
多到批处理方式为了提高资源利用率和吞吐量,周转时间长,无交互能力
分时系统为了实现人机交互,特点是多路性独立性及时性和交互性
实时系统最明显的特征是实时性和可靠性
空闲分区分配算法有以下三个:
-
首适应算法:当接到内存申请时,查找分区说明表,找到第一个满足申请长度的空闲区,将其分割并分配。此算法简单,可以快速做出分配决定,空闲区首地址递增顺序形成空闲分区链。
-
最佳适应算法:当接到内存申请时,查找分区说明表,找到第一个能满足申请长度的最小空闲区,将其进行分割并分配。此算法最节约空间,因为它尽量不分割到大的空闲区,其缺点是可能会形成很多很小的空闲分区,称为“碎片”,空闲区大小递增顺序形成空闲分区链。
-
最坏适应算法:当接到内存申请时,查找分区说明表,找到能满足申请要求的最大的空闲区。该算法的优点是避免形成碎片,而缺点是分割了大的空闲区后,在遇到较大的程序申请内存时,无法满足的可能性较大,空闲区大小递减顺序形成空闲分区链。
1)接口可以继承接口,而且可以继承多个接口,但是不能实现接口,因为接口中的方法全部是抽象的,无法实现;
另外,如果是Java 7以及以前的版本,那么接口中可以包含的内容有:1. 常量;2. 抽象方法 如果是Java 8,还可以额外包含有:3. 默认方法;4. 静态方法 如果是Java 9,还可以额外包含有:5. 私有方法
2)普通类可以实现接口,并且可以实现多个接口,但是只能继承一个类,这个类可以是抽象类也可以是普通类,如果继承抽象类,必须实现抽象类中的所有抽象方法,否则这个普通类必须设置为抽象类;
3)抽象类可以实现接口,可以继承具体类,可以继承抽象类,也可以继承有构造器的实体类。
抽象类中可以有静态main方法;抽象类里可以没有抽象方法,没有抽象方法的抽象类就是不想让别人实例化它;
另外,抽象类可以有构造方法,只是不能直接创建抽象类的实例对象而已。在继承了抽象类的子类中通过super(参数列表)调用抽象类中的构造方法,可以用于实例化抽象类的字段。
下面总结常见的抽象类与接口的区别:
1)抽象类和接口都不能直接实例化,如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口变量必须指向实现所有接口方法的类对象;
2)接口只能做方法申明,抽象类中可以做方法申明,也可以做方法实现(java8中 接口可以有实现方法 使用default修饰);
3)接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量;
4)抽象类里的抽象方法必须全部被子类所实现,如果子类不能全部实现父类抽象方法,那么该子类只能是抽象类。同样,一个类实现接口的时候,如不能全部实现接口方法,那么该类也只能为抽象类;
5)抽象方法要被实现,所以不能是静态static的,也不能是私有private的,也不能被final修饰(试想一下,静态方法可以被类名直接调用,而类名直接调用一个没有实现的抽象方法没有意义)。
**Ant****的作用:是一种基于**Java的build工具
- 能够用ant编译java类。生成class文件
- ant能够自己定义标签、配置文件,用于构建。
- ant能够把相关层构建成jar包 。
- ant把整个项目生成web包。并公布到Tomcat
Ant的长处:
-
跨平台性:Ant是纯Java语言编写的,因此具有非常好的跨平台性。
-
操作简单:Ant是由一个内置任务和可选任务组成的。Ant执行时须要一个XML文件(构建文件)。
-
Ant通过调用target树,就能够运行各种task:每一个task实现了特定接口对象。因为Ant构建文件时XML格式的文件。所以非常easy维护和书写,并且结构非常清晰。
-
Ant能够集成到开发环境中:因为Ant的跨平台性和操作简单的特点。它非常easy集成到一些开发环境中去。
**Maven**的作用: 除了以程序构建能力为特色之外,还提供高级项目管理工具。
Maven除了具备Ant的功能外。还添加了下面基本的功能:
- 使用Project Object Model来对软件项目管理。
- 内置了很多其它的隐式规则,使得构建文件更加简单。
- 内置依赖管理和Repository来实现依赖的管理和统一存储;
- 内置了软件构建的生命周期;
**Maven**的长处:
- 拥有约定,知道你的代码在哪里,放到哪里去
- 拥有一个生命周期,比如运行 mvn install就能够自己主动运行编译,測试。打包等构建过程
- 仅仅须要定义一个pom.xml,然后把源代码放到默认的文件夹,Maven帮你处理其它事情
- 拥有依赖管理。仓库管理
总体的比較:
Ant将提供了非常多能够重用的task,比如 copy, move, delete以及junit单元測试Maven则提供了非常多能够重用的过程。
JVM 内存可简单分为三个区:
1、堆区(heap):用于存放所有对象,是线程共享的(注:数组也属于对象)
2、栈区(stack):用于存放基本数据类型的数据和对象的引用,是线程私有的(分为:虚拟机栈和本地方法栈)
3、方法区(method):用于存放类信息、常量、静态变量、编译后的字节码等,是线程共享的(也被称为非堆,即 None-Heap)
Java 的垃圾回收器(GC)主要针对堆区
servlet在多线程下其本身并不是线程安全的。
如果在类中定义成员变量,而在service中根据不同的线程对该成员变量进行更改,那么在并发的时候就会引起错误。最好是在方法中,定义局部变量,而不是类变量或者对象的成员变量。由于方法中的局部变量是在栈中,彼此各自都拥有独立的运行空间而不会互相干扰,因此才做到线程安全。
init方法: 是在servlet实例创建时调用的方法,用于创建或打开任何与servlet相的资源和初始 化servlet的状态,Servlet规范保证调用init方法前不会处理任何请求
service方法:是servlet真正处理客户端传过来的请求的方法,由web容器调用, 根据HTTP请求方法(GET、POST等),将请求分发到doGet、doPost等方法
destory方法:是在servlet实例被销毁时由web容器调用。Servlet规范确保在destroy方法调用之 前所有请求的处理均完成,需要覆盖destroy方法的情况:释放任何在init方法中 打开的与servlet相关的资源存储servlet的状态
A**.Java系统提供3种类加载器:**启动类加载器(Bootstrap ClassLoader) 扩展类加载器(Extension ClassLoader) 应用程序类加载器(Application ClassLoader). A正确
**B.《深入理解Java虚拟机》P228:对于任意一个类,都需要由加载它的类加载器和这个类本身一同确立其在Java虚拟机中的唯一性,每一个类加载器,都拥有一个独立的类名称空间。这句话可以表达得更通俗一些:比较两个类是否“相等”,只有在这两个类是由同一个类加载器加载的前提下才有意义,否则,即使这两个类来源于同一个Class文件,被同一个虚拟机加载,只要加载它们的类加载器不同,那么这两个类必定不相等。**接口类是一种特殊类,因此对于同一接口不同的类装载器装载所获得的类是不相同的。B错误
C.类只需加载一次就行,因此要保证类加载过程线程安全,防止类加载多次。C正确
D. Java程序的类加载器采用双亲委派模型,实现双亲委派的代码集中在java.lang.ClassLoader的loadClass()方法中,此方法实现的大致逻辑是:先检查是否已经被加载,若没有加载则调用父类加载器的loadClass()方法,若父类加载器为空则默认使用启动类加载器作为父类加载器。如果父类加载失败,抛出ClassNotFoundException异常。D错误** **
E.双亲委派模型的工作过程:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求时,子加载器才会尝试自己去加载。E正确
F.\应用程序类加载器(Application ClassLoader)负责加载****用户类路径(ClassPath)上所指定的类库,不是所有的ClassLoader都加载此路径。F错误
-Xmx:最大堆大小
-Xms:初始堆大小
-Xmn:年轻代大小
-XXSurvivorRatio:年轻代中Eden区与Survivor区的大小比值
1.页面调入:是给页面调入内存中,给它分配物理内存。
2.页面置换,就是将内存中的页面置换出来,放到虚拟内存中,让物理内存空闲出来,让给需要使用的页面。
3.LRU:全称是:Least Recently Used(最近最久未使用)置换算法,所以这个算法涉及到了虚拟内存的分配和物理内存的释放。所以答案是AD。
Bean的作用域由@scope注解来修改,该注解有五个不同的取值,分别是:singleton、prototype、request、session、global-session。
- singleton,在每一个Spring容器中,一个Bean定义只有一个对象实例(默认为singleton)
- prototype,允许Bean的定义可以被实例化任意次(每次调用都创建一个一个实例)
- request,在一次HTTP请求中,每个Bean定义对应一个实例。该作用域仅在基于Web的Spring上下文(例如SpringMVC)中才有效
- session,在一个HTTP Session中,每个Bean定义对应一个实例。该作用域仅在基于Web的Spring上下文(例如SpringMVC)中才有效
- global-session,在一个全局HTTP Session中,每个Bean定义对应一个实例。该作用域仅在基于Web的Spring上下文(例如SpringMVC)中才有效
事务属性的种类: 传播行为、隔离级别、只读和事务超时
a) 传播行为定义了被调用方法的事务边界。
* *
\b)\ **隔离级别***在操作数据时可能带来* *3* *个副作用,分别是脏读、不可重复读、幻读。为了避免这* *3* *中副作用的发生,在标准的* *SQL* *语句中定义了* *4* *种隔离级别,分别是未提交读、已提交读、可重复读、可序列化。而在* *spring* *事务中提供了* *5* *种隔离级别来对应在* *SQL* *中定义的* *4* *种隔离级别,如下:***
\c)\ **只读***如果在一个事务中所有关于数据库的操作都是只读的,也就是说,这些操作只读取数据库中的数据,而并不更新数据,那么应将事务设为只读模式(* *READ_ONLY_MARKER* *)* *,* *这样更有利于数据库进行优化* **。***因为只读的优化措施是事务启动后由数据库实施的,因此,只有将那些具有可能启动新事务的传播行为* *(PROPAGATION_NESTED* *、* *PROPAGATION_REQUIRED* *、* *PROPAGATION_REQUIRED_NEW)* **的方法的事务标记成只读才有意义。***如果使用* *Hibernate* *作为持久化机制,那么将事务标记为只读后,会将* *Hibernate* *的* *flush* *模式设置为* *FULSH_NEVER,* *以告诉* *Hibernate* **避免和数据库之间进行不必要的同步,并将所有更新延迟到事务结束。***d)* **事务超时****如果一个事务长时间运行,这时为了尽量避免浪费系统资源,应为这个事务设置一个有效时间,使其等待数秒后自动回滚。与设***置“只读”属性一样,事务有效属性也需要给那些具有可能启动新事物的传播行为的方法的事务标记成只读才有意义。***
Tcp/Ip有3次握手:第一次握手:客户端向服务器端发送SYN包(syn=j),进入SYN_SEND状态,等待服务器确认。第二次握手:服务器收到SYN包,确认SYN,此时syn=j+1,同时发送一个SYN包(syn=k)即SYN+ACK包,此时服务器进入SYN_RECV状态;第三次握手:客户端收到SYN+ACK包,向服务器发送ACK确认包,此时客户端和服务器端均进入ESTABLISHED状态。
其中有一个半连接状态:服务器维护一个半连接队列,该队列卫每个客户端SYN包开设一个条目,标明服务器已经接到SYN包,并向客户端发出确认,这些条目表示的连接处于SYN_RECV状态,得到客户端的确认后进入ESTABLISHED状态。
(1)程序直接访问方式跟循环检测IO方式,应该是一个意思吧,是最古老的方式。CPU和IO串行,每读一个字节(或字),CPU都需要不断检测状态寄存器的busy标志,当busy=1时,表示IO还没完成;当busy=0时,表示IO完成。此时读取一个字的过程才结束,接着读取下一个字。
(2)中断控制方式:循环检测先进些,IO设备和CPU可以并行工作,只有在开始IO和结束IO时,才需要CPU。但每次只能读取一个字。
(3)DMA方式:Direct Memory Access,直接存储器访问,比中断先进的地方是每次可以读取一个块,而不是一个字。
(4)通道方式:比DMA先进的地方是,每次可以处理多个块,而不只是一个块。
系统回收主存时,按道理,空闲区会加1,但是如果存在以下的两种情况,空闲区个数会有所不同: (1).当回收的主存与已有的空闲区存在上邻 或者\ 下邻的情况,将回收的主存与已有的空闲区合并,空闲区的个数不变; (2).当回收的主存与已有的空闲区存在上邻 和\ 下邻的情况,则回收的主存会将原来的空闲去中的两个空闲区合并成一个空闲区,即回收的主存起到了联通的作用,空闲区的个数不增,反而与之前相比,个数还减少了一个。
JDK动态代理,是Java提供的动态代理技术,可以在运行时创建接口的代理实例。Spring AOP默认采用这种方式,在接口的代理实例中织入代码。CGLib动态代理,采用底层的字节码技术,在运行时创建子类代理的实例。当目标对象不存在接口时,Spring AOP就会采用这种方式,在子类实例中织入代码。
1.IP数据报分片的原因:
在TCP/IP分层中,数据链路层用 MTU (Maximum Transmission Unit,最大传输单元)来限制所能传输的数据包大小,MTU是指一次传送的数据最大长度,不包括数据链路层数据帧的帧头,如以太网的MTU为1500字节,实际上数据帧的最大长度为1512字节,其中以太网数据帧的帧头为12字节。
2.分片的思想:
当发送的IP数据报的大小超过了MTU时,IP层就需要对数据进行分片,否则数据将无法发送成功。
IP 分片发生在 IP 层 ,不仅 源端主机 会进行分片,中间的 路由器 也有可能分片,因为不同的网络的 MTU 是不一样的,如果传输路径上的某个网络的 MTU 比源端网络的 MTU 要小,路由器就可能对 IP 数据报再次进行分片。而分片数据的 重组 只会发生在 目的 端 的 IP 层。
操作系统:
原语和系统调用是两个层面的概念
原语强调的是 某个操作或者指令集合 的连续性以及不可中断性。集合中的指令要么全部执行,要么一个也不执行,进程和其它进程通信用的是进程间通信原语,如信号,监视器或消息。
而系统调用 是出于对多种设计原则的考虑(如安全性,耦合性,模块化等等),内核态为了用户态能使用内核态的服务 而提供一个简单、一致的接口。用户态不用关心内核态是怎样实现服务的,只需要按照规定的方式调用,即可得到自己期望的结果。进程在用户态的时候运行一个用户程序时,它需要系统服务时,例如从文件读数据,它必须执行一个陷入指令,把控制权交给操作系统,当执行完所需服务时,操作系统把控制权交还给用户进程。
线程是将一个进程分成多个部分来进行程序的执行,那么这多个部分就还需要额外的内存来进行管理,也就是多要了内存,所以不可能提高内存利用率。
相对于CISC,RISC的特点是指令条数少;指令长度固定,指令格式和寻址种类少;只有取数/存数指令访问存储器,其余指令的操作均在寄存器之间进行;CPU中通用寄存器多;大部分指令在一个或者小于一个机器周期内完成;以硬布线逻辑为主,不用或者少用微程序控制。选项B、C、D都是RISC的特点,选项A是错误的,因为RISC的速度快,所以普遍采用硬布线控制器,而非微程序控制器。
虽然进程在运行过程中,可能发生死锁,但死锁的发生也必须具备一定的条件,死锁的发生必须具备以下四个必要条件。
1 )互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。
2 )请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。
3 )不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。
4 )环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。
因此为了避免发生死锁,则不能生成此资源的环形链,则4个进程是极限了。
批处理系统主要特点:
多道:在内存中同时存放多个作业,一个时刻只有一个作业运行,这些作业共享CPU和外部设备等资源。
成批:用户和他的作业之间没有交互性。用户自己不能干预自己的作业的运行,发现作业错误不能及时改正。
批处理系统的目的是提高系统吞吐量和资源的利用率。
多道处理系统的优点是由于系统资源为多个作业所共享,其工作方式是作业之间自动调度执行。并在运行过程中用户不干预自己的作业,从而大大提高了系统资源的利用率和作业吞吐量。其缺点是无交互性,用户一旦提交作业就失去了对其运行的控制能力,而且是批处理的,作业周转时间长,用户使用不方便。
破坏死锁的方法包括: 1. 破坏互斥条件,如果系统资源都能共享,则不会死锁--但由于打印机等资源显然不能被共享,该方法不好。 2. 破坏请求并保持条件,预先分配全部资源,运行时才投入使用,并一直独享,系统资源被浪费。 3. 破坏不可剥夺条件,保持不可剥夺资源的进程,在请求新资源未被满足时,必须先释放保持的资源,需要时重新申请,反复申请和释放增加了开销。 4. 破坏循环等待条件,采用顺序资源分配,用编号分配资源,按次序操作会造成浪费。
静止就绪:这个也叫做挂起就绪,是指进程被对换到辅存时的就绪状态,是不能被直接调度的状态,只有当主存中没有活跃就绪态进程,或者是挂起就绪态进程具有更高的优先级,系统将把挂起就绪态进程调回主存并转换为活跃就绪。
活动就绪:进程在主存并且可被调度的状态。
静止睡眠(阻塞):是指进程对换到辅存时的阻塞状态,一旦等待的事件产生便进入静止就绪状态。
活动睡眠(阻塞):是指进程已在主存,一旦等待的事件产生便进入活跃就绪状态。
正在执行的进程由于其时间片用完被暂停执行,此时进程应从执行状态变为活动就绪状态;
处于静止睡眠状态的进程,在进程等待的事件出现后,应变为静止就绪状态;
若进程正处于执行状态时,因终端的请求而暂停下来以便研究其运行情况,这时进程应转变为静止就绪状态;若进程已处于睡眠状态,则此时应转变为静止睡眠状态。
高响应比优先算法是一种综合考虑任务长度和等待时间的调度算法,响应比=(等待时间+执行时间)/执行时间。高响应比优先算法在等待时间相同的情况下,作业执行时间越短则响应比越高,满足短任务优先。随着长任务的等待时间增加,响应比也会变大,执行机会也就增大,所以不会发生饥饿现象。先来先服务和时间片轮转不符合短任务优先,非抢占式短任务优先会产生饥饿现象。
select和epoll这两个机制都是多路I/O机制的解决方案,select为POSIX标准中的,而epoll为Linux所特有的。
epoll的最大好处是不会随着FD的数目增长而降低效率,在select中采用轮询处理,其中的数据结构类似一个数组的数据结构,而epoll是维护一个队列,直接看队列是不是空就可以了。
nginx就是使用epoll来实现I/O复用支持高并发,目前在高并 发的场景下,nginx越来越收到欢迎。
select的一 个缺点在于单个进程能够监视的文件描述符的数量存在最大限制
epoll:
(1)IO的效率不会随着监视fd的数量的增长而下降。epoll不同于select和poll轮询的方式,而是通过每个fd定义的回调函数来实现的。只有就绪的fd才会执行回调函数;
(2)支持电平触发和边沿触发(只告诉进程哪些文件描述符刚刚变为就绪状态,它只说一遍,如果我们没有采取行动,那么它将不会再次告知,这种方式称为边缘触发)两种方式,理论上边缘触发的性能要更高一些,但是代码实现相当复杂。
(3)有着良好的就绪事件通知机制
select:
(1)单个进程可监视的fd数量受到了限制,在32位机器上,他所能管理的fd数量最大为1024;
(2)对socket进行扫描时是线性扫描,当socket文件描述符数量变多时,大量的时间是被白白浪费掉的。
建立符号链接时,引用计数值直接复制;建立硬链接时,引用计数值加1。删除文件时,删除操作对于符号链接是不可见的,这并不影响文件系统,当以后再通过符号链接访问时,发现文件不存在,直接删除符号链接;但对于硬链接则不可以直接删除,引用计数值减1,若值不为0,则不能删除此文件,因为还有其他硬链接指向此文件。
当建立F2时,F1和F2的引用计数值都为1。当再建立F3时,F1和F3的引用计数值就都变成了2。当后来删除F1时,F3的引用计数值为2-1=1,F2的引用计数值一直不变。
SPOOLing技术的特点:
(1)提高了I/O速度.从对低速I/O设备进行的I/O操作变为对输入井或输出井的操作,如同脱机操作一样,提高了I/O速度,缓和了CPU与低速I/O设备速度不匹配的矛盾.
(2)设备并没有分配给任何进程.在输入井或输出井中,分配给进程的是一存储区和建立一张I/O请求表.
(3)实现了虚拟设备功能.多个进程同时使用一独享设备,而对每一进程而言,都认为自己独占这一设备,不过,该设备是逻辑上的设备.
进程的三种基本状态
进程在运行中不断地改变其运行状态。通常,一个运行进程必须具有以下三种基本状态。
就绪(Ready)状态
当进程已分配到除CPU以外的所有必要的资源,只要获得处理机便可立即执行,这时的进程状态称为就绪状态。
执行(Running)状态
当进程已获得处理机,其程序正在处理机上执行,此时的进程状态称为执行状态。
阻塞(Blocked)状态
正在执行的进程,由于等待某个事件发生而无法执行时,便放弃处理机而处于阻塞状态。引起进程阻塞的事件可有多种,例如,等待I/O完成、申请缓冲区不能满足、等待信件(信号)等。
在没有其他进程可以执行时(如所有进程都在阻塞状态),通常会自动执行系统的空闲进程。
线程是指进程内的一条执行线路,或者说是进程中可执行代码的单独单元,它是操作系统的基本调度单元。一个进程至少有一个线程,即主线程,也可以有多个线程协同工作。进程从主线程开始执行,进而可以创建一个或多个附加线程来执行该进程内的并发任务,这就是基于线程的多任务。
进程中的制约关系由2种:
第一种是直接制约关系,两个进程之间需要在某些点上交换数据时所产生的制约关系.
第二种是间接制约关系,当两个进程竞争同一资源时所产生的相互制约关系.
PV操作:1)semaphore的取值必须大于或等于0。0表示当前已没有空闲资源,而正数表示当前空闲资源的数量;2) semaphore的取值可正可负,负数的绝对值表示正在等待进入 临界区 的进程个数。
P原语:P是荷兰语Proberen(测试)的首字母。为阻塞原语,负责把当前进程由运行状态转换为阻塞状态,直到另外一个进程唤醒它。操作为:申请一个空闲资源(把信号量减1),若成功,则退出;若失败,则该进程被阻塞;
V原语:V是荷兰语Verhogen(增加)的首字母。为唤醒原语,负责把一个被阻塞的进程唤醒,它有一个参数表,存放着等待被唤醒的进程信息。操作为:释放一个被占用的资源(把信号量加1),如果发现有被阻塞的进程,则选择一个唤醒之。
虚拟内存是计算机系统内存管理的一种技术。它使得应用程序认为它拥有连续可用的内存,使得每个进程看到的内存空间一致。
基于索引结点的共享方式,即硬链接。 如当用户A创建一个新文件时,它便是该文件的所有者,此时将count置为1。当有用户 B要共享此文件时,在用户B的目录中增加一个目录项,并设置一指针指向该文件的索引结点。此时,文件主仍然是用户A,count=2。如果用户A不再需要此文件,不能将文件直接删除。若直接删除了该文件,也必然删除了该文件的索引结点,这样便会使用户B的指针悬空。
操作系统是一个庞大的管理控制程序,大致包括5个方面的管理功能:进程与处理机管理、作业管理、存储管理、设备管理、文件管理。目前微机上常见的操作系统有DOS。
I/O控制方式:轮询方式、中断处理方式、直接内存存取方式(DMA)、通道方式。
通道是一个用来控制外部设备工作的硬件机制,相当于一个功能简单的处理机。通道是独立于CPU的、专门负责数据的输入输出传输工作的处理器,它对外部设备实施统一管理,代替CPU对I/O操作进行控制,从而使I/O操作可以与CPU并行工作。通道是实现计算机和传输并行的基础,以提高整个系统的效率。
所谓的层次结构,就是把操作系统所有的功能模块按照功能调用次序分别排成若干层,各层之间的模块只有单向调用关系(例如,只允许上层或外层模块调用下层或内层模块)。分层的优点是: (1)把功能实现的无序性改成有序性,可显著提高设计的准确性。 (2)把模块问的复杂依赖关系改为单向依赖关系,即高层软件依赖于低层软件。 E.W.Dijkstra于1968年发表的THE多道程序设计系统第一次提出了操作系统的分层结构方法。整个THE系统分为6层。
信号量机制可能会导致进程自我阻塞,当进程在中断上下文中阻塞,一直不能开中断,且关闭中断期间CPU不例行检查中断信号(CPU每执行完一条指令都会检查是否有中断信号需要处理),会导致处理机一直被该进程占用。原语一气呵成的原子特性就是通过关中断和开中断两个特权指令实现的,这也就是原语不会被中断的原因。
- 存储周期:连续启动两次读或写操作所需最小的间隔时间。
- 存取时间:指的是CPU读或写内存内数据的过程时间。
- 存储时间:属于存取时间的存操作数据的过程时间。(注意和存取时间的区分)
- 访问周期:存储器进行一次“读”或“写”操作所需的时间间隔(注意和存储时间的区分)。
sleep()是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep()不会释放对象锁。
wait()是Object类的方法,对此对象调用wait()方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify()方法或notifyAll()后本线程才进入对象锁定池准备获得对象锁进入运行状态。
临界区是指一个访问共用资源的程序片段,而这些共用资源又无法同时被多个线程访问的特性。
进程进入临界区的调度原则是:
1、如果有若干进程要求进入空闲的临界区,一次仅允许一个进程进入。
2、任何时候,处于临界区内的进程不可多于一个。如已有进程进入自己的临界区,则其它所有试图进入临界区的进程必须等待。
3、进入临界区的进程要在有限时间内退出,以便其它进程能及时进入自己的临界区。
4、如果进程不能进入自己的临界区,则应让出CPU,避免进程出现“忙等”现象。
I/O控制方式:轮询方式、中断处理方式、直接内存存取方式(DMA)、通道方式。
通道是一个用来控制外部设备工作的硬件机制,相当于一个功能简单的处理机。通道是独立于CPU的、专门负责数据的输入输出传输工作的处理器,它对外部设备实施统一管理,代替CPU对I/O操作进行控制,从而使I/O操作可以与CPU并行工作。通道是实现计算机和传输并行的基础,以提高整个系统的效率。
值类型与引用类型区别:
值类型 | 引用类型 | |
---|---|---|
存储方式 | 直接存储数据本身 | 存储的是数据的引用,数据存储在数据堆中 |
内存分配 | 分配在栈中的 | 分配在堆中 |
效率 | 效率高,不需要地址转换 | 效率较低,需要进行地址转换 |
内存回收 | 使用完后立即回收 | 使用完后不立即回收,而是交给GC处理回收 |
赋值操作 | 创建一个新对象 | 创建一个引用 |
类型扩展 | 不易扩展,所有值类型都是密封(seal)的,所以无法派生出新的值类型 | 具有多态的特性方便扩展 |
实例分配 | 通常是在线程栈上分配的(静态分配),但是在某些情形下可以存储在堆中 | 总是在进程堆中分配(动态分配) |
临界区是指一个访问共用资源的程序片段,而这些共用资源又无法同时被多个线程访问的特性。
进程进入临界区的调度原则是:
1、如果有若干进程要求进入空闲的临界区,一次仅允许一个进程进入。
2、任何时候,处于临界区内的进程不可多于一个。如已有进程进入自己的临界区,则其它所有试图进入临界区的进程必须等待。
3、进入临界区的进程要在有限时间内退出,以便其它进程能及时进入自己的临界区。
4、如果进程不能进入自己的临界区,则应让出CPU,避免进程出现“忙等”现象。
进程调度取决于操作系统,执行先后可能作系统改变,如window存在一个优先级推动器,如果某优先级高的进程执行次数过多,会被越过将资源分配给其他进程。
- 互斥条件:指进程对所分配到的资源进行排他性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其他进程请求资源,则只能等待,直至占有资源的进程用毕释放。简而言之,即资源不能共享,只能由一个资源使用。
- 请求与保持条件:指进程已经至少保持一个资源,但又提出来对新的资源的请求,而该资源已经被其它进程占用,此时请求进程阻塞,但又对自己已获得的资源保持不放。
- 非剥夺条件:指进程已经获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己来释放。
- 循环等待条件:指发生进程死锁时,必然存在一个由进程组成的资源环形链。系统中的若干进程组成环路,该环路中的每个进程都在等待相邻的进程正占用的资源。
安全状态是指系统能按某种顺序来为每个进程分配所需要的资源,使每个进程都可以顺序完成。
若系统不存在这样一个安全序列,则称系统处于不安全状态。
进入了不安全状态仅说明当前情况下的资源分配出现不安全的因素,而随着时间的推移,资源的分配可能会发生变化的,原来占有临界资源的进程可能因为某些原因自己阻塞起来,并放弃已拥有的临界资源跑到阻塞队列后排队,这样原来请求这些临界资源的进程就有可能满足其需要而可以执行。
意图考察程序和进程的区别:
- 进程由程序和数据两部分组成,进程是竞争计算机系统有限资源的基本单位,也是进程处理机调度的基本单位。
- 程序是静态的概念;进程是程序在处理机上一次执行的过程,是动态的概念。
- 一个程序可以作为多个进程的运行程序;一个进程也可以运行多个程序。
抢占式会引起系统的开销更大。
可抢占式调度是严格保证任何时刻,让具有最高优先数(权)的进程占有处理机运行,因此增加了处理机调度的时机,引起为退出处理机的进程保留现场,为占有处理机的进程恢复现场等时间(和空间)开销增大。
共享文件夹的访问权限包括 读取,修改,完全控制
中断类型分为如下两大类:
一、强迫性中断:正在运行的程序所不期望的,来自硬件故障或外部请求。
1、I/O 中断:来自外部设备通道;
2、程序性中断:运行程序本身的中断,如 溢出、缺页中断、缺段中断、地址越界。
3、时钟中断
4、控制台中断
5、硬件故障
二、自愿性中断:用户在编程时要求操作系统提供的服务,使用访管指令或系统调用使中断发生。也称为访管中断。包括执行I/O,创建进程,分配内存,信号量操作,发送/接收消息。
1.强占式:现行进程在运行过程中,如果有重要或紧迫的进程到达(其状态必须为就绪),则现运行进程将被迫放弃处理机 ,系统将处理机立刻分配给新到达的进程。
2. 静态优先权 :在创建进程时确定的,优先权在进程的整个运行期间保持不变。
3. 动态优先权 :在创建进程时所赋予的优先权,是可以随进程的推进或随其等待时间的增加而改变的,以便获得更好的调度性能,该优先权会随着等待的时间增长而增长。
backtrace bt 打印当前的函数调用栈的所有信息。
info threads 显示当前可调试的所有线程,每个线程会有一个GDB为其分配的ID,后面操作线程的时候会用到这个ID。 前面有*的是当前调试的线程。
set scheduler-locking 线程调试 显示线程状态,off 不锁定任何线程
info break 可列出所有断点信息,info break 后也可设置要查看的break num
- 直接寻址:在指令格式的地址的字段中直接指出操作数在内存的地址,而不需要经过某种变换。
- 立即寻址:将操作数紧跟在操作码后面,与操作码一起放在指令代码段中,在程序运行时,程序直接调用该操作数,而不需要到其他地址单元中去取相应的操作数。
- 间接寻址:间接寻址是相对于直接寻址而言的,指令地址字段的形式地址不是操作数的真正地址,而是操作数地址的指示器。
- 变址寻址:变址寄存器的内容(通常是首地址)与指令地址码部分给出的地址(通常是位移量)之和作为操作数的地址来获得所需要的操作数就称为变址寻址。
1、先来先服务算法(FCFS)First Come First Service
这是一种比较简单的磁盘调度算法。它根据进程请求访问磁盘的先后次序进行调度。此算法的优点是公平、简单,且每个进程的请求都能依次得到处理,不会出现某一进程的请求长期得不到满足的情况。此算法由于未对寻道进行优化,在对磁盘的访问请求比较多的情况下,此算法将降低设备服务的吞吐量,致使平均寻道时间可能较长,但各进程得到服务的响应时间的变化幅度较小。
先来先服务 (125)86.147.91.177.94.150.102.175.130
2、最短寻道时间优先算法(SSTF) Shortest Seek Time First
该算法选择这样的进程,其要求访问的磁道与当前磁头所在的磁道距离最近,以使每次的寻道时间最短,该算法可以得到比较好的吞吐量,但却不能保证平均寻道时间最短。其缺点是对用户的服务请求的响应机会不是均等的,因而导致响应时间的变化幅度很大。在服务请求很多的情况下,对内外边缘磁道的请求将会无限期的被延迟,有些请求的响应时间将不可预期。
最短寻道时间优先(125)130.147.150.175.177.102.94.91.86
3、扫描算法(SCAN)电梯调度
扫描算法不仅考虑到欲访问的磁道与当前磁道的距离,更优先考虑的是磁头的当前移动方向。例如,当磁头正在自里向外移动时,扫描算法所选择的下一个访问对象应是其欲访问的磁道既在当前磁道之外,又是距离最近的。这样自里向外地访问,直到再无更外的磁道需要访问才将磁臂换向,自外向里移动。这时,同样也是每次选择这样的进程来调度,即其要访问的磁道,在当前磁道之内,从而避免了饥饿现象的出现。由于这种算法中磁头移动的规律颇似电梯的运行,故又称为电梯调度算法。此算法基本上克服了最短寻道时间优先算法的服务集中于中间磁道和响应时间变化比较大的缺点,而具有最短寻道时间优先算法的优点即吞吐量较大,平均响应时间较小,但由于是摆动式的扫描方法,两侧磁道被访问的频率仍低于中间磁道。
电梯调度(125)102.94.91.86.130.147.150.175.177
4、循环扫描算法(CSCAN)
循环扫描算法是对扫描算法的改进。如果对磁道的访问请求是均匀分布的,当磁头到达磁盘的一端,并反向运动时落在磁头之后的访问请求相对较少。这是由于这些磁道刚被处理,而磁盘另一端的请求密度相当高,且这些访问请求等待的时间较长,为了解决这种情况,循环扫描算法规定磁头单向移动。例如,只自里向外移动,当磁头移到最外的被访问磁道时,磁头立即返回到最里的欲访磁道,即将最小磁道号紧接着最大磁道号构成循环,进行扫描。
循环扫描 (125)130.147.150.175.177.86.91.94.102
- **进程互斥:**两个或两个以上的进程,不能同时进入关于同一组共享变量的临界区域,否则可能发生与时间有关的错误,这种现象被称作进程互斥。也就是说,一个进程正在访问临界资源,另一个要访问该资源的进程必须等待。
- 临界资源:系统中某些资源一次只允许一个进程使用(也叫临界资源、互斥资源、共享资源)。
- 临界区(互斥区):各个进程中对某个临界资源(共享变量)试试操作的程序片段。
线程通常被定义为一个进程中代码的不同执行路线。
从实现方式上划分,线程有两种类型:“用户级线程”和“内核级线程”。
用户线程指:不需要内核支持而在用户程序中实现的线程,其不依赖于操作系统核心,应用进程利用线程库提供创建、同步、调度和管理线程的函数来控制用户线程。这种线程甚至在象 DOS 这样的操作系统中也可实现,但线程的调度需要用户程序完成,这有些类似 Windows 3.x 的协作式多任务。
内核级线程:另外一种则需要内核的参与,由内核完成线程的调度。其依赖于操作系统核心,由内核的内部需求进行创建和撤销,这两种模型各有其好处和缺点。
用户线程不需要额外的内核开支,并且用户态线程的实现方式可以被定制或修改以适应特殊应用的要求,但是当一个线程因 I/O 而处于等待状态时,整个进程就会被调度程序切换为等待状态敏感词线程得不到运行的机会;而内核线程则没有各个限制,有利于发挥多处理器的并发优势,但却占用了更多的系统开支。 Windows NT和OS/2支持内核线程。Linux 支持内核级的多线程.
操作系统分类
批 处 理操作系 统 (Batch Processing Operating System )
它的特点是:多道和成批处理。
分 时 操作系 统 (Time Sharing Operating System, 简 称 TSOS)
分时系统具有多路性、交互性、“独占”性和及时性的特征。多路性指,伺时有
多个用户使用一台计算机,宏观上看是多个人同时使用一个CPU,微观上是多个人在不同时刻轮流使用CPU。交互性是指,用户根据系统响应结果进一步提出新请求(用户直接干预每一步)。“独占”性是指,用户感觉不到计算机为其他人服务,就像整个系统为他所独占。及时性指,系统对用户提出的请求及时响应。
实时操作系统 (Real Time Operating System, 简 称 RTOS)
实时操作系统要追求的目标是:对外部请求在严格时间范围内做出反应,有高可靠性和完整性。其主要特点是资源的分配和调度首先要考虑实时性然后才是效率。此外,实时操作系统应有较强的容错能力。
网 络 操作系 统 (Network Operating System , 简 称 NOS )
通常运行在服务器上的操作系统,是基于计算机网络的,其目标是相互通信及资源共享。
分布式操作系 统 (Distributed Software Systems)
是为分布计算系统配置的操作系统。大量的计算机通过网络被连结在一起,可以获得极高的运算能力及广泛的数据共享。
分布式操作系统是网络操作系统的更高形式,它保持了网络操作系统的全部功能,而且还具有透明性、可靠性和高性能等。网络操作系统和分布式操作系统虽然都用于管理分布在不同地理位置的计算机,但最大的差别是:网络操作系统知道确切的网址,而分布式系统则不知道计算机的确切地址;分布式操作系统负责整个的资源分配,能很好地隐藏系统内部的实现细节,如对象的物理位置等。这些都是对用户透明的。
1、fork
一个程序一调用fork函数,系统就为一个新的进程准备了前述三个段,首先,系统让新的进程与旧的进程使用同一个代码段,因为它们的程序还是相同的,对于数据段和堆栈段,系统则复制一份给新的进程,这样,父进程的所有数据都可以留给子进程,但是,子进程一旦开始运行,虽然它继承了父进程的一切数据,但实际上数据却已经分开,相互之间不再有影响了,也就是说,它们之间不再共享任何数据了。而如果两个进程要共享什么数据的话,就要使用另一套函数(shmget,shmat,shmdt等)来操作。现在,已经是两个进程了,对于父进程,fork函数返回了子程序的进程号,而对于子程序,fork函数则返回零,这样,对于程序,只要判断fork函数的返回值,就知道自己是处于父进程还是子进程中。事实上,目前大多数的unix系统在实现上并没有作真正的copy。一般的,CPU都是以“页”为单位分配空间的,象INTEL的CPU,其一页在通常情况下是4K字节大小,而无论是数据段还是堆栈段都是由许多“页”构成的,fork函数复制这两个段,只是“逻辑”上的,并非“物理”上的,也就是说,实际执行fork时,物理空间上两个进程的数据段和堆栈段都还是共享着的,当有一个进程写了某个数据时,这时两个进程之间的数据才有了区别,系统就将有区别的“页”从物理上也分开。系统在空间上的开销就可以达到最小。
2、exec
一个进程一旦调用exec类函数,它本身就“死亡”了,系统把代码段替换成新的程序的代码,废弃原有的数据段和堆栈段,并为新程序分配新的数据段与堆栈段,唯一留下的,就是进程号,也就是说,对系统而言,还是同一个进程,不过已经是另一个程序了。不过exec类函数中有的还允许继承环境变量之类的信息,这个通过exec系列函数中的一部分函数的参数可以得到。
面向块 :将信息保存在块中,传输时一次传一块,例如磁盘、usb智能卡等。
面向流:将信息以字节流的方式输入输出数据,没有块结构,例如终端, 打印机 等。
顺序文件是指按记录进入文件的先后顺序存放、其逻辑顺序和物理顺序一致的文件。
一切存储在顺序存取存储器(如磁带)上的文件,都只能是顺序文件。
发生死锁的必要条件:
1.互斥:某段时间内,某一资源只能被一个进程占用
2.请求和保持:某一进程在无法申请到资源时,却对自己已经占有的资源保持不放;
3.不可抢占:未用毕的资源不可被抢占;
4.循环等待:发生死锁的进程组成一个进程-资源的循环链;
对于PC机而言,显示存储器、字符发生器置于显示卡(显示适配器)上。对于多用户的计算机终端,扫描控制逻辑、显示存储器、字符发生器均置于终端设备本身的控制器中。
SRAM:是英文Static RAM的缩写,它利用晶体管来存储数据,不需要刷新电路即能保存它内部存储的数据**。与DRAM相比,SRAM的速度快,但是集成度低(即在相同面积中SRAM的容量要比DRAM的小)。
DRAM(动态随机存储器):**是最为常见的计算机系统的内部存储器。DRAM使用电容存储,为了保持数据,必须隔一段时间刷新(refresh)一次,如果存储单元没有被刷新,存储的信息就会丢失。
ROM:分为EPROM和EEPROM两种**
EPROM(可擦除可编程ROM):**芯片可重复擦除和写入数据。EPROM芯片有一个很明显的特征,在其正面的陶瓷封装上开有一个玻璃窗口,透过该窗口,可以看到其内部的集成电路,紫外线透过该孔照射内部芯片就可以擦除其内的数据。EPROM内数据的写入要用专用的编程器,并且往芯片中写内容时必须要加一定的编程电压(VPP=12~24V,随不同的芯片型号而定)。
EEPROM(电可擦可编程只读存储器):是一种掉电后数据不丢失的存储芯片。EEPROM可以在电脑上或专用设备上擦除已有信息,重新编程。它常用在接口卡中,用来存放硬件设置数据,也常用在防止软件非法拷贝的“硬件锁”上面。
**D选项——双稳态触发器:**静态存储器依靠双稳态触发器的两个稳定状态保存信息。每个双稳态电路存储一位二进制代码0或1,一块存储芯片上包含许多个这样的双稳态电路。双稳态电路是有源器件,需要电源才能工作,只要电源正常,就能长期稳定的保存信息,所以称为静态存储器。如果断电,信息将会丢失,属于挥发性存储器,或称易失性。
对进程调度算法中,排队等待时间最长的作业即是最先进入等待队列的作业;
短作业优先算法是根据作业运行时间长短来衡量的;
优先级调度算法分为静态优先权和动态优先权;
响应比高优先算法其实也是一种优先级调度,其优先权权值相当于响应比,响应比等于作业响应时间除以作业要求服务的时间。
面向用户的准则
通常把周转时间短作为评价批处理系统的性能
响应时间此准则是分时操作系统中选择进程调度的重要准则
截止时间的保证这是评价实时系统性能的重要指标
优先权准则
面向系统原则
( 1 )系统吞吐量高
( 2 )处理机利用率好
( 3 )各类资源平衡利用;处理机,内存, I/O 设备等
随机存取存储器(英语:Random Access Memory,缩写:RAM),也叫主存,是与CPU直接交换数据的内部存储器。它可以随时读写(刷新时除外),而且速度很快,通常作为操作系统或其他正在运行中的程序的临时数据存储介质。RAM工作时可以随时从任何一个指定的地址写入(存入)或读出(取出)信息。它与ROM的最大区别是数据的易失性,即一旦断电所存储的数据将随之丢失。RAM在计算机和数字系统中用来暂时存储程序、数据和中间结果。
ROM 是 read only memory的简称,表示只读存储器。只读存储器(ROM)是一种在正常工作时其存储的数据固定不变,其中的数据只能读出,不能写入,即使断电也能够保留数据,要想在只读存储器中存入或改变数据,必须具备特定的条件。按存取信息的不同方式,存储器可以分为随机存取存储器(RAM)和非随机存取存储器。只读存储器就属于非随机存取存储器。
顺序执行的特性有如下三点。 (1)顺序性:程序顺序执行时,其执行过程可看做一系列严格按程序规定的状态转移的过程,也就是每执行一条指令,系统将从上一个执行状态转移到下一个执行状态,且上一条指令的执行结束是下一条指令执行开始的充分必要条件。 (2)封闭性:程序执行得到的最终结果由给定的初始条件决定,不受外界因素的影响。 (3)无关性(可再现性):顺序执行的最终结果可再现是指运行结果与执行速度无关。只要输人的初始条件相同,则无论何时重复执行该程序都会得到相同的结果。
断定方式属于微地址的形成方法之一,根据机器状态决定下一条微指令的地址,下一条微指令的地址包含在当前微指令的代码中。为了实现多路分支,将微地址的若干低位作为可断定的部分,相应地在微指令的顺序控制字段中设置或注明断定条件,即微地址低位段的形成条件。
(1) 进程间通信方法有:文件映射、共享内存、匿名管道、命名管道、邮件槽、剪切板、动态数据交换、对象连接与嵌入、动态连接库、远程过程调用等
(2) 事件、临界区、互斥量、信号量可以实现线程同步
进程同步
进程同步也是进程之间直接的制约关系,是为完成某种任务而建立的两个或多个线程,这个线程需要在某些位置上协调他们的工作次序而等待、传递信息所产生的制约关系。进程间的直接制约关系来源于他们之间的合作。
比如说进程A需要从缓冲区读取进程B产生的信息,当缓冲区为空时,进程B因为读取不到信息而被阻塞。而当进程A产生信息放入缓冲区时,进程B才会被唤醒。概念如图所示。
进程互斥
进程互斥是进程之间的间接制约关系。当一个进程进入临界区使用临界资源时,另一个进程必须等待。只有当使用临界资源的进程退出临界区后,这个进程才会解除阻塞状态。
比如进程B需要访问打印机,但此时进程A占有了打印机,进程B会被阻塞,直到进程A释放了打印机资源,进程B才可以继续执行。概念如图所示。
**1.**伙伴算法中,一个很小的块往往会阻碍一个大块的合并,一个系统中,对内存块的分配,大小是随机的,一片内存中仅一个小的内存块没有释放,旁边两个大的就不能合并。
**2.**伙伴算法是按2的幂次方大小进行分配内存块,这样避免把大的内存块拆的太碎,更重要的是使分配和释放过程迅速。但是如果所需内存大小不是2的幂次方,就会有部分页面浪费。有时还很严重。比如原来是1024个块,申请了16个块,再申请600个块就申请不到了,因为已经被分割了。
**3.**Buddy(伙伴的定义):
满足以下三个条件的称为伙伴:
1)两个块大小相同;
2)两个块地址连续;
3)两个块必须是同一个大块中分离出来的;
**4.**另外拆分和合并涉及到 较多的链表和位图操作,开销还是比较大
- 工作集是指一个进程当前正在使用的页面集合。
- 依据进程过去某段时间间隔的运行行为,预测和近似其将来某段时间间隔内的运行行为,确保在进程继续运行前,它的工作集就已经在内存,这就是工作集模型。
首先需要知道操作系统维护四种表:I/O 表、内存表、文件表、进程表。操作系统需要管理 I/O 等资源,进程执行需要使用内存等。题面中描述的是操作系统管理进程和资源,所以四种表都需要。
TLB(Translation Lookaside Buffer)转换检测缓冲区是一个内存管理单元,用于改进虚拟地址到物理地址转换速度的缓存。
PTBR:页表基址寄存器(pagetablebaseregister,PTBR),CPU中的一个控制寄存器
**系统态,即管态或核心态**,是**操作系统管**理的程序执行时,机器所处的状态。
**用户态,即目态,是用户程序执行时机器所处的状态。**
为什么要划分用户态和系统态?
一个最主要原因是要把用户程序和系统程序区分开,以利于程序的共享和保护。显然,这也是以增加系统复杂度和系统开销为代价的。
时钟中断处理程序都属于中断,在系统态执行;
****进程创建原语、进程调度程序属于系统调用,在系统态执行;
命令解释程序属于命令接口,在用户态执行。
程序在装入内存之前,通常为逻辑地址形式,有时甚至在装入内存后,程序仍为相对地址形式。为了保证 CPU 执行程序指令时能正确访问存储单元,需要将用户程序中的逻辑地址转换为可由机器直接寻址 的物理地址,这一过程称为地址映射。
动态链接是指不对那些组成程序的目标文件进行链接,等到程序要运行时才进行链接。也就是说,把链接这个过程推迟到了运行时再进行。
- 用户层I/O软件:实现与用户交互的接口,用户可以直接调用在用户层提供的、与I/O操作有关的库函数,对设备进行操作。
- 设备独立软件:用于实现用户程序与设备驱动器的统一接口、设备命令、设备保护以及设备分配与释放等,同时为设备管理和数据传送提供必要的存储空间。
- 设备驱动程序:与硬件直接相关,负责具体实现系统对设备发出的操作指令,驱动I/O设备工作的驱动程序。
- 中断处理程序:用于保护被中断进程的CPU环境,转入相应的中断处理程序进行处理,处理完并恢复被中断进程的现场后,返回到被中断进程。
简而言之,第1层是用户和I/O软件之间,第2层是I/O软件和设备驱动器之间,第3层是设备驱动器与硬件之间,最后1层那保存中断的。
- **并发:**是指两个或多个事件在同一时间间隔内发生。操作系统的并发性是指计算机系统中同时存在多个运行着的程序,因此它应该具有处理和调度多个程序同时执行的能力。
- **共享:**是指系统中的资源(硬件资源和信息资源)可以被多个并发执行的程序共同使用,而不是被其中一个独占。资源共享有两种方式:互斥访问和同时访问。
- 异步:在多道程序环境下,允许多个程序并发执行,但由于资源有限,进程的执行不是一贯到底。而是走走停停,以不可预知的速度向前推进,这就是进程的异步性。异步性使得操作系统运行在一种随机的环境下,可能导致进程产生与时间有关的错误。但是只要运行环境相同,操作系统必须保证多次运行程序,都获得相同的结果。
- **虚拟:**虚拟性是一种管理技术,把物理上的一个实体变成逻辑上的多个对应物,或把物理上的多个实体变成逻辑上的一个对应物的技术。采用虚拟技术的目的是为用户提供易于使用、方便高效的操作环境。
作业在执行中发生了缺页中断,经系统将该缺页调入内存后,应继续执行( 被中断的指令 )。
缺页中断机构:
在请求分页系统中,每当要访问的页面不存在时,便产生一缺页中断,请求OS将所缺之页调入内存。 缺页中断作为中断同样经历:保护CPU环境、分析中断原因、转入缺页中断,恢复CPU环境等步骤。
缺页中断与其他中断的区别:
(1)在执行期间产生和处理中断信号。通常CPU是在一条指令执行完后,才检查是否有中断请求到达。若有,便去响应,否则继续执行下条指令。但缺页中断是在指令执行期间或数据不在内存时所产生和处理的。
(2)一条指令在执行期间,可能产生多次缺页中断。 有可能执行一个指令时,指令本身跨越两个页面,访问的数据块也不在同一个页面,所以,系统中硬件机构应该能保存多次中断时的状态,并保证最后能返回到中断前产生缺页中断指令处继续执行。
连续文件(顺序文件)
定义:将一个文件中逻辑上连续的信息存放到存储介质的依次相邻的块上便形成顺序结构,这类文件叫连续文件,又称顺序文件。
优点:简单; 支持顺序存取和随机存取(直接存取);顺序存取速度快;所需的磁盘寻道次数和寻道时间最少。
缺点:建立文件前需要能预先确定文件长度,以便分配存储空间;修改、插入和增生文件记录有困难;对直接存储器作连续分配,会造成少量空闲块的浪费。
链接文件
定义:一个文件的信息存放在若干不连续的物理块中,各块之间通过指针连接,前一个物理块指向下一个物理块。
优点:提高了磁盘空间利用率,不存在外部碎片问题。有利于文件插入和删除。有利于文件动态扩充。
缺点:存取速度慢,不适于随机存取。可靠性问题,如指针出错。更多的寻道次数和寻道时间。链接指针占用一定的空间。
索引文件
定义:一个文件的信息存放在若干不连续物理块中,系统为每个文件建立一个专用数据结构----索引表,表中每一栏目指出文件信息所在的逻辑块号和与之对应的物理块号。索引表的物理地址则由文件说明信息项给出。
索引项的组织:
稠密索引:每个逻辑纪录设置一个索引项。
稀疏索引:一组逻辑纪录设置一个索引项。
优点:保持了链接结构的优点,又解决了其缺点:即能顺序存取,又能随机存取。满足了文件动态增长、插入删除的要求。也能充分利用外存空间。
缺点:较多的寻道次数和寻道时间。索引表本身带来了系统开销 如:内外存空间,存取时间。
什么是TCP粘包拆包?为什么会出现粘包拆包?如何在应用层面解决此问题?
TCP是流式传输协议,数据传输时候没有边界,就如同在Linux下进行socket网络通信编程时,创建套接字使用函数socket()时候,有一个参数我们选用流式传输时候,系统就会默认是TCP协议。
而流式传时,因为数据之间是没有边界的,所以会出现粘包现象。
请大致描述一下BIO,AIO和NIO的区别?
BIO:同步阻塞式IO,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。 NIO:同步非阻塞式IO,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。 AIO:异步非阻塞式IO,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理。
HTTP响应报文由三部分组成, 响应行:由报文协议及版本、状态码及描述组成。 响应头:和请求头一样,由属性组成。 响应体:是服务器返回给客户端的文本信息。
RIP(Routing Information Protocol,路由信息协议) 属于网络层
IP、IPX都属于网络层
PPP 点对点协议(Point to Point Protocol,PPP)属于数据链路层
网络层常见协议:ARP、IP(v4 v6)、ICMP、RIP、OSPF
内存回收方式有三种: 基于LRU(Least Recently Used)算法,回收缓存;基于Swap机制,回收不常访问的匿名页;基于OOM(Out of Memory)机制,杀掉占用大量内存的进程。
malloc()对应到系统调用上两种实现方式,分别为brk()和mmap()来分配;小块内存(小于128K)使用brk()来分配,大块内存(大于 128K),则直接使用内存映射mmap()
LRU 回收算法,实际上维护着 active 和 inactive 两个双向链表,其中:active记录活跃的内存页;inactive 记录非活跃的内存页。
cat /proc/meminfo | grep -i active | sort可查看active、inactive大小
top可查看CPU状态,但是区分不出进程的用户态CPU和内核态CPU
pidstat可区分查看用户态CPU使用率、内核态PU使用率、运行虚拟机、等待CPU使用率和总的CPU使用率
iostat可查看CPU、网卡、磁盘等设备的活动情况, 负载信息
vmstat命令可以报告关于进程、内存、I/O等系统整体运行状态
netstat -anp 查看网络中占用的端口情况
awk '{print $5}'显示出目标ip port
awk -F是按照指定字符切割,已显示具体的ip,而不是ip和端口(c没有分割)
要统计最多的ip的话,就要去重和排序(B没有去重)
sort命令
-c 检查文件是否已经按照顺序排序
-d 当指定要查找的是目录而非文件时,必须使用这项参数,否则grep指令将回报信息并停止动作
-n 在显示符合样式的那一行之前,标示出该行的列数编号
-r 类型-d(这个参数不影响结果)
程序的内存分配
1、栈区(stack)——由编译器自动分配和释放,存放函数的参数,局部变量等。
2、堆区(heap)——一般由程序员分配和释放,若程序员不释放,程序结束可能由OS回收。容易产生内存碎片。
3、全局区(静态区)(static)——初始化的全局变量与静态变量在一块区域,未初始化的在相邻的另一块区域。程序结束后由系统释放
4、文字常量区——常量字符串放在这里,程序结束后由系统释放。
5、程序代码区——存放函数体的二进制代码