4-15 OS(线程,用户态,内核态,页) 数据库(原子性,日志) JAVA(I/O)

在internet services课上老师说到Capriccio 是用户模式下的thread library,OS课里第2个project也是实现一个用户模式下的线程库。之前用过POSIX库,我知道这是在内核模式里的线程库,那就表示由内核来创建、调度线程吧。但内核就像一个黑盒,一直不明白它做了什么,怎么做到的。Modern Operating System有章讲user space和kernel space控制线程。

在user space:所有线程的管理都在用户区,内核不知道多线程的存在。在用户区实现的好处是,可以在不支持多线程的操作系统上运行多线程,减少在用户模式和内核模式间切换,可以用应用程序来进行线程调度(比如有个garbage collector线程,我们希望这个线程不会打扰其他线程的执行)。坏处是,如果某个线程里发生了一个阻塞的系统调用,系统切换到内核态。但由于线程管理在用户态,内核不知道多线程的存在,不知道除了当前被阻塞的这个线程,还有其他线程想要执行,所以任由该线程阻塞,直到得到结果、阻塞结束或者分给这个进程的时间片用完了。

在用户模式和内核模式间切换的过程发生了什么呢,为什么会有很大的开销?从发生一个系统调用开始说吧。单核CPU任何时间只能执行一条指令,当某个应用运行在用户态,它需要获取系统资源时,如从disk上读数据,它就必须转换到内核态、去执行内核里的代码。以调用read函数为例,首先应用调用C标准库里的read函数(library procedure),标准库函数里它发生一个系统调用,也叫read。在这个过程里,库函数把要发生的系统调用的编号存在某个地方如寄存器里,然后执行TRAP指令,从用户态进入内核态。TRAP和普通的函数调用类似,将函数指针指向另一个函数入口并把返回地址入栈,实现跳转。不同的是,TRAP后指针指向内核代码,普通函数调用是指向用户态的另一段代码;TRAP不能跳到一个任意的地址。接下来,内核会检查之前放在寄存器里的系统调用的编号,通过查表跳到对应的处理函数里。等系统调用完成了,重新回到用户态。

http://www.cnblogs.com/gtarcoder/articles/5278074.html

哪些代码是属于内核的?为什么要把指令分为两种等级,用户态和内核态?

在kenel space:在内核区进行线程调用的话,若某个线程发生阻塞型的系统调用,内核会切换到另一个线程,解决了用户区的问题。在多线程运行中,有如何处理信号的问题。信号是发送给一个进程,而不是单个线程。所以当收到一个信号,由哪个线程来处理呢?书里简单介绍,不同的线程注册不同的信号,所以某个信号会由对它感兴趣的那个线程来处理。

之前不明白,怎样就是创建了一个新的线程呢?思考一下什么构成了一个线程,线程可以由哪些来表示?当然是线程状态了,包括函数计数器,线程栈,一些寄存器值。就像一个snapshot,能从这些数据重新恢复一个暂停的线程。所以在thread library里,要保存下每个线程的snapshots,调出某个snapshot,恢复寄存器的各种状态,从函数计数器指向的地方开始执行。

大部分操作系统在存储上都用了虚拟。代码看见的地址都是虚拟地址,不论是用户态还是内核态,每个进程有自己的页目录和页表,页表里记录了虚拟地址到物理地址的映射。为什么要用虚拟地址?首先虚拟空间可以大于物理空间、即内存的大小。可能会有疑问,因为一个进程用的是虚拟地址,如果它用到的地址空间大于内存空间,怎么正常运行?实际上,把需要用到的数据划成很多固定大小的页,在某个执行时刻,并不是所有的页都要用到。内存中只需要存当前用到的页面。当某个时候进程请求的页不在内存中,产生page fault,操作系统将把对应的页从磁盘加载到内存里,替换掉不需要的页。另外,虚拟地址给一个进程提供了一块连续的地址空间。

什么时候操作系统需要处理页?创建进程、执行进程、页故障、结束进程时。

数据库里如何保证一个交易的原子性呢?原子性表示一个交易或者发生、或者不发生,all or none. 故障可能发生在交易进行的过程中,原子性不允许这种交易完成一半的情况,所以要么继续进行、完成交易,要么回退到最初的状态。

一种办法是deferred-modification,就像ds第二个project里cache时采用copy-on-write。在这里,要更新时,先创建一个数据库的副本,在副本上更新,到commit时,把指向原数据库的指针更新为指向最新副本的指针。如果在更新之前发生故障,重启后还是指向原数据库,相当于交易abort,如果更新之后发生故障,重启后指向更新的数据库,交易成功commit。但在这里需要保证指针更新的原子性,这个原子性可以由disk硬件来保证。

一种办法是直接在原数据上修改,但为每个修改都创建一条日志。可以根据日志判断某个交易进行到哪个状态,如果需要回退,就是撤销之前的操作。日志需要及时写入disk,保证不会在故障中消失。

时间: 2024-10-12 17:20:44

4-15 OS(线程,用户态,内核态,页) 数据库(原子性,日志) JAVA(I/O)的相关文章

用户态/内核态、用户栈/内核栈

一.用户态和内核态 内核态和用户态是操作系统的两种运行级别,用于区分不同程序的不同权利. 内核态就是拥有资源多的状态,或者说访问资源多的状态,也称为特权态.相对来说,用户态就是非特权态,访问的而资源将受到限制.如果一个程序运行在特权态,该程序就可以访问计算机的任何资源,它的资源访问权限不受限制.如果一个程序运行在用户态,其资源需求将受到各种限制.如:要访问操作系统的内核数据结构,如进程表,则需要在特选态下才能办到.如果要访问用户程序里的数据,在用户态即可. 二.用户栈和内核栈 内核在创建进程的时

DSP 之原子与高性能设计(一) 用户态/内核态 原子原语

type __sync_fetch_and_add (type *ptr, type value, ...)type __sync_fetch_and_sub (type *ptr, type value, ...)type __sync_fetch_and_or (type *ptr, type value, ...)type __sync_fetch_and_and (type *ptr, type value, ...)type __sync_fetch_and_xor (type *pt

用户态内核态

Q:怎么从用户态切换到内核态 A:用户程序调用系统调用的时候,用户程序先将系统调用号放入eax,执行int0x80指令触发中断,中断发生时,cpu切入内核态,从 用户栈 切换到 内核栈 ,在 内核栈 中依次压入用户态的寄存器,也就是保护现场,根据中断号在中断向量表中查找对应的中断处理程序,并调用它. 中断 中断:操作系统是通过中断来从用户态切换到内核态 中断分两种: 硬件中断:电源掉电,键盘被按下 软件中断:i386下是 int 指令 linux上系统调用的中断号是0x80,而windows上是

用户态-内核态

前戏 我们知道计算机主要分为三部分,硬件,操作系统和应用程序,然后硬件的头脑cpu才是控制内核态和用户态的大佬 操作系统 操作系统是直接和硬件打交道的,操作系统在内核态下运行,从而可以访问整个硬件 应用程序 应用程序直接和用户交互,但是应用程序不能直接操作硬件,应用程序在用户态下运行,但是有时候应用程序也需要操作硬件,这个时候,就涉及到用户态和内核态的切换 内核态-用户态概念 内核态(所有指令都给操作系统使用) 当cpu在内核态运行时,cpu可以执行指令集中所有的指令,很明显,所有的指令中包含了

从socket can中断到netlink用户态内核态通信

1. Linux中的进程间的通信机制源自于Unix平台上的进程通信机制.Unix的两大分支AT&T Unix和BSD Unix在进程通信实现机制上的各有所不同,前者形成了运行在单个计算机上的System V IPC,后者则实现了基于socket的进程间通信机制.同时linux也遵循IEEE制定的posix IPC标准,在三者的基础上实现以下几种主要的IPC机制:管道(Pipe)和命名管道(Name Pipe),信号(Signal),消息队列(Message queue),共享内存(Shared

linux 用户态 内核态

http://blog.chinaunix.net/uid-1829236-id-3182279.html 究竟什么是用户态,什么是内核态,这两个基本概念以前一直理解得不是很清楚,根本原因个人觉得是在于因为大部分时候我们在写程序时关注的重点和着眼的角度放在了实现的功能和代码的逻辑性上,先看一个例子: 1)例子 C代码 1.     void testfork(){   2.     if(0 = = fork()){   3.     printf(“create new process suc

进程:linux用户态-内核态

用户态:Ring3运行于用户态的代码则要受到处理器的诸多检查,它们只能访问映射其地址空间的页表项中规定的在用户态下可访问页面的虚拟地址,且只能对任务状态段(TSS)中I/O许可位图(I/O Permission Bitmap)中规定的可访问端口进行直接访问. 内核态:Ring0在处理器的存储保护中,核心态,或者特权态(与之相对应的是用户态),是操作系统内核所运行的模式.运行在该模式的代码,可以无限制地对系统存储.外部设备进行访问. 一.用户态和内核态 现在我们从特权级的调度来理解用户态和内核态就

关于内核态用户态和信号的思考(其中中断上下段没有看懂)

终于搞懂用户态内核态以及中断.信号的上下文切换关系了,处于内核态的时候用户态的上下文保存在内核栈中,此时如果发生中断或者切换,是不会区分进程处于用户态还是内核态的,直接切之,软中断导致的是内核态和用户态的转化,也即是用户上下文到内核上下文的转化,而中断导致的是用户态或者内核态上下文到中断上下文的转化,进程切换导致的是用户态/内核态上下文到用户态/内核态上下文的转化.关键是每个进程都对应一个用户栈和内核栈. 扩展阅读: http://19880512.blog.51cto.com/936364/2

关于内核态和用户态切换开销的测试

最近开发用到fuse文件系统,这个文件系统的功能实现是在用户态下进行的,然而它的文件系统操作接口必须在内核态注册,所以需要研究一下内核态到用户态的开销到底如何.下面这个例子是在stackoverflow上看到的,基本能反映开销的差异了:在linux测试这个测试程序,getuid是一个系统调用,返回当前用户的id 1 #include <unistd.h> 2 3 #define MAX 100000000 4 int main() { 5 int ii; 6 for (ii=0; ii<