Version: Next
Linux 相关问题
Linux 根目录构成
- 都挂在
/
路径下面 - Linux 中一切皆
文件
,Linux 会把计算机硬件都映射为一个个文件来进行管理 - 第一部分:必须有的
目录 | 解释 |
---|---|
/bin | 系统有很多放置可执行文件的目录,但 /bin 比较特殊它放置在单人维护模式下还能够被操作的 指令 ,可以被 root 与一般账号使用如 cat 、chmod 、chown 、date 、mv 、cp 、bash |
/boot | 存放开机使用到的文件 |
/dev | 任何设备与周边设备都是以文件的形态存在于这个目录中的,存取这个目录下的文件,等效于存储某个设备 如 /dev/null、/dev/zero、/dev/zero、/dev/loop |
/etc | 系统主要配置文件目录 一般用户可读,只有 root 用户可写,不建议将可执行文件放在这里 /etc/passwd、/etc/fstab、/etc/opt |
/lib | 放置在开机时会用到的库函数,以及 /bin 或者 /sbin 下面的指令会调用到的库函数 /lib/module/ 目录存放可抽换式驱动程序 |
/mnt | 挂载额外设备,建议挂载在这个目录 |
/opt | 给第三方协力软件放置的目录 习惯上也把第三方安装在 /usr/local 目录 |
/run | 存放开机后产生的各项信息 早期在 /var/run,最新规范在 /run /run 可以使用内存来方针 |
/sbin | 设置系统环境的内容,此处为 root 才能使用的,开机过程中需要使用的开机、修复、还原系统指令 某些服务器软件程序,则放置在 /usr/sbin 中 本机自行安装的软件产生的系统可执行文件放在 /usr/local/sbin |
/srv | service 的缩写,一些网络服务启动后,这些服务所需要去用数据用的目录 如WWW、FTP |
/tmp | 让一般使用者或者正在执行的程序临时存东西的地方 任何人都能用,建议定期清理 规范建议每次开机时都删除 |
/usr | Unix SoftWare Resource 规范建议开发者将各自数据合理放置到该目录下,而不要自行创建该软件自己独立的目录 类似于 windows 的 C:\Windows 和 C:\Program files 的结合体 |
/var | 常态性变动文件,包括高速缓存 cache、登录文件 log file 以及某些软件运行所产生的的文件 包括程序文件 lock file, run file 或例如 MySQL 数据库文件等 /var/lib/mysql /var/log/ 登录文件存放目录/var/run 某些程序、服务启动后,会将他们的 PID 存放在这里;链接到 /run |
- 第二部分:建议存在
目录 | 解释 |
---|---|
/home | 系统默认的主使用者的主文件夹,当新增一个一般用户账号时,默认使用的主文件夹~ 代表当前用户的 home 目录~用户名 :代表某个用户的家目录 |
/lib<qual> | 用来存放与 /lib 不同格式的二进制函数库,例如 64 为函数库 |
/root | root 用户的主文件夹,放在这里是因为如果进入单人维护模式而仅挂载根目录时,该目录就能够拥有 root 的主文件夹 |
- 其他重要目录
目录 | 解释 |
---|---|
/lost + found | 使用标准的 ext2、ext3、ext4 文件系统格式才会产生的目录,用于文件系统发生错误时,将一些遗失的片段存到这里 |
/proc | 这个目录本身是一个 虚拟文件系统 他放置的数据都是在 内存 中的,例如系统核心、进程信息、周边设备以及网络状态等/proc/cpuinfo、/proc/dma、/proc/interrupts、/proc/ioports、/proc/net/* |
/sys | 与 /proc 比较像,也是虚拟文件系统,记录核心与系统硬件相关信息 包括目前已载入的核心模块与核心侦测到的硬件设备信息等 |
- 关于 CentOS7 上述目录的一些链接关系
- /bin -> /usr/bin
- /sbin -> /usr/sbin
- /lib -> /usr/lib
- /lib64 -> /usr/lib64
- /var/lock -> /run/lock
- /var/run -> /run
Linux 进程
Linux 进程结构
代码段 + 堆栈段 + 数据段
- 代码段:存放程序代码的数据,假设计算机中有几个进程运行相同的程序,那么他们可以
共用
相同的代码段- 堆栈段:存放子程序的返回地址、子程序的参数以及程序的局部变量 (不能共用)
- 数据段:存放程序的全局变量、常数、动态分配的数据空间(不能共用)
父进程 | 子进程 | fork | exec 函数族
fork
用来创建新进程,该进程几乎是当前进程的一个完全拷贝exec
用来启动另外的进程以取代当前运行的进程
除了
0
号进程由系统创建以外,Linux 中的进程都是由其他进程创建的
- 创建新进程,则
父进程
为调用fork()
函数的进程,新创建的进程为子进程
- 父进程在创建子进程时,子进程会把父进程的地址空间里的
数据段
、堆
、栈
进行复制,但不复制代码段- 在复制瞬间数据基本一致,但之后各自运行,数据段、堆栈段的数据就开始不一样了
- 在 fork 时 Unix 体系做了优化,实际上只是
逻辑 fork
,物理上堆栈段数据段还是共享的- 一旦写入新数据,则立刻升级为
物理 fork
,各自具有独立的堆栈段、数据段- 此时父子进程之间的区别仅在于
pid
、ppid
以及资源统计量(例如挂起的信号)exec() 也可以创建进程
- 读取可执行文件并载入当前地址空间执行,一般称为 exec 函数族,有一系列以
exec
开头的函数,例如execl
、execve
fork 函数
Fork 函数不需要任何参数,一次调用, 返回两次,分别返回父进程和子进程
- 对于父进程,fork 函数返回新建子进程的
pid
- 对于子进程,fork 函数返回
0
- 如果出错,fork 函数返回
-1
- 出错原因
- 系统中已经有太多的进程
- 调用 fork 函数的用户的进程太多
子进程还获得与父进程任何打开文件描述符相同的拷贝,意味着子进程可以读取父进程中打开的任何文件
- 父进程和新创建的子进程之间最大的
区别
在于他们具有不同的 PID
execve 函数
execve() 系统调用的作用是运行另一个指定程序
- 会将新程序加载到当前进程的内存空间内,当前进程被丢弃,它的堆、栈和所有的段数据都会被新进程相应的部分代替
- 需要提供参数,包括:文件名 filename、参数列表 argv、环境变量 envp
- 之后,从新程序的
初始化代码
和main
函数开始执行,进程 PID 保持不变
fork + exec = 启动另一程序且自身保持运行
- 如果某程序想要启动另一个程序,但自身继续存活运行,那么就好结合 fork 与 exec 的使用
例:shell 命令执行 ps 命令
- shell 进程 fork 一个子进程
- 利用 exec 系统调用将子进程完全替换为 ps 进程
孤儿进程与僵尸进程
基本概念
- 如上图所示,子进程的结束和父进程的结束是一个异步过程,即父进程无法预知子进程什么时候结束
- 当一个子进程完成工作并终止后,父进程需要调用
wait()
或waitpid()
系统调用取得子进程的终止状态孤儿进程
- 一个父进程退出,而父进程的一个或多个子进程还在运行,那么这些子进程就成了
孤儿进程
- 孤儿进程将被
init 进程
(进程号为1
)所收养,并由 init 进程对他们完成状态收集工作init 进程
进行了接管,可以认为没什么危害僵尸进程
- 一个进程使用
fork
创建子进程,如果子进程退出,而父进程没用调用wait()
或waitpid()
获取子进程状态信息,那么子进程的进程描述符仍然保持在系统中,称为僵尸进程
- 几乎放弃所有内存空间,没有任何可执行代码,不能被调度,仅在进程列表中保留一个位置,记载该进程的退出状态等信息供其他进程收集
- 占用了
进程号
,如果太多会耗尽系统资源,导致不能开出新进程- 僵尸进程不能用
kill
命令清除,因为它是已经退出的进程,**必须清除其 `父进程
如何杀死僵尸进程
- 如何找到僵尸进程的父进程?
ps -ef | grep defunct_process_pid
- 如何找出僵尸进程?
ps aux | grep Z
- 如何杀掉僵尸进程的父进程
kill -s SIGCHLD pid
,其中pid
更换为父进程真实 ID
Linux 进程间通信
推荐阅读 《UNIX 环境高级编程》
- 管道
- 共享内存
- 信号量
- 套接口 Socket
管道
进程通信中最古老的方式,分为两种
- 无名管道:用于父进程、子进程通信 ——
pipe()
函数- 有名管道: 用于同一台计算机上
任意
两个进程间通信 ——mknod()
或mkfifo
函数生成管道后,就可以使用一般文件的 I/O 函数,如
open
、close
、read
、write
等来对它进行操作
共享内存
运行在同一台计算机上的进程之间通信速度最快的方式,因为数据不需要在不同的进程间复制
- 通常由一个进程创建一块共享内存区,其余进程对这块区域进行读写
- 在 Linux 下通过
shmXXX
函数族实现利用共享内存进行的存储 (shared memory)
- 例如
shmget
用于获得一个共享存储标识符- 当共享内存创建后,其余进程可以调用
shmat
将其连接到自身的地址空间中void *shmat(int shmid, void *addr, int flag);
shmid
为shmget
函数返回的共享存储标识符
,addr
、flag
参数决定了以什么方式确定连接的地址,函数的返回值是该进程数据段所连接的实际地址,进程可以对此进程进行读写操作- 这种方式要考虑
互斥访问
以及数据同步
问题
信号量
又称
信号灯
- 用来协调不同进程间的数据对象时,最主要的应用是前一节的共享内存方式的进程间通信
- 本质上,是一个
计数器
,用来记录某个资源的存取情况- 为了使用共享内存,一般情况下进程需要执行下列操作
- 测试控制该资源的信号量
- 若此信号量值 > 0,则允许使用资源,同时数值--
- 若信号量值 == 0,则资源不可用,进程进入睡眠状态,直到 值 > 0,进程被唤醒,转入步骤 1
- 当进程不再使用一个信号量控制的资源时,信号量++,如果此时有进程正睡眠等待此信号量,则唤醒该进程
套接字 Socket
- Socket 是实现 Linux 系统和其他大多数操作系统中进程通信的主要方式之一
- 对传输层的实现
用户态陷入内核态
用户态陷入指令——trap、访管指令(系统调用)
- 陷入指令是指用户程序所依靠的指令,用于发起
系统调用
,请求操作系统提供服务- 陷入指令的特殊之处:唯一一种,只能在用户态下执行,不能在核心态执行的指令,在发起系统调用请求,而系统调用的相应处理在核心态下进行
- 用户程序执行陷入指令,立即产生一个
软中断
,相当于将 CPU 的使用主动权交给了操作系统内核
(从用户态切换到内核态),之后操作系统内核程序再对系统调用请求做出相应的处理- 处理完成后,切换回用户态
三种切入方式——中断、异常、陷入机制(系统调用)
系统调用(软中断)
- 是用户态进程主动要求切换到内核态的一种方式,用户态进程通过
系统调用
申请使用操作系统提供的服务程序完成干工作,例如fork()
实际上就是执行了一个创建新进程的系统调用 (内核态的do_fork()
)- 系统调用机制:使用操作系统为用户特别开放的
软中断
——int 80H
- 通过
中断向量表
,查询中断向量
获取中断处理程序
的地址- 保护现场,处理中断请求
异常
- 当 CPU 执行运行在用户态的程序时,发生不可知错误,此时会触发由用户态切换到内核态,执行内核中关于异常的处理程序,例如缺页异常
外部中断(硬中断)
- 外设完成用户请求的操作后,向 CPU 发出响应的硬件中断,CPU 转而进入中断处理流程,如果当时正在执行用户态程序,则会转入内核态
Linux 查看进程状态的指令
两个家伙差不多,源自不同的规范体系
ps -ef | grep
- 特点是能显示
PID
以及PPID
父进程ID
ps aux | grep
- 特点是能显示更多的存储空间消耗信息,比如内存消耗
根据 pid 查看进程状态
- 方式一:通过包管理安装
pidstat
工具 - 方式二:
cat /proc/[pid]/status
lsof 命令
lsof -i :端口号
->lsof -i :80
lsof -i@127.0.0.1
查看到指定主机的连接lsof -i@127.0.0.1:80
lsof -i -sTCP:ESTABLISHED
找出任何处于已连接状态的TCP进程lsof -i | grep -i ESTABLISHED
lsof -p [pid]
查看指定进程 ID 已打开的内容lsof -iTCP
显示所有TCP进程lsof -i 6
仅获取 IPv6 流量
netstat 命令
netstat -ntlp
查看当前所有 TCP 端口netstat -tunlp | grep [端口号]
查看所有端口占用情况- -t:显示 TCP 相关
- -u:显示 UDP 相关
- -n:拒接显示别名,能显示数字的全部转化为数字
- -l:仅列出处于 LISTEN 状态的服务
- -p:显示建立相关连接的进程名字
/proc 路径支持的命令
watch -d cat /proc/interruptes
cat /proc/stat
提供系统 CPU 和任务统计信息cat /proc/stat | grep ^cpu
提供系统 CPU 和任务统计信息,只需要保留各个 CPU的信息cat /proc/interrupts | more
详细信息cat /proc/interrupts | less
ps aux --sort -pcpu | less
根据 CPU 使用,排序,结果能精确到具体程序路径ps aux --sort -pmem | less
根据 内存 使用,排序,结果能精确到具体程序路径cat /proc/cpuinfo | grep "physical id" | sort |uniq |wc -l
查看物理 CPU 数量cat /proc/cpuinfo | grep "cpu cores" | uniq | wc -l
查看每个物理 CPU 的核心数目cat /proc/cpuinfo | grep "processor" | wc -l
查看逻辑 CPU 数目
关机重启命令
shutdown -h now
立即关机shutdown -h 1
1分钟后关机shutdown -r now
立刻重启halt
关机reboot
现在重启sync
将内存数据同步到磁盘
提示
- 不管是重启系统还是关闭系统,首先要运行
sync
命令将内存数据持久化到磁盘 - 目前
shutdown
、reboot
、halt
等命令均已经在关机前自动执行sync
,但是还是小心驶得万年船
用户登录与注销命令
- 用普通用户登录,然后用
su -root
切换到 root 用户,不建议直接登录 root 账户 logout
用来注销当前用户- Logout 指令在图形运行级别无效,在
运行等级3
以下有效
- Logout 指令在图形运行级别无效,在
用户管理
添加用户
useradd 新用户名
- 当创建成功后,会自动创建和用户名相同的 home 目录
- 也可以通过
useradd -d 指定目录 新用户名
为新创建的用户指定 home 目录位置
指定和修改密码
passwd 用户名
- 如果不写
用户名
,默认是 修改当前登录用户的密码