Linux.docx
- 文档编号:14636489
- 上传时间:2023-06-25
- 格式:DOCX
- 页数:41
- 大小:6.20MB
Linux.docx
《Linux.docx》由会员分享,可在线阅读,更多相关《Linux.docx(41页珍藏版)》请在冰点文库上搜索。
Linux
Linux复习概要
文件系统:
1、数据结构
文件逻辑结构与读写指针
文件物理结构
UNIX文件系统采用的是多级索引结构(综合模式)。
每个文件的索引表为13个索引项,每项2个字节。
最前面10项直接存放文件信息的物理块号(直接寻址)。
如果文件大于10块,则利用第11项指向一个物理块,该块中最多可放256个文件物理块的块号(一次间接寻址)。
对于更大的文件还可利用第12和第13项作为二次和三次间接寻址。
UNIX中采用三级索引结构后,文件最大可达16兆个物理块。
分级目录
i节点
磁盘i节点(indexnode–inode)含有对应文件的所有说明信息。
一个文件系统的所有磁盘i节点组成一个表,保存在超级块之后的确定地址。
每个节点按其相对位置顺序编号(如1,2,…),称为i节点号。
磁盘i节点的内容如下:
。
文件主标识号:
用户id(i_uid),组id(i_gid)
。
set_uid位和set_gid位(i_mode)
。
文件类型(i_mode)
。
文件访问权限(i_mode)
。
连接数(i_nlink)
。
文件所在物理块号表(索引表i_addr[])
。
文件长度(i_size)
。
文件本身设备号(特殊文件i_rdev)
。
文件创建修改访问时间(i_ctime,i_mtime,i_atime)
………………………
磁盘分区和文件系统
文件表与内存i节点表
内存i节点表
为加快文件名在目录树中的搜索速度设立了内存i节点表,其中每一项对应一个打开文件。
打开文件时将i节点由磁盘复制到内存i节点表项中,关闭时再复制回磁盘原处。
文件打开时,磁盘i节点复制到内存i节点(除时间信息外),但增加如下内容:
。
设备号(所在设备设备号i_dev)
。
i节点号(所在设备的i节点号i_ino)
。
访问计数(访问此内存i节点的进程数)
。
使用状态:
互斥锁,安装点标志,文件或此节点是否改写
。
指向flock结构的指针
文件关闭时,内存i节点除上述内容外的大部分信息复制到磁盘i节点上,但增加时间等信息,整个系统只有一个内存i节点表,用以存放系统内所有内存i节点。
i节点的大部分内容可由stat()和ls读取。
系统打开文件表
系统打开文件表简称系统文件表或文件表,此表整个系统只有一个,每项保存有对应打开文件的当前使用特征。
共享此打开文件的各进程在自己的打开文件表中各有一表项,其中的指针指向该文件的文件表项。
各表项内容如下:
文件状态标志:
读(O_RDONLY),写(O_WRONLY),读写(O_RDWR),
附加写(O_APPEND),非阻塞(O_NONBLOCK),
同步(O_SYNC),异步(O_ASYNC)。
它们可由open()或fcntl()设置修改。
当前文件位移量(读写指针),read/write由此位移开始向后读写文件的数据。
读写打开时位移量缺省值为0,附加打开时其值为文件尾,打开后可由lseek()重新设置。
用户打开文件表
每个进程有一个用户打开文件表(或简称用户文件表,描述字表),其大小由内核配置时确定。
每一项表示该进程的一个打开文件,表的索引号称为文件描述字(符)。
但描述字0,1,2有专门含义:
0:
标准输入,缺省为键盘输入,可重定向为任一文件;
1:
标准输出,缺省为屏幕输出,可重定向为任一文件;
2:
出错输出,指定为为屏幕输出,不可重定向。
文件描述字(符)可由系统调用creat,open返回,由dup复制;
表项内容如下:
文件描述字标志:
目前只有执行关闭标志(close-on-exec)。
其值为0(缺省)表示当前进程执行一目标文件时不关闭这个打开文件;1表示执行某文件时关闭此文件,此标志可由fcntl
(2)设置修改。
文件表项指针。
文件类型与访问权限
文件类型(12-15位)及建立的系统调用:
普通文件(IFREG-100000)creat(),mknod()
目录文件(IFDIR-040000)mkdir()
块设备(IFBLK-060000)mknod()
字符设备(IFCHR-020000)mknod()
套接口(IFSOCK-140000)socket()
符号链接(IFLNK-120000)symlink()
管道/FIFO(IFIFO-010000)mknod()
2、基本IO函数
打开文件open
intopen(constchar*pathname,intoflag,…/*,mode_tmode*/);
关闭文件close
建立文件creat
复制文件描述字dup
读写文件read和write
移动文件指针lseek
文件控制fcntl
intstat(constchar*pathname,structstat*buf);
intlstat(constchar*pathname,structstat*buf);返回符号连接信息
intfstat(intfd,structstat*buf);
将文件的信息(来自inode)读入buf,ls命令需要这个函数。
structstat{
mode_tst_mode;/*文件类型与访问许可*/
ino_tst_ino;/*i节点号*/
dev_tst_dev;/*所在设备号*/
dev_tst_rdev;/*特殊文件设备号*/
nlink_tst_nlink;/*连接数*/
uid_tst_uid;/*文件主用户id*/
gid_tst_gid;/*文件主组id*/
off_tst_size;/*普通文件规模(字节数)*/
time_tst_atime;/*最近访问时间*/
time_tst_mtime;/*最近修改时间*/
time_tst_ctime;/*最近文件状态改变时间*/
longst_blksize;/*最好的IO块规模*/
longst_blocks;/*512字节块数*/
};
3、文件与目录函数
4、管道
特点
1.无文件名
2.先进先出(自动同步检查实现)单向
3.临时文件
4.同一家族进程
系统调用:
intpipe(intfds[2]);
返回fds[0]为读描述字,fds[1]为写描述字
5、文件系统管理
文件系统位于一个磁盘分区或一个磁盘内。
通过mkfs命令或系统调用可在指定分区或磁盘上建立一个文件系统。
物理上,一个文件系统就是由超级块,i节点表,目录和文件数据块的集合;逻辑上,文件系统在用户面前表现为树形分级结构(除连接外),最高级为一个根目录。
分区或磁盘作为逻辑盘在系统中作为普通设备看待,它们在/dev目录下也有文件名,如/dev/dsk1,/dev/fd0等,也有对应的i节点,但其中没有文件索引表,只有设备号。
设备号包括两部分:
主设备号和次设备号,它们分别标识设备的类别和具体的驱动器号。
故设备号唯一地标识一个文件系统所在的具体设备。
系统中有一个磁盘分区含有根文件系统,所以叫做根设备。
系统初启时计算机首先在这里找到操作系统核心,将其读入内存运行。
其它分区上的文件系统可以“安装”到根文件系统中的一个目录上(也叫安装点)。
其效果是该目录逻辑上成为被安装文件系统的根目录。
于是,这两个文件系统便合成为统一的树形分级结构。
其后用户还可以将该文件系统“拆卸”下来。
由于系统安全性的需要,安装拆卸操作必须由超级用户执行。
七、虚拟文件系统*
vnode/vfs最早出现于sun公司的sunnos中(1986),后来被AT&T公司集成到SVR4中。
它们采用了面向对象的设计思想。
vnode(vituralnode,虚拟节点)作为一种虚拟节点有一组统一的接口函数调用格式,但对于不同类的i节点有着不同的实现函数体和私有数据。
vnode相当于面向对象中的抽象基类,它提供抽象接口,用于派生出各种文件节点的实现函数。
这些文件节点既包括不同文件系统的inode又包括socket等。
vfs(vituralfilesystem,虚拟文件系统)作为一种虚拟的文件系统有一组统一的接口函数调用格式,但对于不同类的文件系统有着不同的实现函数和私有数据。
vfs相当于面向对象中的抽象基类,它提供抽象接口,用于派生出多种文件系统实现,如s5fs,ufs,NFS,FAT32等。
vnode/vfs体系结构的目标:
同时支持多种文件系统,如Linux类:
s5fs,ufs。
非Linux类:
FAT32;
用户对所有(在不同分区)安装的文件系统具有统一的视图(接口);
支持网络文件系统(NFS)的共享和透明的访问;
允许厂家将定制的文件系统以模块方式加入内核。
进程存储管理:
(1)代码区(textsegment)。
加载的是可执行文件代码段,其加载到内存中的位置由加载器完成。
(2)全局初始化数据区/静态数据区(DataSegment)。
加载的是可执行文件数据段,存储于数据段(全局初始化,静态初始化数据)的数据的生存周期为整个程序运行过程。
(3)未初始化数据区(BSS)。
加载的是可执行文件BSS段,位置可以分开亦可以紧靠数据段,存储于数据段的数据(全局未初始化,静态未初始化数据)的生存周期为整个程序运行过程。
(4)栈区(stack)。
由编译器自动分配释放,存放函数的参数值、返回值、局部变量等。
在程序运行过程中实时加载和释放,因此,局部变量的生存周期为申请到释放该段栈空间。
(5)堆区(heap)。
用于动态内存分配。
堆在内存中位于BSS区和栈区之间。
一般由程序员分配和释放,若程序员不释放,程序结束时有可能由OS回收。
栈和堆的区别
(1)管理方式不同。
(2)空间大小不同。
(3)产生碎片不同。
(4)增长方向不同。
(5)分配方式不同。
(6)分配效率不同。
进程环境及进程属性
守护进程(Daemon)是运行在后台的一种特殊进程,其脱离于终端,之所以脱离于终端是为了避免进程被任何终端所产生的信息所打断,其在执行过程中的信息也不在任何终端上显示。
守候进程周期性地执行某种任务或等待处理某些发生的事件,Linux的大多数服务器就是用守护进程实现的。
比如,Internet服务器inetd,Web服务器httpd等。
一般情况下,守护进程可以通过以下方式启动:
在系统启动时由启动脚本启动,这些启动脚本通常放在/etc/rc.d目录下;
利用inetd超级服务器启动,如telnet等;
由cron定时启动以及在终端用nohup启动的进程也是守护进程。
两类型管道具有以下特点:
(1)管道是特殊类型的文件,在满足先入先出的原则条件下可能进行读写,但不能定位读写位置。
(2)管道是单向的,要实现双向,需要两个管道。
无名管道只能实现亲缘关系进程间通信(即无名管道的两个文件描述符可以被两者都访问到),而有名管道以磁盘文件的方式存在,可以实现本机任意两进程间通信。
(3)无名管道阻塞问题。
无名管道无须显式打开,创建时直接返回文件描述符,而在读写时需要确实对方的存在,否则将退出。
即如果当前进程向无名管道的写数据时,必须确定其别一端为某个进程(这个进程可以是当前进程)拥有,即有一个(或多个)进程的文件描述符表中至少有一个成员指向管道的另一端(显然,能够读写管道当前端,则本端在当前进程中是可以访问的)。
如果写入无名管道的数据超过其最大值,写操作将阻塞,如果管道中没有数据,读操作将阻塞,如果管道发现另一端断开(另一端文件描述符关闭),将自动退出。
(4)有名管道阻塞问题。
有名管道在打开时需要确实对方的存在,否则将阻塞。
即以读方式打开某管道,该操作得以继续执行的条件是:
在此之前,已经有一个进程以写的方式打开此管道,否则阻塞,直到条件满足,因此有名管道将阻塞在打开位置。
也可以以读写(O_RDWR)方式打开有名管道,进程能够继续执行(不阻塞),只是这样操作没有什么意思,即当前进程读,当前进程写。
Linux常见信号与处理
信号的处理流程
(1)信号被某个进程产生,并设置此信号传递的对象(一般为对应进程的pid),然后传递给操作系统;
(2)操作系统根据接收进程的设置(是否阻塞)而选择性的发送给接收者,如果接收者阻塞该信号(且该信号是可以阻塞的),操作系统将暂时保留该信号,而不传递,直到该进程解除对此信号的阻塞(如果对应进程已经退出,则丢弃此信号);如果对应进程没有阻塞,操作系统将传递此信号;
(3)目的进程接收到此信号后,将根据当前进程对此信号设置的预处理方式,暂时终止当前代码的执行,保护上下文(主要包括临时寄存器数据、当前程序位置以及当前CPU的状态)、转而执行中断服务程序,执行完成后再恢复到被中断的位置。
当然,对于可抢占式内核,在中断返回时还将引发新的调度。
信号处理办法
(1)忽略此信号。
大多数信号都可使用这种方式进行处理,但有两种信号不能被忽略,SIGKILL和SIGSTOP。
这两种信号不能被忽略的原因是:
它们向超级用户提供一种使进程终止或停止的可靠方法。
(2)捕捉信号。
通知内核在某种信号发生时调用一个用户函数。
在用户函数中,可执行用户希望对这种事件进行的处理,这需要安装此信号。
例如捕捉到SIGCHLD信号,则表示子进程已经终止,所以此信号的捕捉函数可以调用waitpid()以取得该子进程的进程PID以及它的终止状态和资源。
(3)执行系统默认操作。
Linux系统对任何一个信号都规定了一个默认的操作。
中断是可以被屏蔽(阻塞)的(部分硬件中断是必须立即处理的,例如复位中断),因此,Linux的信号是可以屏蔽,即阻塞信号。
但这与前面提到的忽略是有区别的。
信号忽略:
系统仍然传递该信号,只是相应进程对该信号不作任何处理而已。
信号阻塞:
系统不传递该信号,显示该进程无法接收到该信号直到进程的信号集发生改变。
SystemV进程间通信
Linux系统为每个IPC机制都分配了唯一的ID,所有针对该IPC机制的操作都使用对应的ID。
因此,通信的双方都需要通过某个办法来获取ID值。
显然,创建者根据创建函数的返回值可获取该值,但另一个进程如何实现呢?
显然,Linux两个进程不能随意访问对方的空间(一个特殊是,子进程可以继承父亲进程的数据,实现父亲进程向子进程的单向传递),也就不能够直接获取这一ID值。
为解决这一问题,IPC在实现时约定使用key值做为参数创建,如果在创建时使用相同的key值将得到同一个IPC对象的ID(即一方创建,另一方获取的是ID),这样就保证了双方可以获取用于传递数据的IPC机制ID值。
多线程
线程自己基本上不拥有系统资源,只拥有少量在运行中必不可少的资源(如程序计数器、一组寄存器、栈、线程信号掩码、局部线程变量和线程私有数据),但是它可与同属一个进程的其他线程共享进程所拥有的全部资源(同一地址空间、通用的信号处理机制、数据与I/O)。
进程在使用时占用了大量的内存空间,特别是进行进程间通信时一定要借助操作系统提供的通信机制,这使得进程有自身的弱点,而线程占用资源少,使用灵活,很多应用程序中都大量使用线程,而较少的使用多进程,但是,线程不能脱离进程而存在,另外,线程的层次关系,执行顺序并不明显,对于初学者大量使用线程会增加程序的复杂度。
新创建的线程从执行用户定义的函数处开始执行,直到出现以下情况时退出:
调用pthread_exit函数退出。
调用pthread_cancel函数取消该线程。
创建线程的进程退出或者整个函数结束。
其中的一个线程执行了exec类函数执行新的进程。
取消线程是指取消一个正在执行线程的操作,当然,一个线程能够被取消并终止执行需要满足以下条件:
该线程是否可以被其它取消,这是可以设置的,在Linux系统下,默认是可以被取消的,可用宏分配是PTHREAD_CANCEL_DISABLE和PTHREAD_CANCEL_ENABLE;
该线程处于可取消点才能取消。
也就是说,该线程被设置为可以取消状态,另一个线程发起取消操作,该线程并不是一定马上终止,只能在可取消点才中止执行。
可以设置为立即取消和在取消点取消。
可用宏为PTHREAD_CANCEL_DEFERRED和PTHREAD_CANCEL_ASYNCHRONOUS。
可设置的state的合法值:
如果目标线程的可取消性状态为PTHREAD_CANCEL_DISABLE,则针对目标线程的取消请求将处于未决状态,启用取消后才执行取消请求。
如果目标线程的可取消性状态为PTHREAD_CANCEL_ENABLE,则针对目标线程的取消请求将被传递。
默认情况下,在创建某个线程时,其可取消性状态设置为PTHREAD_CANCEL_ENABLE。
pthread_setcanceltype()函数用来设置取消类型,即允许取消的线程在接收到取消操作后是立即中止还是在取消点中止,该函数声明如下:
externintpthread_setcanceltype(int__type,int*__oldtype)
此函数有两个参数,type为调用线程的可取消性类型所要设置的值。
oldtype为存储调用线程原来的可取消性类型的地址。
type的合法值包括:
如果目标线程的可取消性状态为PTHREAD_CANCEL_ASYNCHRONOUS,则可随时执行新的或未决的取消请求。
如果目标线程的可取消性状态为PTHREAD_CANCEL_DEFERRED,则在目标线程到达一个取消点之前,取消请求将一直处于未决状态。
在创建某个线程时,其可取消性类型设置为PTHREAD_CANCEL_DEFERRED。
线程资源
线程只拥有少量在运行中必不可少的资源,主要包括:
程序计数器:
标识当前线程执行的位置;
一组寄存器:
当前线程执行的上下文内容;
栈:
用于实现函数调用、局部变量。
因此,局部变量是私有的;
线程信号掩码:
因此可以设置每线程阻塞的信号,见本书下一章内容;
局部线程变量:
在栈中申请的数据;
线程私有数据。
见前一小节介绍。
获取/设置线程属性调度属性
网络编程
IP数据包头
TCP包头
UDP数据包头
通信过程
首先,服务器端需要做以下准备工作:
(1)调用socket()函数。
建立socket对象,指定通信协议。
(2)调用bind()函数。
将创建的socket对象与当前主机的某一个IP地和端口绑定。
(3)调用listen()函数。
使socket对象处于监听状态,并设置监听队列大小。
客户端需要做以下准备工作:
(1)调用socket()函数。
建立socket()对象,指定相同通信协议。
(2)应用程序可以显式的调用bind()函数为其绑定IP地址和端口,当然,也可以将这工作交给TCP/IP协议栈。
接着建立通信连接:
(1)客户端调用connect()函数。
向服务器端发出连接请求。
(2)服务端监听到该请求,调用accept()函数接受请求,从而建立连接,并返回一个新的socket文件描述符专门处理该连接。
然后通信双方发送/接收数据:
(1)服务器端调用write()或send()函数发送数据,客户端调用read()或者recv()函数接收数据。
反之客户端发送数据,服务器端接收数据。
(2)通信完成后,通信双方都需要调用close()或者shutdown()函数关闭socket对象。
Linux系统运行级别介绍
一.系统运行级别介绍
Linux系统有7个运行级别,他们各自的含义是:
第0级关闭系统
第1级单用户模式
第2级没有网络多用户模式
第3级有网络多用户模式
第4级系统保留
第5级有网络和图形的多用户模式
第6级重启系统
二.系统默认运行级别
系统开机启动时,init进程读取/etc/inittab文件中所设置的默认运行级别
vim/etc/inittab/如下图:
可以看出目前系统默认启动级别为5级
三.修改运行级别
1.修改默认运行级别
修改/etc/inittab文件,如上图。
达到永久改变的效果。
2.通过GRUB,修改系统启动后的运行级别
首先,进入引导项界面,选择这个条目然后输入‘e’来编辑这个条目
然后,您现在应该可以看到以root、kernel、initrd开始的行出现。
将光标移动到以“kernel”开始的行,然后输入‘e’来编辑这一行。
最后,将光标移动到这一行的末尾,然后添加一个空格和数字‘1’。
如果需要的话您可以删除‘quiet’,或者根据需要修改任何其他参数。
之前的操作步骤做完后,按下Enter键来保存修改,然后输入‘b’来引导系统。
系统便会按照填写的相应级别来启动。
3.不重启系统,临时修改运行级别
首先,runlevel查看当前运行级别
其次使用命令init3来切换当前系统的运行级别
四.单用户模式
相比个人电脑操作系统,比如DOS或Windows,Linux本身是一个多用户系统。
然而,有时候这可能会成为一个问题,比如,当您需要恢复一个重要文件系统或者数据库时,或者安装和测试某个新软件时。
运行级别1,单用户模式是您在这些情况下的最佳答案。
实际实现根据不同版本有所变化,但是您通常只使用一个很小的系统简单地启动。
通常这里没有联网,没有(或者非常少)守护进程运行。
在一些系统上,您必须通过登录来进行认证,但在其他系统上您可以直接以根用户开始操作shell提示符。
单用户模式可能是一个救生圈,也可能是毁坏您的系统,因此,不管任何时候,当您使用根用户权限时都应该小心注意。
完成后立即重新启动到一个正常多用户模式。
Linux用户如果遇到忘记开机密码的情况,可直接采用单用户模式进入,设定或修改root账号密码,然后再用其他方式从正常进入系统。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Linux