【linux】部分知识点总结

kernal和cpu

kernel: 负责系统管理,比如内存管理,屏蔽了对硬件的操作。
cpu: 硬件层面上的,处理各种指令,提供运算

系统调用

程序都是运行在用户态的。
用来使用系统态级别的子功能的入口。

文件存储

inode

inode:index node, 维护文件的属性信息

文件数据存储在块里。另外还需要inode来存储文件的元信息:某个文件被分成了几块,每一块的地址,文件拥有者,创建时间,权限,大小等。

每个 inode都有一个号码,linux使用inode号码区分不同的文件

使用stat a.txt查看inode信息

目录

  • /bin: 所有二进制可执行文件,常用命令
  • /etc 系统管理和配置文件
  • /home 存放所有用户文件的根目录,用户主目录的基点。
  • /usr 系统应用程序
  • /opt tomcat等安装在这里。额外安装的可选应用程序包一般在这里
  • root 系统管理员住目录
  • /sbin 二进制可执行文件,系统管理员使用的系统级别的管理命令和程序。ifconfig等
  • /dev 用来存放设备文件
  • /mnt 让用户临时挂载其他的文件系统
  • /boot 系统引导时的各种文件

linux基本命令

  1. 增删改查

    cp -r 目录名,目录拷贝的目标位置 -r代表递归: 如果给出的源文件是目录文件,则将复制目录下所有的子目录和文件。

    ls ll区别: ll == ls -l , ll是查看目录下所有目录和文件的详细信息。(例如权限等)

    more一页一页查看

    cat查看全部文件, cat filename.txt | more

  2. 打包并压缩

    tar -zcvf [压缩后的文件名] [要打包压缩的文件]

    z: 调用gzip压缩命令进行压缩
    c: 打包文件
    v: 显示运行过程
    f: 显示文件名

    解压: tar [-xvf] 压缩文件 tar -xvf test.tar.gz
    x: 解压

  3. 开发和调试程序

    netstat 显示网络相关的信息,如网络连接,路由表(-r),接口状态
    -a (all) 显示全部信息

    tcpdump 对网络上的数据包进行截获的包分析工具。

    ipcs提供进程间通信方式的信息,包括共享内存,信号量,消息队列。
    -a 输出所有
    -m 共享内存
    -q 消息队列
    -s 信号

    ipcrm 移除一个消息对象、或者共享内存、或者信号量

  4. 文本处理

    grep 文档详细查找

linux中的权限:

r: 可读。可以使用cat查看文件的内容
w: 可写。可以修改文件的内容
x: 可执行。可将其运行为二进制文件。
  1. 查看所有者: ls -ahl, 修改所有者:chown 用户名
  2. 查看文件所在组:ls -ahl, 修改所有者:chgrp 组名
  3. 其他组:除了这个文件的所有者和所在组的用户外,其他所有用户都属于这个
  4. 修改权限 chmod

linux用户管理

多用户多任务的分时操作系统。

为什么用户之间可以共享文件

shell

Shell是用户与Linux系统之间的接口.用户登录后,要启动一个进程,负责将用户的操作传给内核. 这个进程是用户登陆到系统以后运行的命令解释器。就是shell.

利用这一特点,我们可以限制用户只能运行指定的应用程序

其他命令

常用命令:

grep 要搜索的字符串 要搜索的文件 --color(color表示高亮)

grep 更适合单纯的查找或匹配文本,sed 更适合编辑匹配到的文本,awk 更适合格式化文本,对文本进行较复杂格式处理

ps -ef/ ps -aux 查看当前系统正在运行进程。展示格式不同. ps aux|grep redis查看包括redis字符串的进程

如何排查进程之间的父子关系(pid ppid),怎么判断进程是僵尸进程,ps 能看到啥信息

top

能看到什么系统信息

kill
awk
netstat(什么场景使用到它)

linux中进程的几个状态:

  • Z 僵尸
    kill命令对僵尸进程无效。子进程死了之后,会对父进程发送一个信号。父进程一般利用是忽视。父进程也可以用wait来响应,这时wait可以回收这个僵尸子进程。僵尸进程如果不回收,将保留页表项,导致资源泄露。

  • S 休眠

  • D 不可中断的休眠

  • R 运行

  • T 停止时跟踪

    1. kill -9 进程的pid : 杀死进程(-9表示强制终止)
      disown -r 将所有正在运行的进程移除

    2. 查看后台任务:job -l

    3. 把后台任务调到前台:fg

    4. 把停下来的后台任务在后台执行bg, 调整到前台执行:fg

    5. kill [-s <信息编号>] [程序] 或者 [-l <信息编号>]
      kill -9 pid

    6. 查看系统支持的所有信号: kill -l

    7. dirs 查看当前目录栈

    8. wc 文件多少行多少个字

    9. hash 执行过的命令的完整路径,打印所用过的命令以及执行的次数

    10. let 可以进行整数型的数学运算

网络通信命令

查看当前系统的网卡信息:ifconfig

查看与某台机器的连接情况:ping

查看当前系统的端口使用: netstat -an

shutdown -h now: 现在关机

reboot -w: 重开机

常见的内存管理机制

  • 块式管理:将内存固定的分成几个块,每个块只包含一个进程。
  • 页式管理:将内存分成一页一页的格式,每页大小固定。页比较小。出发点是更好满足内存管理的需求。
  • 段式管理:按照程序员设定的逻辑分段。每段大小是不同的。每段内部是连续的,之间是不连续的。
  • 段页式:把主存先分成若干段,每段再分页。

虚拟地址到物理地址的转换是个问题。需要解决虚拟地址空间大,所以页表也会很大。

块表是什么: 分页管理中,页表的一部分,存放的是虚拟地址到物理地址的转换。存储在cache里,加速虚拟地址到物理地址的转换。

多级页表:避免所有的页表都放到内存中占地方太大。时间换空间。

共享内存

建立软连接和硬链接(文件共享)

1. 硬连接:

(基于索引结点的文件共享方式)。每个文件有一个索引节点,inode中存在一个链接计数count。加入当用户B想要共享这个文件,那么用户B的目录中会增加一个目录项,并设置一个指针来指向该文件的索引结点。链接计数+1.

当B不想访问时,只能将count数目-1,count数目不是0的时候不能删除该文件。

ln link source
2. 软连接:

(利用符号链的共享方式)。比如让用户B共享A的一个文件F,系统会创建一个link类型的新文件取名为F. 将文件F写到用户B的目录里。这个文件F里,包括里B中F文件的路径。只有文件所有者才有指向索引结点的指针。这样不会留下悬空指针的问题。于是拥有者可以删除文件。这时候其他用户根据符号链再去访问时会发生访问失败,于是将符号链删除。(这个路径包括文件所在机器的网络地址和该机器中的文件路径。涉及多次读盘)

ln -s slink source

内存共享的实现原理

一件是在内存划出一块区域来作为共享区;另一件是把这个区域映射到参与通信的各个进程空间。

  1. 内存映射:通过系统调用mmap()把这个文件所占用的内存空间映射到参与通信的各个进程地址空间,则这些进程就都可以看到这个共享区域,进而实现进程间的通信。

查看共享内存: ipcs -m

删除共享内存,使用命令:ipcrm -m [shmid]

共享内存什么时候会释放

用户为什么可以访问其他用户的空间

linux的容器:
namespace/cgroup对系统资源做了一层抽象,让系统资源对进程部分可见,在同一个namespace中的进程,可看到系统资源是一样的。

虚拟内存是什么

  1. 使用硬盘空间扩充内存:访问的信息不在内存时,os将需要的部分调入内存。将不需要的还出。这样系统就为用户维护了一个大得多的存储器,就是虚拟存储器。虚拟存储器的大小由计算机的地址结构决定。

  2. 定义了一个连续的虚拟地址空间。让每个进程都拥有一片完成的内存空间。

逻辑地址、虚拟地址、物理地址

逻辑地址:由程序产生的与段相关的偏移地址部分。比如指针的值就是逻辑地址 。机器语言指令中用来指定一个操作数或一条指令的地址

物理地址:实际的地址

虚拟地址:由计算机的地址结构决定。系统中的每个进程所使用的地址。比内存空间大很多。具体访问到哪个物理地址要看MMU将线性地址转换后的物理地址才能知道。

虚拟内存的技术实现

内存管理需要是离散的:请求分页,请求分段,请求段页式存储。

页面置换算法:

缺页中断:需要访问的页没在内存。

最佳页面置换算法:以后不怎么用的(无法实现
FIFO页面置换算法
LRU: 最近最久未使用页面置换算法(双链表和hashmap,hashmap的value存放链表指针,每次操作将对应的双链表中的值放到双链表的末尾) 
LFU: 最少使用页面置换算法

linux中的锁

  1. 原子操作

    避免操作被进程/线程的调度打断。不会出现上下文切换

    实现方式:指令执行期间,给总线加锁(x86)

  2. 自旋锁spinlock

    使用者想用临界区资源时,如果已经加锁,则不会阻塞,而是原地轮训资源判断是否释放锁。不会出现上下文切换。

    调用线程不会阻塞,但是轮训访问消耗cpu

    实现方式:CAS: compare and switch

     - While( CAS(value1, value2, value3 )) // 轮训访问,直到value1 == value2 时候,将value3赋值该value1
    

    使用场景:预计线程持有时间短。则互斥锁两次上下文切换的开销 > 自旋锁消耗的cpu
    代码经常需要加锁,但是实际情况产生竞争的情况比较少。

  3. 互斥锁

    获得不了互斥锁就被阻塞(挂起),由系统唤醒。

    开销:需要从用户态切换到内核态,申请到锁之后从内核态切换到用户态。这个过程产生两次上下文切换。使用资源后释放锁,从用户态切换到内核态,操作系统唤醒阻塞等待锁的其他进程,进程返回用户态。又有两次

    涉及到缓存、tlb的更新,记录当前进程的堆栈和寄存器中的值。

    目的:保护临界区

    条件变量:线程间共享的同步变量进行同步。用来等待线程而不是上锁。

    场景:被保护的资源需要睡眠

  4. 读写锁

    共享锁和互斥锁。

    读优先的读写锁:读加锁时,任何线程都可以对其进行读加锁操作。但是所有试图进行写加锁的操作都会被阻塞。

  5. 可重入锁和不可重入锁

    Mutex可以分为递归锁(recursive mutex)和非递归锁

    1. 可重入(递归):
    2. 非递归:pthread_mutex_t

    二者唯一的区别是,同一个线程可以多次获取同一个递归锁,不会产生死锁。而如果一个线程多次获取同一个非递归锁,则会产生死锁

mmap: 将内核空间的一段内存区域映射到用户空间。映射成功后,用户对这段内存区域的修改可以直接反映到内核空间,相反,内核空间对这段区域的修改也直接反映用户空间。内核空间对这段区域的修改就直接反映给了用户空间。所以可以实现进程间的文件共享

- 1 (创建虚拟空间)进程启动映射过程,并在进程的虚拟空间中创建连续的虚拟映射区域

- 2 (完成地址映射)调用内核空间的系统调用函数mmap,实现文件磁盘地址和进程虚拟地址的映射。

- 3 进程发起对映射空间的访问。缺页。文件内容copy到物理内存中。这个时候因为建立了和文件磁盘地址的映射,所以只需要一次数据拷贝,就能从磁盘将数据写入内存的用户空间。

和正常状态下读写的区别:mmap更高效。因为它类似于一个指针,直接指向了磁盘空间中的文件,对文件的读写利用这个指针,而不需要调用read write等系统调用函数。直接读写,不用去根据逻辑地址查找页表才能的得到物理地址。然后再去修改。节省了一次页表查询时间。

更新文件很多的时候不适合mmap,因为有大量的回写。

进程

数据段、代码段、pcb进程控制快

场景:多进程方式:nginx, 一个master多个worker; 多线程方式:web server。每当有一个请求,就使用一个线程去处理请求。

linux中的folk, exec, exit, wait sleep

  1. folk: 用户创建进程的唯一方法

一个进程运行folk生成子进程。子进程拥有父进程的代码段和数据段和栈。不同的是pid不同。

写时拷贝:创建子进程时,并不立即复制地址空间,拥有相同的地址空间。当父子进程有一方想要写,则内核申请一个新的物理页,将原物理也中的内容复制到新的物理页中。这个时候父子进程有自己的各自物理内存页。

  1. exec

根据指定的文件名找到可执行文件,并用它来取代调用进程的内容。让子进程丢弃当前拷贝父进程的代码段,创建新的代码段和堆栈。

  1. exit

进程结束函数。在结束进程前,检查进程打开了哪些文件,把文件缓冲区中的内容写回文件。

_exit:直接结束进程,清除使用的内存空间,清除内核中各种数据结构。

区别:他们都写入内存,_exit满足条件才写入文件。所以exit可以保证数据完整性。

  1. wait and sleep

wait释放了锁,等待上一批或者一个脚本执行完(进程执行完),再执行wait之后的命令。

具体措施:父进程调用了wait时,阻塞自己。wait等待当前进程的某个子进程是否已经执行完退出。如果找到了一个退出的变成僵尸的子进程,wait就会销毁这个子进程后返回,执行后面的命令;如果没有就一直阻塞在这里

sleep 制定挂起进程的秒数。时间到了就自动返回。

共享内存存在进程的哪里,共享内存段段最大的限制

共享内存存在进程的数据段,最大限制是0x2000000Byte

堆栈存储

  • 堆:存放一些程序员声明的对象,是由malloc之类函数分配的空间所在地。java中用专门的gc回收
  • 栈:存放函数的参数值,局部变量(因为属于线程)
  • 全局区:全局变量和静态变量,程序结束后,系统自动释放。
  • 文字常量区 —常量字符串就是放在这里的。 程序结束后由系统释放
  • 程序代码区—存放函数体的二进制代码

makefile编写

利用make工具可以自动完成编译工作。

makefile完成了整个工程的编译、链接规则

target ... : prerequisites ...
command
// 待补充

信号

常见的信号,系统如何将信号通知到进程

信号是事件发生时,对进程的通知机制。通常是内核将信号通知给进程

信号通知方式:

内核在进程表项的信号域设置对应信号的位

信号发生的原因

信号发生分成三种原因:1.硬件发生异常 2.用户输入特殊字符(control c中断)(control z暂停)3. 发生了软件事件

怎么发送信号

  1. 用户输入
    kill()方式发送信号。命令允许用户向进程发送信号
    Ctrl-C发送INT信号(SIGINT);默认情况下,这会导致进程终止。
    Ctrl-Z发送TSTP信号(SIGTSTP);默认情况下,这会导致进程挂起。
    Ctrl-\发送QUIT信号(SIGQUIT);默认情况下,这会导致进程终止并且将内存中的信息转储到硬盘(核心转储)。
    (这些组合键可以通过stty命令来修改。)

  2. kill用来发送信号到进程或者杀死进程

    -s sig 信号名称。
    -n sig 信号名称对应的数字。
    -l 列出信号名称。kill -l 9 : 列出9号信号对应的名称:KILL

kill 杀死进程实际上做了什么事情

常用信号:

HUP 1 终端挂断
INT 2 中断(同 Ctrl + C)interrupt
QUIT 3 退出(同 Ctrl + \)
KILL 9 强制终止
TERM 15 终止
CONT 18 继续(与STOP相反,fg/bg命令)
STOP 19 暂停(同 Ctrl + Z)

多线程和多进程的区别

i++是否是原子操作,为什么

不是。i++操作分为三个阶段(读、改、写) 不加锁互斥是不行的

linux系统的各类同步机制

同步机制:互斥锁(mutex)、条件变量(cond)(条件变量必须与互斥锁共同使用;)、读写锁(rwlock)

linux系统各类异步机制

异步机制 - 信号(signal)

任何线程都可以向其它线程(同一进程下)发送信号;
每个线程都具备自己独立的信号屏蔽集,不影响其它线程;
线程创建时,不继承原线程的信号屏蔽集

cpu寻址

根据指令的类型判断寻址方式。存储地址的地方可能会存放寄存器号码,或者内存的直接地址or偏移地址

寄存器寻址
立即数寻址:指令的地址字段存储的就是值
内存寻址(直接寻址,基址寻址:指令中给出的偏移地址加上基址寄存器的值,变址寻址)

IO多路复用

一个进程同时处理多个IO请求

本质:使用select,poll或者epoll函数,挂起进程,当一个或者多个I/O事件发生之后,使用一个进程同时监控多个IO事件。

实现原理:用户将想要监视的文件描述符(File Descriptor)添加到select/poll/epoll函数中,由内核监视,函数阻塞。一旦有文件描述符就绪(读就绪或写就绪),或者超时(设置timeout),函数就会返回,然后该进程可以进行相应的读/写操作。

epoll

epoll是Linux特有的I/O复用函数。一个文件描述符来管理多个描述符。将用户关心的事件放到内核的一个事件列表中。
内核通过红黑树描述这些文件描述符。

epoll解决了select和poll在文件描述符集合拷贝和遍历上的问题,能够在一个进程当中监听多个文件描述符,并且十分高效。

其他问题

  1. Linux如何查看端口占用?
    Netstat -tunlp | grep 80
    Lsof -i:80 需要root权限
  2. Linux下程序崩溃,无法打印log,如何查看哪里出现问题?
  3. Linux下python 调试?pdb如何使用?
  4. Linux下gdb使用?
  5. Linux 下java debug?
    1.ps -e 查看进程 pid; ps -ef 能查看父进程id
    2.top -p pid 查看该进程资源占用情况;
    3.ps -mp pid -o THREAD,tid,time;查看该进程下的各个线程运行时间,根据运行时间可以判断卡再哪个位置;
  6. Printf “%x\n” tid ; 把tid转换为16进制格式;
    5.jstack pid | grep tid -A 30;
    打印pid进程的Java运行信息,截取带有tid线程号的行并输出其后30行的信息
    // 查看端口顺序
  7. Lsof -i:3306 or netstat -tunlp | grep 3306 查看端口占用; 找到对应的pid 或 程序名;
  8. Ps -aux | grep pid or top -p pid 查看该进程的资源占用(看ppid 要用 ps -ef)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值