Linux概念与体系阅读笔记

【Linux概念与体系教程http://www.cnblogs.com/vamei/archive/2012/10/10/2718229.html】

1.Linux开机启动(bootstrap)

启动顺序:BIOS -> MBR -> boot loader -> kernel -> init process -> login

BIOS:Basic Input/Output System

MBR :Master Boot Record

2.Linux文件管理

(1)文件附件信息(metadata)

文件自身包含的只有数据。文件名实际上储存在目录文件。除了这些之外,还有操作系统维护的文件附加信息,比如文件类型,文件尺寸,文件权限,文件修改时间,文件读取时间等。可以用ls命令查询文件信息($ls -l file.txt),得到如下结果:

-rw-r--r-- 1 vamei vamei 8445 Sep  8 07:33 file1.txt

各个部分的含义如下:

  • 我们先介绍最开始的-,它表示文件类型,说明file1.txt是常规文件(如果是目录文件,则应显示d)。
  • 随后有九个字符,为rw-r--r--,它们用于表示文件权限。这九个字符分为三组,rw-, r--, r--,分别对应拥有者(owner),拥有组(owner group)和所有其他人(other)。回顾Linux开机启动,登录后,我会有一个用户身份和一个组身份, 相当于我的名片。第一组表示,如果我的名片上的用户身份证明我是该文件的拥有者,那么我就可以对该文件有读取(r),写入(w)该文件的权限,但不拥有执行(-,如果拥有执行权限,则为x)该文件的权限。第二组表示,如果我的名片上的组身份证明我所在的组是该文件的拥有组的一员,那么我有从该文件读入的权限。第三组表示,如果我的名片显示我既不是拥有者,也不是拥有组的一员,那么我只有读入的权限。当我想要进行一个读取操作时,Linux会先看我是否是拥有者下文会进一步解释拥有者和拥有组。
  • 后面的1是硬连接(hard link)数目(link count)。
  • 之后的vamei表示用户vamei是文件的拥有者(owner),文件的拥有者有权更改文件权限(比如改为rwxrwxrwx)。而后面的vamei文件的拥有组是组vamei。文件的拥有者和拥有组在文件创建时就附加在文件上(相当于给文件上锁,只有有合适名片的用户才能打开操作)。要注意,Linux有一个超级用户root (也叫做根用户),该用户拥有所有的文件。
  • 随后的8445表示文件大小,单位为字节(byte)。
  • Sep 8 07:33表示文件的上一次写入的时间(modification time)。实际上在文件附加信息中还包含有文件的上一次读取时间(access time),没有显示出来。

(2)umask

当我们创建文件的时候,比如使用touch,它会尝试将新建文件创建为权限666,也就是rw-rw-rw-。但操作系统要参照权限mask来看是否真正将文件创建为666。权限mask表示操作系统不允许设置的权限位,比如说037(----wxrwx)的权限mask意味着不允许设置设置group的wx位和other的rwx位。如果是这个权限mask的话,最终的文件权限是rw-r----- (group的w位和other的rw位被mask)。我们可以通过 $umask 022 的方式改变权限mask。

3.Linux架构

4.Linux命令行与命令

(1)shell命令可以分为如下几类

  • 可执行文件(executable file)
  • shell内建函数(built-in function)
  • 别名(alias)。

(2)当一个命令运行时,你中途想要停止它时,可以用Ctrl + c。如果你只是想暂时停止,使用Ctrl + z。具体机制与信号(signal)有关。

(3)在执行命令之前加上sudo, 以便临时以root的身份执行某条命令

5.Linux文件管理相关命令

(1)文件权限相关

  • $chmod 755 a.txt,change mode 改变a.txt的读、写以及执行权限
  • $sudo chown root a.txt,change owner 改变文件的拥有者为root用户。这个命令需要有超级用户权限才能执行,所以我们在命令之前加上sudo。
  • $sudo chgrp root a.txt,change group 改变文件的拥有组为root组

6.Linux文本流

(1)文本流

Linux以字节(byte)来作为数据的单位,也就是说这个序列每八位(bit)为一个单位(八位二进制对应的十进制范围为0到255),"everything is a stream of bytes"

(2)标准输入,标准输出,标准错误与重新定向

  • 重新定向标准输出:$ls > a.txt,计算机会新建一个a.txt的文件,并将命令行的标准输出指向这个文件;$ls >> a.txt,这里>>的作用也是重新定向标准输出。如果a.txt已经存在的话,ls产生的文本流会附加在a.txt的结尾,而不会像>那样每次都新建a.txt。
  • 重新定向标准错误:$cd void 2> a.txt > b.txt,标准错误对应的总是2号,所以有以上写法。标准错误输出到a.txt,标准输出输出到b.txt。
  • 同时重新定向标准输出和标准错误:$cd void >& a.txt,错误信息被导向a.txt。
  • echo,cat

(3)管道 (pipe)

管道可以将一个命令的输出导向另一个命令的输入,从而让两个(或者更多命令)像流水线一样连续工作,不断地处理文本流。在命令行中,我们用|表示管道:$cat < a.txt | wc 


7.Linux进程基础

(1)可以使用$ps命令来查询正在运行的进程

(2)当计算机开机的时候,内核(kernel)只建立了一个init进程。Linux kernel并不提供直接建立新进程的系统调用。剩下的所有进程都是init进程通过fork机制建立的。新的进程要通过老的进程复制自身得到,这就是fork。fork()系统调用是Unix下以自身进程创建子进程的系统调用,一次调用,两次返回,在父进程中,fork返回新创建子进程的进程ID,在子进程中,fork返回0。在fork()的调用处,整个父进程空间会原模原样地复制到子进程中,包括指令,变量值,程序调用栈,环境变量,缓冲区,等等。

(3)父进程在得知子进程终结时,有责任对该子进程使用wait系统调用。这个wait函数能从kernel中取出子进程的退出信息,并清空该信息在kernel中所占据的空间。

8.Linux信号基础

(1)相对于其他的进程间通信方式(interprocess communication, 比如说pipe, shared memory)来说,信号所能传递的信息比较粗糙,只是一个整数。但正是由于传递的信息量少,信号也便于管理和使用。信号因此被经常地用于系统管理相关的任务,比如通知进程终结、中止或者恢复等等。

(2)常见信号

  • SIGINT   当键盘按下CTRL+C从shell中发出信号,信号被传递给shell中前台运行的进程,对应该信号的默认操作是中断 (INTERRUPT) 该进程。
  • SIGQUIT  当键盘按下CTRL+\从shell中发出信号,信号被传递给shell中前台运行的进程,对应该信号的默认操作是退出 (QUIT) 该进程。
  • SIGTSTP  当键盘按下CTRL+Z从shell中发出信号,信号被传递给shell中前台运行的进程,对应该信号的默认操作是暂停 (STOP) 该进程。
  • SIGCONT  用于通知暂停的进程继续。
  • SIGALRM  起到定时器的作用,通常是程序在一定的时间之后才生成该信号。

(3)在shell中使用信号

下面我们实际应用一下信号。我们在shell中运行ping:

$ping localhost

此时我们可以通过CTRL+Z来将SIGTSTP传递给该进程。shell中显示:

[1]+  Stopped                 ping localhost

我们使用$ps来查询ping进程的PID (PID是ping进程的房间号), 在我的机器中为27397

我们可以在shell中通过$kill命令来向某个进程发出信号:

$kill -SIGCONT  27397

来传递SIGCONT信号给ping进程。

9.Linux进程关系

(1)进程组 (process group)

每个进程都会属于一个进程组(process group),每个进程组中可以包含多个进程。进程组会有一个进程组领导进程 (process group leader),领导进程的PID (PID见Linux进程基础)成为进程组的ID (process group ID, PGID),以识别进程组。

(2)在shell支持工作控制(job control)的前提下,多个进程组还可以构成一个会话 (session)。会话中的每个进程组称为一个工作(job)。会话可以有一个进程组成为会话的前台工作(foreground),而其他的进程组是后台工作(background)。每个会话可以连接一个控制终端(control terminal)。当控制终端有输入输出时,都传递给该会话的前台进程组。

会话的意义在于将多个工作囊括在一个终端,并取其中的一个工作作为前台,来直接接收该终端的输入输出以及终端信号。 其他工作在后台运行。

一个命令可以通过在末尾加上&方式让它在后台运行:

$ping localhost > log &

此时终端显示:

[1] 10141

括号中的1表示工作号,而10141为PGID

我们通过如下方式查询更加详细的信息:

$ps -o pid,pgid,ppid,sid,tty,comm

(tty表示控制终端)

信号可以通过kill

$kill -SIGTERM -10141

或者

$kill -SIGTERM %1

的方式来发送给工作组。上面的两个命令,一个是发送给PGID(通过在PGID前面加-来表示是一个PGID而不是PID),一个是发送给工作1(%1),两者等价。

一个工作可以通过$fg从后台工作变为前台工作:

$cat > log &

$fg %1

当我们运行第一个命令后,由于工作在后台,我们无法对命令进行输入,直到我们将工作带入前台,才能向cat命令输入。在输入完成后,按下CTRL+D来通知shell输入结束。

10.Linux用户

(1)每个进程会维护有如下6个ID:

真实身份: real UID,       real GID

有效身份: effective UID,  effective GID

存储身份:saved UID,      saved GID

其中,真实身份是我们登录使用的身份,有效身份是当该进程真正去操作文件时所检查的身份,存储身份就是真实身份之外的另一个身份。进程的不同阶段可能需要不同的特权。比如一个进程最开始的有效身份是真实身份,但运行到中间的时候,需要以其他的用户身份读入某些配置文件,然后再进行其他的操作。为了防止其他的用户身份被滥用,我们需要在操作之前,让进程的有效身份变更回来成为真实身份。这样,进程需要在两个身份之间变化。

11.Linux从程序到进程

(1)每个进程空间按照如下方式分为不同区域:

Text区域用来储存指令(instruction),说明每一步的操作。Global Data用于存放全局变量,栈(Stack)用于存放局部变量,堆(heap)用于存放动态变量 (dynamic variable. 程序利用malloc系统调用,直接从内存中为dynamic variable开辟空间)。Text和Global data在进程一开始的时候就确定了,并在整个进程中保持固定大小。

栈(Stack)以帧(stack frame)为单位。当程序调用函数的时候,stack会向下增长一帧。帧中存储该函数的参数和局部变量,以及该函数的返回地址(return address)。位于栈最下方的帧,和全局变量一起,构成了当前的环境(context)。典型的编程语言都只允许你使用位于stack最下方的帧 ,而不允许你调用其它的帧 (这也符合stack结构“先进后出”的特征。但也有一些语言允许你调用栈的其它部分,相当于允许你在运行inner()函数的时候调用main()中声明的局部变量,比如Pascal)。

当程序中使用malloc的时候,堆(heap)会向上增长,其增长的部分就成为malloc从内存中分配的空间。malloc开辟的空间会一直存在,直到我们用free系统调用来释放,或者进程结束。一个经典的错误是内存泄漏(memory leakage), 就是指我们没有释放不再使用的堆空间,导致堆不断增长,而内存可用空间不断减少。栈和堆的大小则会随着进程的运行增大或者变小。当栈和堆增长到两者相遇时候,也就是内存空间图中的蓝色区域(unused area)完全消失的时候,再无可用内存。进程会出现栈溢出(stack overflow)的错误,导致进程终止。

11.Linux多线程与同步

(1)创建一个新的线程时,我们为这个线程建一个新的栈。每个栈对应一个线程。当某个栈执行到全部弹出时,对应线程完成任务,并收工。所以,多线程的进程在内存中有多个栈。每个线程可调用自己栈最下方的帧中的参数和变量,并与其它线程共享内存中的Text,heap和global data区域。

(2)多线程同步

  • 互斥锁
  • 条件变量
  • 读写锁

12.Linux进程间通信

进程间通信方式可以分为两种

(1)管道(PIPE)机制

管道是由内核管理的一个缓冲区(buffer)。最开始的时候,上面的两个箭头都连接在同一个进程Process 1上(连接在Process 1上的两个箭头)。当fork复制进程的时候,会将这两个连接也复制到新的进程(Process 2)。随后,每个进程关闭自己不需要的一个连接 (两个黑色的箭头被关闭; Process 1关闭从PIPE来的输入连接,Process 2关闭输出到PIPE的连接),这样,剩下的红色连接就构成了如上图的PIPE。

 

由于基于fork机制,所以管道只能用于父进程和子进程之间,或者拥有相同祖先的两个子进程之间 (有亲缘关系的进程之间)。为了解决这一问题,Linux提供了FIFO方式连接进程。FIFO又叫做命名管道(named PIPE)。当一个进程以读(r)的方式打开该文件,而另一个进程以写(w)的方式打开该文件,那么内核就会在这两个进程之间建立管道,所以FIFO实际上也由内核管理,不与硬盘打交道。

(2)传统IPC (interprocess communication)。我们主要是指消息队列(message queue),信号量(semaphore),共享内存(shared memory)

(3)socket也可以用于计算机内部进程间的通信。

时间: 2024-10-26 10:02:02

Linux概念与体系阅读笔记的相关文章

Linux 2.6 内核阅读笔记 信号

2014年8月3日 信号处理程序调用过程 当一个进程接收到一个信号时,需要暂停进程执行转去执行专门的信号处理函数(如果定义了这个信号的专门处理函数的话),然后再继续执行进程代码. 所有的信号处理都是通过内核函数do_signal进行的,do_signal如果发现需要处理的信号,并且这个信号有专门的处理函数,就需要调用这个用户态的函数,这是通过handle_signal来处理的.执行信号处理函数是非常复杂的任务,因为在用户态和内核态来回切换需要特别谨慎地处理栈里的内容,在当前进程恢复"正常&quo

Linux 2.6 内核阅读笔记 中断和异常

2014年7月24日 中断门.陷阱门及中断门 中断是可以禁止的,可以通过告诉PIC停止对某个中断的发布.被禁止的中断是不会丢失的,在解除禁止后又会发送到CPU上. 禁止中断和屏蔽(mask)中断的不同之处是屏蔽是忽略掉某个中断,而禁止相当于延迟发送. Intel提供了三种类型的中断描述符:任务门.中断门及陷阱门描述.linux使用与inten稍有不同的细分分类和术语,把他们进行如下分类: 中断门:用户态进程不能访问的一个intel中断门(DPL为0),所有的linux中断处理程序都通过中断门在内

Linux 2.6 内核阅读笔记 内存管理

2014年7月29日 buddy分配算法 内核需要为分配一组连续的页框提供一种健壮.高效的分配策略.分配连续的页框必须解决内存管理中的外碎片(external fragmentation).频繁的请求和释放不同大小的一组连续页框,必然导致分配页框的块分算来许多小块的空闲页框无法被一次性大量分配使用. linux内核采用著名的伙伴系统算法来解决外碎片问题.该算法的核心思想是把所有的空闲页框分成11个链块表.每个链块表的大小分别为1,2,4,8,16,32,64,128,256,512和1024个连

Linux内核完全注释阅读笔记1:O(1)时间复杂度查找timeout定时器

前言 一直有Linux kernel情节,之前也一直在看Linux kernel相关的书和代码,但是每次到最后又由于兴趣转变而荒废了.这次终于静下心来想把Linux内核相关的代码好好看看,算是对自己的一个沉淀吧.由于之前工作做的是分布式调度这块的东西,也稍微有过分布式文件系统相关的实习经历,所以阅读Linux内核代码的重心可能会往调度和文件系统这两大块倾斜. 个人感觉读读Linux kernel还是蛮有必要的,其实现在各种分布式框架.各种云计算,其实很多的思想都是借鉴Linux kernel的.

《Linux权威指南》阅读笔记(4)

第十五章  TCP/IP和PPP <DNS与BIND>,见转帖的读书笔记. TCP和UDP数据单位被称为分组包(packet),包头中指定了目的和源端口地址. 互联网协议(IP)在协议层次中位于TCP和UDP下面,将TCP和UDP分组包封装在另一个分组包中(被称为IP报文),

《Linux权威指南》阅读笔记(3)

第十三章 程序设计语言 Linux共享函数库使用一种叫跳跃表格(jump table)的数据结构 gcc -o 执行链接,指定文件名,-c不执行链接,-O优化,-g调试信息放入目标文件, 建立和使用静态函数库的方法: 先gcc -c将含目标函数源码(多个文件也可以)编译为.o文件,然后用ar程序 ar -r 建立.a静态库, 然后用ranlib命令产生索引,然后为该函数库建立头文件 gcc  -I../include -L../lib  -o  wibble  wibble.c  -lstuff

Linux kernel源码阅读笔记2-2.6版本调度器sched.c功能

来自:http://www.ibm.com/developerworks/cn/linux/l-scheduler/ 2.6 版本调度器的源代码都很好地封装到了 /usr/src/linux/kernel/sched.c 文件中.我们在表 1 中对在这个文件中可以找到的一些有用的函数进行了总结. 表 1. Linux 2.6 调度器的功能 函数名 函数说明 schedule 调度器主函数.调度优先级最高的任务执行. load_balance 检查 CPU,查看是否存在不均衡的情况,如果不均衡,就

Linux 2.6 内核阅读笔记 内核同步

2014年7月26日 内核抢占和内核控制路径的设计 内核抢占的一种定义:如果进程正在内核态执行内核函数时,允许发生内核切换(就是被替换的进程是内核函数所在进程),这个内核就是抢占的. linux内核提供了内核抢占的开启和关闭功能,在current_thread_info的preempt_count字段大于0时,内核就是不能抢占的.可以通过preempt_disable和preempt_enable来增加这个字段来控制这个开关. 中断和软中断和抢占的控制主要使用到current_thread_in

linux概念和体系1

1. Linux开机启动 2. Linux文件管理 3. Linux的架构 4. Linux命令行与命令 5. Linux文件管理相关命令 6. Linux文本流 7. Linux进程基础 8. Linux信号基础 9. Linux进程关系 10. Linux用户 11. Linux从程序到进程 12. Linux多线程与同步 13. Linux进程间通信 14. Linux文件系统的实现 15. Linux常用命令 =======================================