Linux系统编程(第一章)笔记

Linux编程的概念

文件和文件系统

    Linux遵循一切皆文件的理念。因此很多交互操作是通过读写文件来完成,即使所涉及的对象看起来并非普通文件。
   文件打开方式有只读、只写和读写模式。文件打开后通过唯一文件描述符来引用,该描述符是从发开文件关联的元数据到文件本身的映射。文件描述符在用户空间共享,用户程序通过文件描述符可以直接访问文件。

普通文件

   我们经常提及的“文件”即Linux中的普通文件。普通文件包含以字节流(即线性数组)组织的数据。在Linux中,可以从文件中的任意字节开始读写。对文件的操作是从某个字节开始,即文件“地址”。该地址称为文件位置(file location)或文件偏移(file offset)。文件位置的最大值只取决于存储该值的C语言类型的大小,在现代Linux操作系统上,该值是64位。
   文件的大小是通过字节来计算,称为文件长度。换句话说,文件长度即组成文件的线性数组的字节数
   文件虽然是通过文件名访问,但文件本身其实并没有直接和文件名关联。相反地,与文件关联的是索引节点inode(最初称为信息节点 ,是information node的缩写),inode是文件系统为该文件分配的唯一整数值(但是在整个系统中不一定是唯一的)索引节点中会保存和文件相关的元数据,如文件修改时间戳、所有者、类型、长度以及文件数据的位置——但不含文件名!
   索引节点就是UNIX文件在磁盘上的实际物理对象,也是在Linux内核中通过数据结构表示的概念实体。

目录和链接

   通过索引节点编号访问文件很繁琐(而且潜在安全漏洞),因此文件通常是通过文件名(而不是索引节点号)从用户空间打开。目录用于提供访问文件需要的名称。目录是可读名称到索引编号之间的映射。名称和索引节点之间的配对称为链接(link)。映射在物理磁盘上的形式,如简单的表或散列,是通过特定文件系统的内核代码来实现和管理的。从概念上看,可以把目录看作普通文件,其区别在于它包含文件名称到索引节点的映射。内核直接通过该映射把文件名解析为索引节点。
   从根目录开始的路径称为完整路径,也叫绝对路径。有些路径不是绝对路径,而是相对路径(如todo/plunder)。当提供相对路径时,内核会在当前工作目录下开始路径解析。内核在当前工作目录中查找todo目录。在这里,内核获取索引节点plunder。相对路径和当前工作目录的组合得到绝对路径。
   虽然目录是作为普通文件存储的,但内核不支持像普通文件那样打开和操作目录。相反地,目录必须通过特殊的系统调用来操作。这些系统调用只支持两类操作:添加链接和删除链接

硬链接

   当不同名称的多个链接映射到同一个索引节点时,我们称该链接为硬链接(hard links)。
   要从目录中删除文件,需要从目录结构中取消链接(unlink)该文件,这只需要从目录中删除该文件名和索引节点就可以。然而,由于Linux支持硬链接,文件系统不能对每个unlink操作执行删除索引节点及其关联数据的操作。否则,如果该索引节点在文件系统中还有其他的硬链接怎么办?为了确保在删除所有的链接之前不会删除文件,每个索引节点包含链接计数(link count),记录该索引节点在文件系统中的链接数。当unlink某个路径时,其链接计数会减1;只有当链接计数为0时,索引节点及其关联的数据才会从文件系统中真正删除。

符号链接

   为了跨越文件系统建立链接,UNIX系统实现了符号链接(symbolic links,简称symlinks)。
   符号链接类似于普通文件,每个符号链接有自己的索引节点和数据块,包含要链接的文件的绝对路径。这意味着符号链接可以指向任何地方,包括不同的文件系统上的文件和路径,甚至指向不存在的文件和目录。指向不存在的文件的符号链接称为坏链接(broken link)。比起硬链接,符号链接会带来更多的开销,因为有效解析符号链接需要解析两个文件:一是符号链接本身,二是该链接所指向的文件。

特殊文件

   特殊文件(special file)是指以文件来表示的内核对象。这些年来,UNIX系统支持了不少不同的特殊文件。Linux只支持四种特殊文件:块设备文件、字符设备文件、命名管道以及UNIX域套接字。特殊文件是使得某些抽象可以适用于文件系统,贯彻一切皆文件的理念。Linux提供了系统调用来创建特殊文件。

文件系统和命名空间

   如同所有的UNIX系统,Linux提供了全局统一的文件和目录命名空间。有些操作系统会把不同的磁盘和驱动划分成独立的命名空间——比如,通过路径A:\plank.jpg可以访问软盘上的文件,虽然硬盘驱动安装在C:\目录下。在UNIX该软盘上的文件可以在其他介质上,通过路径/media/floppy/plank.jpg访问,甚至可以通过/home/captain/stuff/plank.jpg访问。也就是说,在UNIX系统中,命名空间是统一的。

进程

   进程是执行时的目标代码:活动的、正在运行的程序。但是进程不仅包含目标代码,它还包含数据、资源、状态和虚拟计算机。
进程的生命周期是从可执行目标代码开始,这些机器可运行的代码是以内核能够理解的形式存在,在Linux下,最常见的格式称为“可执行和可链接的格式(Executable and Linkable Format,ELF)”。可执行性格式包含元数据、多个代码段和数据段。代码段是线性目标代码块,可以加载到线性内存块中。数据段中的所有数据都一视同仁,有相同的权限,通常也用于相同的目的。最重要和通用的段是文本段、数据段和bss段。文本段包含可执行代码和只读数据如常量,通常标记为只读和可执行。数据段包含初始化的数据,如包含给定值的C变量,通常标记为可读写。bss段包含未初始化的全局数据。
   一般来说,进程只通过系统调用请求和管理资源。资源包括计时器、挂起的信号量、打开的文件、网络连接、硬件和IPC机制。进程资源以及该进程相关的数据和统计保存在内核中该进程的进程描述符中。

线程

   每个进程包含一个或多个执行线程(通常简称线程threads)。线程是进程内的活动单元,换句话说,线程是负责执行代码和管理进程运行状态的抽象。
线程包括栈(正如非线程系统的进程栈一样,用于存储局部变量)、处理器状态、目标代码的当前位置(通常是保存在处理器的指令指针中)。进程的其他部分由所有线程共享,最主要是进程地址空间。在这种情况下,线程在维护虚拟进程抽象时,也共享虚拟内存抽象。
   在Linux系统内部,Linux内核实现了独特的线程模型:它们其实是共享某些资源的普通进程。

进程层次结构

   每个进程都由唯一的正整数标识,称为进程ID(pid)。第一个进程的pid是1,后续的每个进程都有一个新的、唯一的pid。
   在Linux中,进程有严格的层次结构,即进程树。进程树的根是第一个进程,称为init进程,通常是init程序。新的进程是通过系统调用fork()创建的。fork()会创建调用进程的副本。

用户和组

   Linux中通过用户和组进行权限认证,每个用户和一个唯一的正整数关联,该正整数称为用户ID(uid)。相应地,每个进程和一个uid关联,用来识别运行这个进程的用户,称为进程的真实uid。在Linux内核中,uid是用户的唯一标识。但是,用户一般会通过用户名而不是id来表示。用户名及其对应的uid保存在etc/passwd中,而系统库会把用户名映射到对应的uid上。
   在登录过程中,用户向login程序提供用户名和密码。如果提供的用户名和密码都正确,login程序会根据/etc/passwd为用户生成login shell,并把用户id作为该shell进程的uid,子进程继承父进程的uid。超级用户root的uid是0,root用户有特殊的权限几乎可以执行所有操作。login进程是以root身份运行的。
   除了真实uid以外,每个进程还包括有效的uid,保留uid和文件系统uid。真实uid总是启动进程的用户uid,有效的uid在不同情况下会发生变化,从而支持进程切换成其他用户权限来执行。保留uid保存原来的有效uid,其值决定了用户将切换成哪个有效uid。文件系统uid通常和有效uid等效,用于检测文件系统的访问权限。
   每个用户属于一个或多个组,包括在/etc/passwd中给出的基础组或登录组,也可能是/etc/group中给出的很多附加组。因此每个进程和相应的组ID关联,也包括真实gid,有效gid,保留gid,文件系统gid。进程通常是和用户的登录组关联,而不是和附加组关联。

权限

   Linux的标准文件权限和安全机制与unix的一致。
   每个文件都有文件所有者,所属组以及三个权限位集合。每个权限位描述了所有者,所属组以及其他人对文件的读写执行的权限。这三类每个对应3个位,共9位。文件所有者和权限信息保存在文件的索引节点中。

信号

   信号是一种单向异步通知机制。信号可能是从内核发送到进程,也可能是从进程到进程,或者进程发送给自己。信号一般用于通知进程发生了某些事件,如段错误或者用户按下ctrl-c。
   进程收到信号可以根据信号的类型选择忽略或者处理,忽略的信号会被丢弃不做处理。处理信号会执行用户提供的信号处理函数,当信号处理函数返回时,程序控制逻辑将返回之前终端的指令处继续执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值