操作系统的核心--内核

内核的职责

  1. 进程调度:Linux属于抢占式多任务操作系统,多个进程可同时驻留于内存,且每个进程都能获得对CPU的使用权。哪些进程获得对CPU的使用,以及每个进程能使用多长时间 ,都由内核进程调度程序决定。
  2. 内存管理:Linux采用了虚拟内在管理机制。
  3. 提供了文件系统
  4. 创建和终止进程:内核可将新程序载入内存,为其提供运行所需的资源。一旦程序执行完毕,内核还要确保释放其占用资源,以供后续程度重新使用。
  5. 设备的访问:内核既为程序访问设备提供了简化版的标准接口,同时还要仲裁多个进程对每一个设备的访问。
  6. 联网:内核以用户进程的名义收发网络消息(数据包)。该任务包括将网络数据包路由至目标系统。
  7. 提供系统调用应用编程接口(API):进程可利用内核入口点请求内核去执行各种任务。

内核态和用户态

​ 在用户态下运行时,CPU只能访问被标记为用户空间的内存,试图访问属于内核空间的内存会引发硬件异常。当运行于核心态时,CPU既能访问用户空间内存,也能访问内核空间内存。

​ 仅当处理器在核心态运行时,才能执行某些特定操作。如:执行宕机(halt)指令去关闭系统,访问内存管理硬件,以及设备I/O操作的初始化等。实现者们利用这一硬件设计,将操作系统置于内核空间。确保了用户进程既不能访问内核指令和数据结构,也无法执行不利于系统运行的操作。

shell

  • Bourne shell(sh)
  • C shell(csh)
  • Korn shell(ksh)
  • Bourne again shell(bash)

​ 设计shell的目的不仅仅是用于人机交互,对shell脚本进行解释也是其用途之一。为实现这一目的,每款shell都内置有许多通常与编程语言相关的功能,其中包括变量、循环和条件语句、I/O命令以及函数等。

用户和组

用户

​ 系统的每个用户都拥有唯一的登录名和与之相对应的整数型用户ID(UID)。系统密码文件/etc/passwd为每个用户都定义有一行记录,除了上述两项信息外,该记录还包含如下信息。

  • 组ID:用户所属第一个组的整数型组ID。
  • 主目录:用户登录后所居于的初始目录。
  • 登录shell:执行以解释用户命令的程序名称。

​ 该记录还能以加密形式保存用户密码。然而,出于安全考虑,用户密码往往存储于单独的shadow密码文件中,仅供特权用户阅读。

​ 每个用户都对应着系统组文件/etc/group中的一行记录,该记录包含如下信息。

  • 组名:(唯一的)组名称
  • 组ID(GID):与组相关的整数型ID。
  • 用户列表:隶属于该组的用户登录名列表(通过密码文件记录的group ID字段未能标识出的该组其他成员,也在此列),以逗号分隔。

超级用户

​ 超级用户在系统中享有特权。超级用户账号的用户ID为0,通常登录名为root。

单根目录层级、目录、链接及文件

​ 内核维护着一套单根目录结构,以放置系统的所有文件。这一目录层级的根基就是名为“/”的根目录。所有的文件和目录都是根目录的“子孙”。

路径和链接

每个目录至少包含两条记录:..和.,前者是指向目录自身的链接,后者是指向其上级目录——父目录的链接。对根目录而言,..是指向根目录自身的。

符号链接

​ 分为硬链接和软链接。

文件的所有权和权限

​ 每个文件都有一个与之相关的用户ID和组ID,分别定义文件的属主和性组。系统根据文件的所有权来判定用户对文件 的访问权限。

文件I/O模型

文件描述符

​ I/O系统调用使用文件描述符——非负整数——来指代打开的文件。通常,由shell启动的进程会继承3个已打开的文件描述符:描述符0为标准输入,指代为进程提供输入的文件;描述符1为标准输出,指代供进程写入输出的文件;描述符2为标准错误,指代供进程写入错误消息或异常通告的文件。在stdio函数库中,这几种描述符分别与文件流stdin、stdout和stderr相对应。

stdio函数库

​ C编程语言在执行文件I/O操作时,往往会调用C语言标准库的I/O函数。也将这样一组I/O函数称为stdio函数库,其中包括fopen()、fclose()、scanf()、printf()、fgets()、fputs()等。stdio函数位于I/O系统调用层(open()、close()、write()等)之上。

进程

进程的内存布局

​ 逻辑上将一个进程划分为以下几部分(也称为段)

  • 文本:程序的指令。
  • 数据:程序使用的静态变量。
  • 堆:程序可从该区域动态分配额外内存。
  • 栈:随函数调用、返回而增减的一片内存,用于为局部变量和函数调用链接信息分配存储空间。

创建进程和执行程序

​ 进程可使用系统调用fork()来创建一个新进程。调用 fork()的进程被称为父进程,新创建的进程则被称为子进程。内核通过对父进程的复制来创建 子进程。子进程从父进程处继承数据段、栈段以及堆段的副本后,可以修改这些内容,不会影响父进程的“原版”内容。(在内存中被标记为只读的程序文本段code则由父、子进程共享。)

​ 然后,子进程要么去执行与父进程共享代码段中的另一组不同函数,或者,更为常见的情况是使用系统调用 execve()去加载并执行一个全新程序。execve()会销毁现有的文本段、数据段、栈段及堆段,并根据新程序的代码,创建新段来替换它们。

​ 以execve()为基础,C语言库还提供了几个相关函数,接口虽然略不同,但功能全都相同。以上所有库函数的名称均以字符串“exec”打头,在函数间差异无关宏旨的场合,本书会用符号exec()作为这些库函数的统称。不过,实际上根本不存在名为exec()的库函数。

进程ID和父进程ID

​ 每一进程都有一个唯一的整数型进程标识符(PID)。每一进程还具有一个父进程标识符(PPID)属性,用以标识请求内核创建自己的进程。

init进程

​ 系统引导时,内核会创建一个名为init的特殊进程,即“所有进程之父”,该进程的相应程序文件为/sbin/init。系统的所有进程不是由init(使用fork())“亲自”创建,就是由其后代进程创建。init进程的进程号总为1,且总是以超级用户权限运行。

守护进程

​ 守护进程指的是具有特殊用途的进程,系统创建和处理此类进程的方式与其他进程相同,但以下特征是其所独有的:

  • “长生不老”。守护进程通常在系统引导时启动,直至系统关闭前,会一直在。
  • 守护进程在后台运行,且无控制终端供其读取或写入数据。

守护进程中的例子有syslogd(在系统日志中记录消息)和httpd(利用HTTP分发Web页面)。

环境列表

​ 每个进程都有一份环境列表,即在进程用户空间内存中维护的一组环境变量。这份列表的每一元素都由一个名称及其相关值组成。由fork()创建的新进程,会继承父进程的环境副本。这也为父子进程间通信提供了一种机制。当进程调用 exec()替换当前正在运行的程序时,新程序要么继承老程序的环境,要么在exec()调用的参数中指定新环境并加以接收。

​ 在绝大多数shell中,可使用export命令来创建环境变量(C shell使用setenv命令),

​ 如$ export MYVAR='Hello world'

​ C语言程序可使用外部变量(char **environ)来访问环境,而库函数也允许进程去获取或修改自己的环境中的值。

​ 环境变量的用途多种多样。例如,shell定义并使用了一系列变量,供shell执行的脚本和程序访问。其中包括:变量HOME(明确定义了用户登录目录的路径名)、变量PATH(指明了用户输入命令后,shell查找与之相应程序时所搜索的目录列表)。

资源限制

​ 每个进程都会消耗诸如打开文件、内存以及CPU时间 之类的资源。使用系统调用 setrlimit(),进程可为自己消耗的各类资源设定一个上限。此类资源限制的每一项均有两个相关值:软限制限制了进程可以消耗的资源总量,硬限制软限制的调整上限。非特权进程在针对资源调整软限制值时,可将其设置为0到相应硬限制值之间的任意值,但硬 限制值则只能调低,不能调高。

由fork()创建的新进程,会继承其父进程对资源限制的设置。

​ 使用ulimit命令(在C shell中为limit)可调整shell的资源限制。shell为执行命令所创建的子进程会继承上述资源设置。

进程间通信及同步

Linux提供了丰富的进程间通信(IPC)机制。

  • 信号(signal),用来表示事件的发生。
  • 管道和FIFO,用于在进程间传递数据。
  • 套接字,借同一台主机或是联网的不同主机上所运行的进程之间传递数据。
  • 文件锁定,为防止其他进程读取或更新文件内容,允许某进程对文件的部分区域加以锁定。
  • 消息队列,用于在进程间交换消息(数据包)。
  • 信号量,用来同步进程动作。
  • 共享内存,允许两个及以上进程共享一块内存。当某进程改变了共享内存的内容时,其他所有进程会立即了解到这一变化。

线程

​ 每个进程都可执行多个线程。可将线程想象为共享同一虚拟内存及一干其他属性的进程。每个线程都会执行相同的程序代码,共享同一数据区域和堆。可是,每个线程都拥有属于自己的栈,用来装载本地变量和函数调用 链接信息。

​ 线程之间可通过共享的全局变量进行通信。借助于线程API所提供的条件变量和互斥机制,进程所属的线程之间得以相互通信并同步行为——尤其是在对共享变量的使用方面。此外,利用IPC和同步机制,线程间也能彼此通信。

​ 线程的主要优点在于协同线程之间的数据共享更为容易,而且就某些算法而论,以多线程来实现比之以多进程实现要更加自然。再者,显而易见,多线程应用能从多处理器硬件的并行处理中获益匪浅。

/proc文件系统

​ Linux提供了/proc文件系统,由一组目录和文件组成,装配(mount)于/proc目录下。

​ /proc文件系统是一种虚拟文件系统,以文件系统目录和文件形式,提供了一个指向内核数据结构的接口。这为查看和改变各种系统属性开启了方便之门。此外,还能通过一组以/proc/PID形式命名的目录(PID即进程ID)查看系统中运行各进程的相关信息。

​ 通常,/proc目录下的文件内容都采取人类可读 的文件形式,shell脚本也能对其进行解析。程序可以 打开、读取和写入/proc目录下的既定文件。大多数情况下,只有特权级进程才能修改/proc目录下的文件内容。

《Linux系统编程手册》读书笔记——第2章基本概念的更多相关文章

  1. 《Linux内核分析》读书笔记(四章)

    <Linux内核分析>读书笔记(四章) 标签(空格分隔): 20135328陈都 第四章 进程调度 调度程序负责决定将哪个进程投入运行,何时运行以及运行多长时间,进程调度程序可看做在可运行 ...

  2. linux 第三周读书笔记-----第一二章 20135334赵阳林

    第一章 Linux内核简介 1.1 Unix的历史 由于Unix系统设计简洁并且在发布时提供源代码,所以许多其他组织和团体都对它进了进一步的开发. Unⅸ虽然已经使用了40年,但计算机科学家仍然认为它 ...

  3. 《鸟哥的Linux私房菜》读书笔记--第0章 计算机概论 硬件部分

    一个下午看了不少硬件层面的知识,看得太多太快容易忘记.于是在博客上写下读书笔记. 有关硬件 个人计算机架构&接口设备 主板芯片组为“南北桥”的统称,南北桥用于控制所有组件之间的通信. 北桥连接 ...

  4. 《Linux多线程服务器端编程》读书笔记第3章

    <Linux多线程服务器端编程>第3章主要讲的是多线程服务器的适用场合与常用的编程模型. 1.进程和线程 一个进程是"内存中正在运行的程序“.每个进程都有自己独立的地址空间(ad ...

  5. Linux系统编程手册-源码的使用

    转自:http://www.cnblogs.com/pluse/p/6296992.html 第三章后续部分重点介绍了后面章节所要使用的头文件及其实现,主要如下: ename.c.inc error_ ...

  6. 《Unix环境高级编程》读书笔记 第13章-守护进程

    1. 引言 守护进程是生存期长的一种进程.它们常常在系统引导装入时启动,仅在系统关闭时才终止.它们没有控制终端,在后台运行. 本章说明守护进程结构.如何编写守护进程程序.守护进程如何报告出错情况. 2 ...

  7. 《python核心编程》读书笔记--第16章 网络编程

    在进行网络编程之前,先对网络以及互联网协议做一个了解. 推荐阮一峰的博客:(感谢) http://www.ruanyifeng.com/blog/2012/05/internet_protocol_s ...

  8. 《Unix环境高级编程》读书笔记 第10章-信号

    1.引言 信号是软件中断. 信号提供了一种处理异步事件的方法. 2. 信号概念 信号的名字都是以3个字符SIG开头. Linux3.2.0支持31种信号.FreeBSD.Linux和Solaris作为 ...

  9. 《Unix环境高级编程》读书笔记 第8章-进程控制

    1. 进程标识 进程ID标识符是唯一.可复用的.大多数Unix系统实现延迟复用算法,使得赋予新建进程的ID不同于最近终止所使用的ID ID为0的进程通常是调度进程,也常被称为交换进程.它是内核的一部分 ...

随机推荐

  1. openstack Keystone验证服务集群

    #Keystone验证服务群集 openstack pike 部署 目录汇总 http://www.cnblogs.com/elvi/p/7613861.html ##.Keystone验证服务集群 ...

  2. Swarm 如何存储数据?- 每天5分钟玩转 Docker 容器技术(103)

    service 的容器副本会 scale up/down,会 failover,会在不同的主机上创建和销毁,这就引出一个问题,如果 service 有要管理的数据,那么这些数据应该如何存放呢? 选项一 ...

  3. 摘要算法---hashlib模块下MD5和SHA的使用

    作用: 任意长度的字符串内容通过摘要算法都可以生成唯一序列摘要值,通过摘要算法,可以校验某个文档或者某组字符串是否被修改. 应用: 1.文件内容一致性校验 2.用户登录验证 常用方法 update() ...

  4. UWP 使用OneDrive云存储2.x api(一)【全网首发】

    最近开发人脸识别UWP[微识别 / Werecognition]用到了OneDrive开发,下面把来龙去脉讲一下. 下载地址 https://www.microsoft.com/store/produ ...

  5. javascript设计模式——命令模式

    前面的话 假设有一个快餐店,而我是该餐厅的点餐服务员,那么我一天的工作应该是这样的:当某位客人点餐或者打来订餐电话后,我会把他的需求都写在清单上,然后交给厨房,客人不用关心是哪些厨师帮他炒菜.餐厅还可 ...

  6. Django1.10+Mysql 5.7存储emoji表情,报Incorrect string value: '\\xF0\\x9F\\x90\\xA8' for column 'signature' at row 1的解决方法

    问题: 在做webapp项目的时候,用户提交emoji数据,控制台报错:Incorrect string value: '\\xF0\\x9F\\x90\\xA8' for column 'signa ...

  7. 最短路算法之Dijkstra算法通俗解释

    Dijkstra算法 说明:求解从起点到任意点的最短距离,注意该算法应用于没有负边的图. 来,看图. 用邻接矩阵表示 int[][] m = { {0, 0, 0, 0, 0, 0}, {0, 0, ...

  8. java线程池的创建使用

    利用java的多线程编程可以大大的提高系统的并发运行效率,线程越多并发执行的任务就越多,但是并不意味着效率会一直提高,相反会得到适得其反的效果. java中的多线程编程一共有三种方法: 继承Threa ...

  9. javaweb学习总结(四)——Http协议(转)

    转载自 http://www.cnblogs.com/xdp-gacl/p/3751277.html 一.什么是HTTP协议 HTTP是hypertext transfer protocol(超文本传 ...

  10. shell脚本删除N天前的目录-----附linux和mac上date命令的不同

    背景: 每日构建的东西.按日期放到不同的目录里. 现在天的构建放到2015-06-01里,明天的就放到2015-06-02里,依次类推.时间久了.须要一个脚本删除N天前的目录.(本例中N=7.即删除一 ...