文章目录
一、Linux 如何查看磁盘分区大小,
df命令以磁盘分区为单位查看文件系统,可以获取硬盘被占用了多少空间,目前还剩余多少空间等信息。
我们可以使用df -h命令来查看磁盘分区的信息:
显示内容参数说明:
Filesystem:文件系统
Size: 分区大小
Used: 已使用容量
Avail: 还可以使用的容量
Use%: 已用百分比
Mounted on: 挂载点
相关命令:
df -hl:查看磁盘剩余空间
df -h:查看每个根路径的分区大小
du -sh [目录名]:返回该目录的大小
du -sm [文件夹]:返回该文件夹总M数
du -h [目录名]:查看指定文件夹下的所有文件大小(包含子文件夹)
二、查看、修改网卡配置
使用网络管理命令ifconfig:
ifconfig 查看使能的网卡
ifconfig -a 查看所有的网卡,包括禁用的
sudo ifocnfig eth0 up 使能网卡eth0
sudo ifconfig eth0 down 禁用网卡eth0
sudo ifconfig eth0 192.168.1.119 设置IP,使用默认的子网掩码
sudo ifconfig eth0:1 192.168.2.119一张网卡绑定多个IP地址
sudo ifconfig eth0 192.168.1.119 netmask 255.255.255.0 设置IP,使用子网掩码为255.255.255.0
设置MAC地址:
sudo ifconfig eth0 down 设置MAC地址先禁用网卡
sudo ifconfig eth0 hw ether 00:0C:18:EF:FF:ED
sudo ifconfig eht0 up
三、查看进程占用的地址空间
top命令是下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于的任务管理器
内容解释:
PID:进程的ID
USER:进程所有者
PR:进程的优先级别,越小越优先被执行
NInice:值
VIRT:进程占用的虚拟内存
RES:进程占用的物理内存
SHR:进程使用的共享内存
S:进程的状态。S表示休眠,R表示正在运行,Z表示僵死状态,N表示该进程优先值为负数
%CPU:进程占用CPU的使用率%
MEM:进程使用的物理内存和总内存的百分比
TIME+:该进程启动后占用的总的CPU时间,即占用CPU使用时间的累加值。COMMAND:进程启动命令名称
四、什么是软链接, 什么是硬链接
Linux上的文件类型有:目录文件、普通文件、链接文件、管道文件、字符设备文件、块设备文件、套接字文件七种。而链接文件分为硬链接和软链接两种。
1、inode
在Linux文件系统中,保存在磁盘分区下的文件不管什么类型的都会给它分配一个编号,这个编号就是索引节点编号(Inode Index),它是文件或目录在一个文件系统中的唯一标识,存放文件重要的参数信息,包括文件大小、归属的用户、读写权限等信息,而文件实际的数据放置在数据区域里面(data block)。
要了解inode节点,先了解文件系统,linux使用的是一种EXT4的索引文件系统。EXT4在磁盘格式化的时候,将磁盘空间分为3部分:superblock、inode、block
superblock:存储整个文件系统的信息,包括inode和block的总量、使用量、剩余量。
inode:存储文件的属性信息大小等,包括文件的权限、归属的用户、用户组,创建和修改信息等。
block:存储文件的真实数据,每个block都有一个对应的编号,就是索引号,一般情况下一个inode会对应一个或多个block。
2、软链接
又称符号链接,相当于windows下的快捷键,软链接是一个普通文件,其数据块内存储源文件的绝对路径,并不存储源文件的内容,所以通过这个方式就可以快速寻找到源文件实体。软链接可对文件和目录创建。但是软链接使用不同的inode节点。
(1)软链接的创建
ln -s 源文件 链接文件
我们可以发现链接文件的大小很小,这是因为软链接文件只存储源文件的路径。
通过ls -i来查看文件的节点号,可以知道软连接的节点号和源文件的节点号不一样的
3、硬链接
硬链接相当于源文件的别名,且硬链接文件和源文件使用的是同一个inode节点,硬链接通过索引节点进行链接。在Linux系统中,多个文件明指向同一索引节点是正常且允许的,一般这种链接就称为硬链接。硬链接的作用之一就是允许一个文件拥有多个有效路径名。
硬链接可以防止源文件误删,这是因为如果一个文件有多个硬链接的时候,删除其中一个链接并不会影响其他链接和索引节点本身,即数据实体并未删除,只有最后一个链接删除后,此时如果有新的数据要存入磁盘,文件的数据块和链接才被释放,空间被新的数据覆盖。
(1)创建硬链接
ln 源文件 硬链接文件
如果只使用ls -l命令查看硬链接和源文件,很难知道他们的区别,但是如果使用ls -i命令,我们就知道,硬链接和源文件的节点号是一样的。
4、软链接和硬链接的特点
(1)软链接
软链接存放的是另外一个文件的路径;
软链接可以跨文件系统,硬链接不可以;
软链接可以对一个不存在的文件链接,硬链接必须要有源文件;
软链接可以对目录链接。
(2)硬链接
只是以副本的形式出现,和源文件一样指向同一个inode,不占用实际的空间;
不允许给目录创建硬链接;
只能在同一个文件系统创建硬链接;
删除其中一个硬链接文件不影响其他具有相同inode号的文件。
五、什么是文件IO, IO常用的系统调用有哪些? 如何实现文件拷贝?
(1)文件I/O
Linux系统下,一切皆文件,所谓文件I/O,就是文件的Input/Output,指文件的输入输出(读写文件)。
(2)I/O常用的系统调用
open():系统调用用来打开一个文件,并返回一个文件描述符(file description), 并且该文件描述符是当前进程最小、未使用的文件描述符数值,一般是3。
creat():数用来创建一个新文件并返回其fd。它等价于 open(path, O_WRONLY|O_CREAT|O_TRUNC, mode)
close():用来关闭一个打开的文件描述符,关闭一个文件时还会释放该进程加在该文件上的所有记录锁。当一个进程终止时,内核将会自动关闭它所有打开的文件。
lseek():调整文件偏移量的地址。
read():用来从打开的文件描述符对应的文件中读取数据放到buf指向的内存空间中去。
write():用来往打开的文件描述符fd指向的文件中写入数据。
dup() 和 dup2():都可以用来复制一个新的文件描述符来指向fd对应的文件。这两个系统调用经常用在标准输入、标准输出、标准出错重定向。
stat()和fstat():这两个函数都是用来返回文件或目录的相关信息。
unlink():该系统调用可以用来删除文件,其本质是让文件的链接记数自减。
rename():将文件重命名。
等等
(3)实现文件拷贝
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
int main()
{
int fd1, fd2;
int rv;
char buf[1024];
fd1 = open("./test1.txt", O_RDONLY, 0666);
fd2 = open("./test2.txt", O_CREAT|O_WRONLY|O_TRUNC, 0666);
while(1)
{
memset(buf, 0, sizeof(buf));
rv = read(fd1, buf, sizeof(buf));
if(rv < 0)
{
printf("read data from test1.txt failure:%s\n", strerror(errno));
return -1;
}
if(rv == 0)
{
printf("copy over!\n");
break;
}
rv = write(fd2, buf, strlen(buf));
if(rv < 0)
{
printf("write data to test2.txt failure:%s\n", strerror(errno));
return -2;
}
}
close(fd1);
close(fd2);
return 0;
}
六、什么是内核态和用户态? 如何实现内核到用户的转换?
用户态和内核态是操作系统的两种运行状态。
1、内核态:
处于系统内核态的CPU可以访问任意的数据,包括外围设备,比如网卡、硬盘等,处于内核态的CPU可以从一个程序切换到另外一个程序,并且占用CPU不会发生抢占情况,一般处于特权级0的状态我们称之为内核态。
2、用户态:
处于用户态的CPU只能受限地访问内存,并且不允许访问外围设备,用户态的CPU不允许独占,也就是CPU能够被其他程序获取。
3、为什么需要内核态和用户态
我们知道我们所写的程序,在运行的时候会被编译、解析称一条条指令,然后给CPU执行,由于CPU指令的重要性不同,而操作的权限也不同。CPU 指令是做了权限划分的, 例如 Intel X86 中将 CPU 指令权限划分为了 4 个等级:数字越小等级越高。Linux操作系统中主要采用了0和3两个特权级,分别对应的就是内核态(Kernel Mode)与用户态(User Mode)。有一些指令执行失败了对系统没有影响,而有一些指令失败了会导致整个操作系统崩溃。如果将这些指令随意开放给应用程序的话,整个系统崩溃的概率将会大大的增加,而这也体现了为什么要区分用户态和内核态的原因。
4、用户态切换到内核态
一个进程可以运行在用户态也可以运行在内核态,那它们之间肯定存在用户态和内核态切换的过程。打一个比方:C库接口malloc申请动态内存,malloc的实现内部最终还是会调用brk()或者mmap()系统调用来分配内存。具体可以分为以下三种:
(1)系统调用
所有用户程序都是运行在用户态的,但是有时候程序确实需要做一些内核态的事情,例如从硬盘读取数据等。而唯一可以做这些事情的就是操作系统,所以此时程序就需要向操作系统请求以程序的名义来执行这些操作。这时需要一个这样的机制:用户态程序切换到内核态,但是不能控制在内核态中执行的指令。这种机制叫系统调用,在CPU中的实现称之为陷阱指令(Trap Instruction)。
(2)异常事件
当CPU正在执行运行在用户态的程序时,突然发生某些预先不可知的异常事件,这个时候就会触发从当前用户态执行的进程转向内核态执行相关的异常事件,典型的如缺页异常。
(3)外围设备的中断
当外围设备完成用户的请求操作后,会像CPU发出中断信号,此时,CPU就会暂停执行下一条即将要执行的指令,转而去执行中断信号对应的处理程序,如果先前执行的指令是在用户态下,则自然就发生从用户态到内核态的转换。
七、什么是进程上下文与中断上下文?
1、进程上下文:
(1)进程上文:其是指进程由用户态切换到内核态是需要保存用户态时cpu寄存器中的值,进程状态以及堆栈上的内容,即保存当前进程的进程上下文,以便再次执行该进程时,能够恢复切换时的状态,继续执行。
(2)进程下文:其是指切换到内核态后执行的程序,即进程运行在内核空间的部分。
2、中断上下文:
(1)中断上文:硬件通过中断触发信号,导致内核调用中断处理程序,进入内核空间。这个过程中,硬件的一些变量和参数也要传递给内核,内核通过这些参数进行中断处理。中断上文可以看作就是硬件传递过来的这些参数和内核需要保存的一些其他环境(主要是当前被中断的进程环境。
(2)中断下文:执行在内核空间的中断服务程序。
八、多线程为什么要设置属性, 为什么设置栈的大小?
1、线程的主要属性
线程的属性如下,其存于结构体pthread_attr_t中
typedef struct
{
int detachstate; //线程的分离状态
int schedpolicy; //线程调度策略(线程优先级)
structsched_param schedparam; //线程的调度参数
int inheritsched; //线程的继承性
int scope; //线程的作用域
size_t guardsize; //线程栈末尾的警戒缓冲区大小(栈溢出时可以多溢出的大小)
int stackaddr_set; //线程的栈设置
void* stackaddr; //线程栈的位置
size_t stacksize; //线程栈的大小
}pthread_attr_t;
线程属性主要包括:分离的状态(detached state)、栈地址(stack address)、栈尺寸(stack size)、优先级(priority)、作用域(scope)、调度策略和参数(scheduling policy and parameters)。
默认的属性为:非绑定、非分离、缺省的堆栈、与父进程同样级别的优先级。
对于分离和非分离(可会合)属性,主线程和子线程通常定义以下两种关系:
可会合(joinable):这种关系下,主线程需要明确执行等待操作,在子线程结束后,主线程的等待操作执行完毕,子线程和主线程会合,这时主线程继续执行等待操作之后的下一步操作。主线程必须会合可会合的子线程。在主线程的线程函数内部调用子线程对象的wait函数实现,即使子线程能够在主线程之前执行完毕,进入终止态,也必须执行会合操作,否则,系统永远不会主动销毁线程,分配给该线程的系统资源也永远不会释放。
相分离(detached):表示子线程无需和主线程会合,也就是相分离的,这种情况下,子线程一旦进入终止状态,这种方式常用在线程数较多的情况下,有时让主线程逐个等待子线程结束,或者让主线程安排每个子线程结束的等待顺序,是很困难或不可能的,所以在并发子线程较多的情况下,这种方式也会经常使用。
2、为什么要设置栈的大小
一般我们在使用创建和使用线程的时候都是使用一个系统给我们的默认属性值,这是因为默认的线程属性可以满足我们日常的开发需求,但是如果我们对程序的性能提出更高的要求就需要设置线程的属性了。例如,可以通过设置线程栈的大小来降低每个线程内存的使用,从而可增加最大线程个数。
九、进程间通信有几种?
-
信号 ( Sinal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生,信号可以在任何时候发送给某一进程,Linux提供了几十种信号,信号之间依靠他们的值来区分,在程序中用名字来表示一个信号。信号是在软件层次上对中断机制的模拟,是一种异步通信,信号也可以在用户空间进程和内核之间直接交互。
-
管道(Pipe):管道是一种半双工的通信方式(FIFO),数据只能单向流动,而且只能在具有亲缘关系(通常是指父子进程关系)的进程间使用;管道可以看成是一种特殊的文件,对于它的读写也可以使用普通的read、write 等函数。但是它不是普通的文件,并不属于其他任何文件系统,并且只存在于内存中。管道是通过调用pipe函数创建的。
-
命名管道FIFO:命名管道(Named Pipe)也是半双工的通信方式,但是它允许无亲缘关系进程间的通信;
-
命名socket或UNIX域socket(Named Socket或Unix Domain Socket):socket也是一种进程间通信机制,可用于不同进程间的进程通信,而且是双向通信;它也提供了两类套接字:字节流套接字(有点像TCP)和数据报套接字(有点像UDP)。
-
信号量(Semaphore):信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段;
-
共享存储(Shared Memory):共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据。
-
消息队列(Message Queue,简称MQ):消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点;MQ 传递的是消息(一块数据),消息即是我们需要在进程间传递的数据。MQ 采用链表来实现消息队列,该链表是由系统内核维护,系统中可能有很多的 MQ,每个 MQ 用消息队列描述符(消息队列 ID:qid)来区分,qid 是唯一的,用来区分不同的 MQ。在进行进程间通信时,一个进程将消息加到 MQ 尾端,另一个进程从消息队列中取消息(不一定以先进先出来取消息,也可以按照消息类型字段取消息),这样就实现了进程间的通信。如下图: