Linux/操作系统
1.死锁相关
什么是死锁
多个进程在运行过程中争夺资源而形成僵持状态,若没有外力作用,他们都将无法再向前推进。
产生死锁的原因
- 资源竞争(不可剥夺资源,临时资源)
- 非法的进程推进顺序
ps:不可剥夺资源是指将资源分配给某一进程之后,不能强行收回,只能等进程自己释放
可剥夺资源是指将资源分配给某一进程之后,该资源可以被其他进程剥夺
产生死锁的4个必要条件:
- 互斥条件:进程对资源进行排他性控制,在某一时间内某资源仅被一进程占用。
- 请求和保持:当进程因请求资源而阻塞时,对以获得的资源保持不放。
- 不剥夺条件:在资源未被使用完之前,只能由该进程自己释放,不能剥夺。
- 环路等待条件:当发生死锁时,一定存在一个进程/资源的环形链。
预防死锁的方法:
- 破坏请求条件:资源一次性分配。
- 破坏保持条件:只要有一个资源得不到分配,也不给这个进程分配其他资源。
- 破坏不可剥夺条件
- 破坏环路等待条件:资源有序分配
解决死锁的方法:
- 剥夺资源
- 撤销进程
银行家算法
申明所需最大资金量
贷款数量不能超过自己用由的最大值
如何查看线程死锁
- 通过jstack命令进行查看,jstack命令中会显示发生了死锁的线程
- 或者两个线程中操作数据库时,数据库发生了死锁,这时可以查询数据库的死锁情况
1、查询是否锁表
show OPEN TABLES where In_use >0;
2、查询进程
show processlist
3、查看正在锁的事务
SELECT * FROM INFOMATION_SCHEMA.INNODB_LOCKS;
4、查看等待锁的事务
SELECT * FROM INFORMATION_SCHEMA.INNODH_LOCK_WAITS;
2.进程、线程
https://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html
(一) 二者的区别
-
线程依托于进程,一个进程中执行的每个任务就是一个线程,进程是执行中的程序
-
进程是资源分配的最小单位,线程是CPU调度的最小单位
-
进程之间互相独立、数据难以共享、不会相互影响;线程之间资源共享
-
在系统中,如果一个进程出现问题并不会影响其他进程的运行,但是线程的崩溃会造成同一进程下的其他线程也崩溃。多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些
进程的三种状态:阻塞、就绪、执行
线程的五种状态:初始、等待、执行、就绪、终止
- 进程是具有一定功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源调度和分配的一个独立单位。
- 线程是进程的实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。
- 一个进程可以有多个线程,多个线程也可以并发执行
(二)进程的切换比线程的代价更大?
进程切换分两步:
1.切换页目录以使用新的地址空间
2.切换内核栈和硬件上下文
对于linux来说,线程和进程的最大区别就在于地址空间,对于线程切换,第1步是不需要做的,第2是进程和线程切换都要做的。
切换的性能消耗:
1、线程上下文切换和进程上下文切换一个最主要的区别是线程的切换虚拟内存空间依然是相同的,但是进程切换是不同的。这两种上下文切换的处理都是通过操作系统内核来完成的。内核的这种切换过程伴随的最显著的性能损耗是将寄存器中的内容切换出。
2、另外一个隐藏的损耗是上下文的切换会扰乱处理器的缓存机制。简单的说,一旦去切换上下文,处理器中所有已经缓存的内存地址一瞬间都作废了。还有一个显著的区别是当你改变虚拟内存空间的时候,处理的页表缓冲(processor’s Translation Lookaside Buffer (TLB))或者相当的神马东西会被全部刷新,这将导致内存的访问在一段时间内相当的低效。但是在线程的切换中,不会出现这个问题。
(二)线程同步的方式有哪些?
- 互斥量:采用互斥对象机制,只有拥有互斥对象的线程才有访问公共资源的权限。因为互斥对象只有一个,所以可以保证公共资源不会被多个线程同时访问。
- 信号量:它允许同一时刻多个线程访问同一资源,但是需要控制同一时刻访问此资源的最大线程数量。
- 事件(信号):通过通知操作的方式来保持多线程同步,还可以方便的实现多线程优先级的比较操作。
- 临界区:当多个线程访问一个独占性共享资源时,可以使用临界区对象。拥有临界区的线程可以访问被保护起来的资源或代码段,其他线程若想访问,则被挂起,直到拥有临界区的线程放弃临界区为止。
(三)进程的通信方式有哪些?
主要分为:管道、系统IPC(包括消息队列、信号量、共享存储)、SOCKET
管道主要分为:普通管道PIPE 、流管道(s_pipe)、命名管道(name_pipe)
- 管道是一种半双工的通信方式,数据只能单项流动,并且只能在具有亲缘关系的进程间流动,进程的亲缘关系通常是父子进程
- 命名管道也是半双工的通信方式,它允许无亲缘关系的进程间进行通信
- 信号量是一个计数器,用来控制多个进程对资源的访问,它通常作为一种锁机制。
- 消息队列是消息的链表,存放在内核中并由消息队列标识符标识。
- 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
- 共享内存就是映射一段能被其它进程访问的内存,这段共享内存由一个进程创建,但是多个进程可以访问。
- Socket主要是实现不同机器之间的进程间信息交互
(四)进程有哪几种状态?
- 就绪状态:进程已获得除处理机以外的所需资源,等待分配处理机资源
- 运行状态:占用处理机资源运行,处于此状态的进程数小于等于CPU数
- 阻塞状态: 进程等待某种条件,在条件满足之前无法执行
应该注意以下内容:
- 只有就绪态和运行态可以相互转换,其它的都是单向转换。就绪状态的进程通过调度算法从而获得 CPU 时间,转为运行状态;而运行状态的进程,在分配给它的 CPU 时间片用完之后就会转为就绪状态,等待下一次调度。
- 阻塞状态是缺少需要的资源从而由运行状态转换而来,但是该资源不包括 CPU 时间,缺少 CPU 时间会从运行态转换为就绪态。
(五)说一说进程同步有哪几种机制。
临界区、同步与互斥、信号量、管程
(七)什么是缓冲区溢出?有什么危害?其原因是什么?
缓冲区溢出是指当计算机向缓冲区填充数据时超出了缓冲区本身的容量,溢出的数据覆盖在合法数据上。
危害有以下两点:
- 程序崩溃,导致拒绝额服务
- 跳转并且执行一段恶意代码
造成缓冲区溢出的主要原因是程序中没有仔细检查用户输入。
(八)僵尸进程和孤儿进程
僵尸进程: 一个父进程利用fork创建子进程,如果子进程退出,而父进程没有利用wait 或者 waitpid 来获取子进程的状态信息,那么子进程的状态描述符依然保存在系统中。
**孤儿进程:**一个父进程退出, 而它的一个或几个子进程仍然还在运行,那么这些子进程就会变成孤儿进程,孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集的工作
3.缓存
高速数据存储层,通常是短暂性存储,速度比访问数据的主存储位置块,可以高效重用之前检索过或计算过的数据,减少对底层存储层(速度慢)的访问,以提高数据检索性能。
4.虚存与实存
https://www.cnblogs.com/CareySon/archive/2012/04/25/2470063.html
虚存(VIRT = SWAP + RES):
- 进程“需要的”虚拟内存大小
- 包括进程使用的库、代码、数据,以及 malloc、new 分配的堆空间和分配的栈空间等
- 申请 10 MB,使用 1 MB,增长 10 MB
实存(RES = CODE + DATA):
- 包括使用中的 malloc、new 分配的堆空间和分配的栈空间,但不包括 swap out 量
- 包含其他进程的共享
- 虚存包括实存
- 申请 10 MB,使用 1 MB,增长 1 MB
共享内存(SHR):
- 自身,也包括其他进程的共享内存
- 进程只使用了几个共享库的函数,但包含整个共享库大小
- 某个进程所占的物理内存大小:RES - SHR
- swap out 后,它将会降下来
5、有一些任务紧急的进程需要执行,采用什么调度算法?
可以采用优先级调度,使用剥夺式。
其中剥夺式又称为抢占式,即我不等你现在运行的到那步了,我来了就是我上!
① 先来先服务 FCFS,从后备队列选择最先进入的作业,调入内存。
② 短作业优先 SJF,从后备队列选择估计运行时间最短的作业,调入内存。平均等待时间、平均周转时间最少。
③ 优先级调度算法,分为非剥夺式和剥夺式。
④ 高响应比优先算法,综合了 FCFS 和 SJF,同时考虑了每个作业的等待时间和估计的运行时间。
⑤ 时间片轮转算法,遵循先来先服务原则,但是一次只能运行一个固定的时间片。
一些简单操作:
使用linux命令或者shell实现:文件words存放英文单词,格式为每行一个英文单词(单词可以重复),统计这个文件中出现次数最多的前10个单词。
cat words.txt | sort | uniq -c | sort -k1,1nr | head -10
sort: 排序
uniq: 唯一,-c是count的缩写 就是求出所有内容
sort -k1,1nr: 表示按照第一个字符进行排列,然后按照1来进行n(排列)r(倒序)
修改某文件中的abc 变为 def
cat words.txt | tr abc def
# 全部替换大小写
cat words.txt | tr a-z A-Z
# 或者
sed 'y#abc#def#' a.txt
sed 's#abc#def#' a.txt
其中y和s的区别在于是否持续寻找符合条件的内容,s表示是替换掉第一个符合条件的就可以了
查看服务器的进程,并找到名字中带有mysql的进程
ps -ef | grep mysql
写一个 bash 脚本以统计一个文本文件 words.txt 中每个单词出现的频率。
注意几个关键词:词频降序排列、统计每个单词出现次数、使用一行命令实现。
① 使用 xargs 将所有行转为单列显示:
cat words.txt | xargs -n1
其中xargs -n1 表示每次输出的内容个数为1
② 使用 sort + uniq 函数进行排列:
sort -nr 表示依照数值的大小降序排序。
uniq -c 表示在每列旁边显示该行重复出现的次数。
cat words.txt | xargs -n1 | sort | uniq -c | sort -nr
③ 使用 awk + print 函数将 1、2 列位置互换:
cat words.txt | xargs -n 1 | sort | uniq -c | sort -nr | awk ‘{print $2" "$1}’
至此,本题已解。
代码
cat words.txt | xargs -n 1 | sort | uniq -c | sort -nr | awk ‘{print $2" "$1}’
awk命令
awk '{pattern + action}' {filenames}
#############################################
[root@zhoucentos log]# head -5 /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
##############################################
head -5 /etc/passwd | awk -F ':' '{print $1}'
### 简单认为就是以:作为区分符号,然后输出第一列内容把。
Linux下查看进程个端口
#基本操作
ps # 查看所有正在运行的进程信息
ef # 查看父进程信息
a # 当前终端所有运行的进程信息
u # 以用户的信息显示进程
x # 显示后台所有运行的进程参数
aux # 以用户的信息显示当前终端运行的所有进程信息和所有后台运行的进程参数
grep # 查找文件中符合条件的字符串
t # 仅显示tcp相关选项
u # 仅显示udp相关选项
n # 拒绝显示别名,能显示数字的全部转化为数字
l # 列出所有在listen的服务状态
p # 显示建立连接的程序名
r # 显示路由信息,路由表
e # 显示扩展信息,例如uid等
s # 按各个协议进行统计
c # 每隔一个固定时间,执行该netstat命令。
# 注意:LISTEN和LISTENING的状态只有用-a或者-l才能看到
A|B # 用A输出的结果进一步查看B
#根据进程名查看进程信息
ps -ef | grep tomcat
#根据进程ID查看进程信息
ps -ef | grep 1095
#根据进程ID查看被占用的端口
netstat -nap | grep 1095
#根据端口查看对应的进程
netstat -tunlp | grep 8080
#根据进程ID杀死进程
kill -9 1095