linux

2) 文件系统的理解(EXT4XFSBTRFS

文件系统主要用于控制所有程序在不使用数据时如何存储数据、如何访问数据以及有什么其它信息(元数据)和数据本身相关。

Linux 操作系统即便使用标准安装过程,在同一块磁盘上仍使用多个分区。拥有不同分区的一个主要目的就是为了在灾难发生时能获得更好的数据安全性。

EXT4:使用广泛,Linux现在默认的是广泛采用的 ext4易用性以及广泛性

XFSXFS 文件系统是扩展文件系统的一个扩展,XFS 文件系统有一些缺陷,例如它不能压缩,删除大量文件时性能低下。

btrfs:有很多好用的功能,例如写复制、扩展校验、快照、清洗、自修复数据、冗余删除以及其它保证数据完整性的功能。

 

3) 文件处理grep,awk,sed这三个命令必知必会

grep文本过滤器,命令用于打印输出文本中匹配的模式串,它使用正则表达式作为模式匹配的条件。

Sed  是一种在线编辑器,它一次处理一行内容。。

awk    是一种用于处理文本的编程语言工具。

 

9) 硬连接和软连接的区别

APUE 4.154.16

硬链接:

AB的硬链接(AB都是文件名),则A的目录项中的inode节点号与B的目录项中的inode节点号相同,即一个inode节点对应两个不同的文件名,两个文件名指向同一个文件,AB对文件系统来说是完全平等的。如果删除了其中一个,对另外一个没有影响。每增加一个文件名,inode节点上的链接数增加一,每删除一个对应的文件名,inode节点上的链接数减一,直到为0inode节点和对应的数据块被回收。注:文件和文件名是不同的东西,rm A删除的只是A这个文件名,而A对应的数据块(文件)只有在inode节点链接数减少为0的时候才会被系统回收。

软链接:

AB的软链接(AB都是文件名),A的目录项中的inode节点号与B的目录项中的inode节点号不相同,AB指向的是两个不同的inode,继而指向两块不同的数据块。但是A的数据块中存放的只是B的路径名(可以根据这个找到B的目录项)。AB之间是“主从”关系,如果B被删除了,A仍然存在(因为两个是不同的文件),但指向的是一个无效的链接。

 

区别:

硬链接实际上是为文件建一个别名,链接文件和原文件实际上是同一个文件。可以通过ls -i来查看一下,这两个文件的inode号是同一个,说明它们是同一个文件;而软链接建立的是一个指向,即链接文件内的内容是指向原文件的指针,它们是两个文件。

软链接可以跨文件系统,硬链接不可以;

软链接可以对一个不存在的文件名(filename)进行链接(当然此时如果你vi这个软链接文件,linux会自动新建一个文件名为filename的文件),硬链接不可以(其文件必须存在,inode必须存在);

软链接可以对目录进行连接,硬链接不可以。

 


10) 文件权限怎么看(rwx

文件权限查看ls -l,查看文件所有者,所属组,其他的文件权限,rwx777

修改使用chmod命令


11) 文件的三种时间(mtime, atimectime),分别在什么时候会改变

 

更改状态时间是该文件的i节点最后一次被修改的时间。在本章中我们已说明了很多操作,它们影响到i节点,但并没有更改文件的实际内容:文件的存取许可权、用户I D、连接数等等。因为i节点中的所有信息都是与文件的实际内容分开存放的,所以,除了文件数据修改时间以外,还需要更改状态时间。

 

14) 文件读写使用的系统调用

读文件:

int fd = -1;

char filename[] = "/root/test.txt";

fd = open(filename,O_RDONLY);

size = read(fd,buf,10);

close(fd);

 

写文件:

int fd = -1;

char buf[] = "boys and girls\n hi,children!";

fd = open(filename,O_RDWR|O_APPEND);

size = write(fd,buf,strlen(buf));

close(fd);

 

二、IO


1LinuxI/O模型介绍、过程、区别以及同步异步阻塞非阻塞的区别(超级重要)

阻塞IO是在两个过程应用都处于阻塞状态。进程或线程调用某个函数,该函数需要满足特定条件才能向下执行。如果条件不满足,则会使调用进程或线程阻塞,让出CPU控制权,并一直持续到条件满足为止。

非阻塞IO是应用发出IO操作后可以立刻返回,通过轮询盘判断数据是否准备好,在copy数据阶段阻塞应用。

IO多路复用:是阻塞调用select,查找可用的套接字,如果有套接字可用,那么就阻塞调用(recvfrom)完成数据的copy过程。Linux select就是这种模型,缺点是一次select会扫描所有的socket

信号驱动IO是应用发出SIGIO后立刻返回,内核中数据准备好后,通知应用,由应用进行阻塞recvfrom调用从内核copy数据。linux epoll就是基于事件的就绪通知方式,省去了所有socket的扫描开销。

异步IO是应用发出aio-read后马上返回,数据准备好后,由操作系统把数据copy到应用,并通知应用数据copy完成。

 

阻塞:用户进程访问数据时,如果未完成IO,调用的进程一直处于等待状态,直到IO操作完成。

非阻塞:用户进程访问数据时,会马上返回一个状态值,无论是否完成,此时进程可以操作其他事情。
同步:用户进程发起IO后,进行就绪判断,轮询内核状态。

异步:用户进程发起IO后,可以做其他事情,等待内核通知。


4IO复用的三种方法(select,poll,epoll)深入理解,包括三者区别,内部原理实现?

selectpollepoll都是IO多路复用的机制I/O多路复用就通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。但selectpollepoll本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的,而异步I/O则无需自己负责进行读写,异步I/O的实现会负责把数据从内核拷贝到用户空间

select:是最初解决IO阻塞问题的方法。用结构体fd_set来告诉内核监听多个文件描述符,该结构体被称为描述符集。由数组来维持哪些描述符被置位了。对结构体的操作封装在三个宏定义中。通过轮寻来查找是否有描述符要被处理,如果没有返回。

存在的问题:内置数组的形式使得select的最大文件数受限与FD_SIZE;每次调用select前都要重新初始化描述符集,将fd从用户态拷贝到内核态,每次调用select后,都需要将fd从内核态拷贝到用户态;轮寻排查当文件描述符个数很多时,效率很低;

poll:通过一个可变长度的数组解决了select文件描述符受限的问题。数组中元素是结构体,该结构体保存描述符的信息,每增加一个文件描述符就向数组中加入一个结构体,结构体只需要拷贝一次到内核态。poll解决了select重复初始化的问题。轮寻排查的问题未解决。

epoll:轮寻排查所有文件描述符的效率不高,使服务器并发能力受限。因此,epoll采用只返回状态发生变化的文件描述符,便解决了轮寻的瓶颈。

 

 

 

 

 

 

 

 

 

每次调用poll/select系统调用,操作系统都要把current(当前进程)挂到fd对应的所有设备的等待队列上,可以想象,fd多到上千的时候,这样“挂”法很费事;而每次调用epoll_wait则没有这么罗嗦,epoll只在epoll_ctl时把current挂一遍(这第一遍是免不了的)并给每个fd一个命令“好了就调回调函数”,如果设备有事件了,通过回调函数,会把fd放入rdllist,而每次调用epoll_wait就只是收集rdllist里的fd就可以了——epoll巧妙的利用回调函数,实现了更高效的事件驱动模型。

 

5)EpollET模式和LT模式(ET的非阻塞)

LT:level trigger, 水平触发模式

ET:edge trigger, 边缘触发模式

相同点:都是通过epoll_waitEPOLL等待队列读取激活事件
区别:1. LT模式读取激活事件后,如果还有未处理的数据。事件会重新放入EPOLL等待队列。2. ET模式读取激活事件,直接从EPOLL等待队列移除,不管是否有未处理的数据

 

LT模式问题:如果可读或可写事件未处理,会频繁激活未处理事件

解决方法:不想处理读写事件时, EPOLL中移除句柄。需要处理时再加入EPOLL

ET模式问题:如果可读或可写没有全部处理,会有老数据残留。要等待新数据到来。

解决方法:1. 循环读取或写入数据,一直到EAGAINEWOULDBLOCK

 

2. 读取或者写入数据后,通过epoll_ctl设置EPOLL_CTL_MOD,激活未处理事件

 

ET模式饿死问题处理方法:

应用层维护一个list, 存储epoll_wait返回的就绪文件描述符, 然后循环处理

list不为空时, 进行循环处理其中事件

每个文件描述符只进行一定限度的 IO 操作, 比如每次限定只读 1KB 数据, 然后继续处理其他的文件描述符

如果该文件描述符读了 1KB 没读完 (没有返回EAGIN / EWOULDBLOCK), 就继续停留在list, 反之如果其上的 IO 操作执行完了, 就将其移除list

 

上一题中编程的时候有什么区别,是在边缘触发的时候要把套接字中的数据读干净,那么当有多个套接字时,在读的套接字一直不停的有数据到达,如何保证其他套接字不被饿死(面试网易游戏的时候问的一个问题,答不上来,印象贼深刻)

 

 

 

三、进程

13Linux进程管理

在很多情况下,进程都是动态创建并由一个动态分配的 task_struct 表示。一个例外是 init 进程本身,它总是存在并由一个静态分配的 task_struct 表示。在 ./linux/arch/i386/kernel/init_task.c 内可以找到这样的一个例子。

Linux 内所有进程的分配有两种方式。第一种方式是通过一个哈希表,由 PID 值进行哈希计算得到;第二种方式是通过双链循环表。循环表非常适合于对任务列表进行迭代。由于列表是循环的,没有头或尾;但是由于 init_task 总是存在,所以可以将其用作继续向前迭代的一个锚点

 

15fork返回值是什么?

fork函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。

它可能有三种不同的返回值:

    1在父进程中,fork返回新创建子进程的进程ID

    2在子进程中,fork返回0

    3如果出现错误,fork返回一个负值

17守护进程、孤儿进程、僵尸进程问题

    守护进程:

通常在系统后台运行,没有控制终端,不与前台交互,Daemon程序一般作为系统服务使用。Daemon是长时间运行的进程,通常在系统启动后就运行,在系统关闭是才结束。一般说Daemon程序在后台运行,是因为它没有控制终端,无法和前台的用户交互。Daemon程序一般都作为服务程序使用,等待客户端程序与它通信。我们把运行的Daemon程序称作守护进程。

 

孤儿进程:

一个父进程退出,而它的一个或多个子进程还在运行,那么这些子进程将成为孤儿进程。孤儿进程将被 init 进程(进程号为 1)所收养,并由 init 进程对它们完成状态收集工作。由于孤儿进程会被 init 进程收养,所以孤儿进程不会对系统造成危害。

 

僵尸进程:

一个子进程的进程描述符在子进程退出时不会释放,只有当父进程通过 wait() waitpid() 获取了子进程信息后才会释放。如果子进程退出,而父进程并没有调用 wait() waitpid(),那么子进程的进程描述符仍然保存在系统中,这种进程称之为僵尸进程。

僵尸进程通过 ps 命令显示出来的状态为 Zzombie)。

系统所能使用的进程号是有限的,如果产生大量僵尸进程,将因为没有可用的进程号而导致系统不能产生新的进程。

要消灭系统中大量的僵尸进程,只需要将其父进程杀死,此时僵尸进程就会变成孤儿进程,从而被 init 进程所收养,这样 init 进程就会释放所有的僵尸进程所占有的资源,从而结束僵尸进程。

 

 

17)处理僵尸进程的两种经典方法

父进程回收法:

wait函数将使其调用者阻塞,直到其某个子进程终止。故父进程可调用wait函数回收其僵尸子进程。

init进程回收法:

上面的这种解决方案需要父进程去等待子进程,但在很多情况下,这并不合适,因为父进程也许还有其他任务要做,不能阻塞在这里。在讲述下面这种不用父进程等待就能完成回收子进程的方法之前,先请明白以下两个概念:

1. 如果父进程先于子进程结束,那么子进程的父进程自动改为 init 进程。

2. 如果 init 的子进程结束,则 init 进程会自动回收其子进程的资源而不是让它变成僵尸进程。

 

18)进程终止的几种方式

1main函数的自然返回,return

2、调用exit函数

3、调用_exit函数

4、调用abort函数

5、接受能导致进程终止的信号:

 

exit_exit函数都是用来终止进程的。当程序执行到exit_exit时,进程会无条件的停止剩下的所有操作,清除包括PCB在内的各种数据结构,并终止本程序的运行。

exit函数和_exit函数的最大区别在于exit函数在退出之前会检查文件的打开情况,把文件缓冲区中的内容写回文件,也就是清理I/O缓冲

abort()是使异常程序终止,同时发送SIGABRT信号给调用进程。

 

四、线程

 

 

五、内存管理

 

16)什么是虚拟内存?

1. 每个进程都有自己独立的4G内存空间,各个进程的内存空间具有类似的结构

2. 一个新进程建立的时候,将会建立起自己的内存空间,此进程的数据,代码等从磁盘拷贝到自己的进程空间,哪些数据在哪里,都由进程控制表中的task_struct记录,task_struct中记录中一条链表,记录中内存空间的分配情况,哪些地址有数据,哪些地址无数据,哪些可读,哪些可写,都可以通过这个链表记录

3. 每个进程已经分配的内存空间,都与对应的磁盘空间映射

 

 

1. 每个进程的4G内存空间只是虚拟内存空间,每次访问内存空间的某个地址,都需要把地址翻译为实际物理内存地址

2. 所有进程共享同一物理内存,每个进程只把自己目前需要的虚拟内存空间映射并存储到物理内存上。

3. 进程要知道哪些内存地址上的数据在物理内存上,哪些不在,还有在物理内存上的哪里,需要用页表来记录

4.页表的每一个表项分两部分,第一部分记录此页是否在物理内存上,第二部分记录物理内存页的地址(如果在的话)

5. 当进程访问某个虚拟地址,去看页表,如果发现对应的数据不在物理内存中,则缺页异常

6.缺页异常的处理过程,就是把进程需要的数据从磁盘上拷贝到物理内存中,如果内存已经满了,没有空地方了,那就找一个页覆盖,当然如果被覆盖的页曾经被修改过,需要将此页写回磁盘

 

17Linux是如何避免内存碎片的

伙伴算法,用于管理物理内存,避免内存碎片;

高速缓存Slab层用于管理内核分配内存,避免碎片。

 

 

六、常用命令
6) 查询进程占用CPU的命令(注意要了解到usedbuf***代表意义)


7linux的其他常见命令(killfindcp等等)


8shell脚本用法

 


12Linux监控网络带宽的命令,查看特定进程的占用网络资源情况命令

 

18Linux基本命令?

命令 作用

pwd     显示当前目录

rm     删除

touch 生成文件

cat     读取指定文件的内容并打印到终端输出

mkdir 新建目录make directory

file     查看文件类型

whereiswhichfind locate 查找

chown 改变文件所有者

df     查看磁盘容量

wc     计数工具

tr     删除一段文本信息中的某些文字。或者将其进行转换

join     连接两个文件

paste 它是在不对比数据的情况下,简单地将多个文件合并一起,以Tab隔开

 

 

Linux内核

 

1Linux内核的进程调度

 

 

posted @ 2022-03-27 12:30  淡然那片天  阅读(67)  评论(0)    收藏  举报