目录 Linux操作系统 12个问题 爬过六个坡 综述 内核体系结构图 程序运行 系统初始化 进程和线程 使用者管理 软件管理 Linux操作系统 12个问题 在Linux上安装一个软件常用的方式有? make install通过rpm和deb文件通过yum和apt-get下载压缩包解压缩后设置PATH 下列过程在实模式下运行的有? BIOS加载启动扇区启动扇区加载Grub的kernel.imgGrub加载Linux内核Linux内核加载驱动 对于在Linux内核初始化阶段创建进程,下列说法正确的有? 0号进程是所有用户态进程的祖先1号进程是所有用户态进程的祖先1号进程是所有内核态进程的祖先2号进程是所有内核态进程的祖先 下列属于触发系统调用指令的有? int &0x80sysentersyscallsystemcall 对于内核中的进程管理,下列描述正确的有? 将所有进程放在一个链表中,所有线程放在另外一个链表中处于TASK_RUNNING状态的进程一定在占用CPU父进程和子进程之间可以通过指针相互访问从用户态到内核态要切换到内核栈 对于进程调度,下列说法正确的有? 优先级低的进程可以采取FIFO策略对于优先级低的进程可以采取轮流调度策略对于普通进程可以采取CFS调度策略对于实时进程可以采取CFS调度策略 对于进程的内存管理,下列说法正确的有? 进程的代码非常关键,要放在内核态进程的代码非常关键,不能修改进程的栈被划分为两部分,用户栈和内核栈不同进程的内核态映射到相同的地方 对于物理内存的管理,下列说法正确的有? 物理内存先被划分为大小相同的段,然后再分为大小相同的页物理内存的页需要被标记这个页是属于内核的还是用户的很可能CPU访问不同的页速度不同会有多个链表保存空闲的页面 对于文件,下列描述正确的有? 文件描述符仅在一个进程内有效每个进程维护一个file链表,维护它打开的文件操作系统统一维护一个file链表,维护所有打开的文件每个文件都要有一个inode 对于虚拟文件系统,下列描述正确的有? 文件系统需要注册才能使用dentry结构维护了文件名和inode之间的关系每种文件系统对于读,写,打开,关闭操作都可以有自己的实现虚拟文件系统可以对接NFS之类的网络文件系统 对于输入输出设备,下列描述正确的有? 对于设备的操作可以完全使用文件的方式块设备可以使用缓存,也可以不使用缓存进行读写字符设备可以使用缓存,也可以不使用缓存进行读写设备也会关联inode 对于网络通信,下列描述正确的有 七层协议全部都有再内核里面的实现套接字也是一个文件,因而也有inode相同机器的两个进程Socket通信只能通过Loopback相同机器的两个进程Socket通信可以通过文件 爬过六个坡 抛弃旧的思维习惯,熟练使用Linux命令行 《鸟哥的Linux私房菜》《Linux系统管理技术手册》 通过系统调用或者glibc,学会自己进行程序设计 也就是用自己写的代码来操作Linux,使用Linux系统调用或glibc库。《UNIX环境高级编程》 了解Linux内核机制,反复研习重点突破 《深入理解LINUX内核》 阅读Linux内核代码,聚焦核心逻辑和场景 《LINUX内核源代码情景分析》 实验定制Linux组件面向真实场景的开发 综述 Linux Linux里一切皆文件; “一切皆文件”的优势,就是统一了操作的入口,提供了极大的便利。 内核体系结构图 系统调用子系统 进程管理子系统 调度同步任务管理CPU 内存管理子系统 虚拟内存内存映射页表物理内存swap伙伴slab 文件子系统 VFS缓存文件系统 设备子系统 字符设备块设备 网络子系统 套接字协议栈网络设备 程序运行 通过shell在交互命令行里面运行后台运行 nohup (no hang up)tmux tmux new -s your_session_namepython your.pyCtrl + B then D 会话分离,脚本继续在后台运行 以服务的方式运行 系统启动的时候就在的,也就开机自启的 程序管理 kill程序 ps -ef |grep 关键字 |awk '{print $2}'|xargs kill -9ps -ef 显示所有正在运行的程序 xargs 将标准输入中的内容转换成命令行参数,并将这些参数传递给其他命令。 数据处理 sed 行为单位,一般整行处理sed -n '5, 7p' 显示5~7行 awk 行为单位,处理一行中的字段awk '条件类型1{操作1} 条件类型2{操作2} ....'awk '{print $2}' 只打印第二列 开关机 shutdown -h nowreboot 系统调用 进程管理 fork所有的进程都是由父进程,也就说操作系统会有一个“祖宗进程”。 内存管理 申请堆的内存 brk 内存小 mmap 内存大 文件管理 openclosecreatreadwrite 信号处理进程间通信 消息队列共享内存 网络通信 创建套接字socket Glibc Glibc为程序员提供丰富的 API,除了例如字符串处理、数学运算等用户态服务之外,最重要的是封装了操作系统提供的系统服务,即系统调用的封装。 系统初始化 计算机工作模式 Topic1 总线 地址总线 位数决定能访问的内存的大小 数字总线 位数决定一次能读取多少数据 BIOS Basic Input and Output System,基本输入输出系统ROM(Read Only Memory)系统启动过程 BIOS 引导扇区boot.img diskoot.img lzma_decompress.img kernel.img 启动内核 选择一个操作系统 实模式到保护模式,建立分段分页,打开地址栈实模式 指处理器工作在16位模式下,只能寻址1MB的内存空间; 保护模式 保护模式是指处理器工作在32位模式下,可以寻址4GB的内存空间; 内核初始化 start_kernel() 进程初始化 set_task_stack_end_magic(&init_task) 创建创始进程,叫0进程,唯一一个没有通过fork或者kernel_thread产生的进程,是进程列表的第一个; x86的权限机制 ring0 内核ring1 设备驱动ring2 设备驱动ring3 应用 rest_init() kernel_thread() 创建第二个进程,叫1号进程,是所有用户态进程的祖先创建第三个进程,叫2号进程,是所有内核态进程的祖先 ramdisk 根文件系统,这个运行完就到用户态了; 进程和线程 进程 直白点说程序运行起来就叫进程,或者运行起来的一部分程序叫进程。程序到进程的过程,见程序员的自我修养; 线程 是什么 分工产生效能,线程其实就是进程的进一步拆分,线程只负责执行二进制指令,进程出了执行指令,还需要管内存,文件系统等这个程序运行的一堆东西。即使没有主动创建线程,进程也是默认有一个主线程的。 为什么要有线程? 为了并行,多线程 一个进程分为多个线程并行;应对突发,主线程在运行,突然有个小事情也做,重新起一个线程; 并行进程? 进程的并行是有的,只是进程并行有两个缺点,第一,创建进程占用资源太多;第二,进程之间的通信需要数据在不同的内存空间传来传去,无法共享。 线程数据 线程栈上的本地数据整个进程共享的全局数据 如果两个线程同时修改一个全局数据? 共享数据保护 Mutex,全称Mutual Exclusion,中文叫互斥访问共享数据的时候,申请加个锁,申请到了就有访问权限,其他人都等着,访问完了再解锁,就是谁先拿到谁先访问。 如果逻辑上线程a应该先改共享数据,但是a运行的慢了,被线程b先拿到了锁,先改了呢?这种情况不存在,如果有这种逻辑的依赖关系,就不能多线程; 线程私有数据 创建线程 声明线程函数 就是需要多线程运行的那个函数void *threadfunc(void *param) { .... pthread_exit(void *funcOutput); } 声明线程对象 pthread_t thread_name; 设置线程属性 pthread_attr_t thread_attr; pthread_attr_init(&thread_attr); pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE); 创建线程 就是创建好,跑起来了pthread_create(&thread_name, &thread_attr, threadfunc, (void *)funcInput); 销毁线程属性 pthread_attr_destroy(&thread_attr); 等待线程结束 pthread_join(thread_name, (void**)&output); 主线程结束 pthread_exit(NULL); 互斥锁mutex 声明锁 pthread_mutex_t mutex_name; 初始化锁 pthread_mutex_init(&mutex_name, NULL); 在所有访问共享数据的操作前加个锁,访问结束之后解锁 pthread_mutex_lock(&mutex_name);pthread_mutex_unlock(&mutex_name); 销毁mutex锁 pthread_mutex_destroy(&mutex_name); 条件变量 引入一个条件变量,让线程拿不到锁的情况下不用一直傻等,可以先干别的事,等收到主线程通知,再来看条件变量是否满足;主线程 声明锁 pthread_mutex_t lock_name; 声明条件变量 pthread_cond_t cond_name; 初始化锁 pthread_mutex_init(&lock_name, NULL); 初始化条件变量 pthread_cond_init(&cond_name, NULL); 加锁通知所有线程 pthread_cond_broadcast(&cond_name) 解锁销毁锁销毁条件变量 pthread_cond_destory(&cond_name) 主线程退出 子线程 加锁循环判断条件是否满足? 满足 操作共享数据,然后解锁,线程退出 不满足 解锁,等主线通知,收到通知跳转到判断条件是否满足 流程图 Topic1 问题 流程里有一个地方不理解,为什么子线程是先加锁,然后再判断条件?条件变量不是为了拿不到锁的情况下干别的事? 使用者管理 账号管理和权限 账号和用户组 用户标识符 UID User ID,用户ID GID Group ID,用户组ID 账号 /etc/passwd 记录账号名称,UID,GID,说明信息,home目录,shell的默认; /etc/shadow 账号名称,密码,最近修改密码的日期,密码的啥时候能改,啥时候必须改,不改啥时候失效,密码的有效期(也就是账号的有效期) 用户组 /etc/group/etc/gshadow 最主要的功能就是建立用户组管理员,作用就是root太忙,帮忙分担; 初始用户组 就是你最开始的用户组,也就是UID 有效用户组 一个用户可能属于多个用户组,用户新建一个文件,新建文件的用户组就是有效用户组查看 groups 显示的第一个就是 切片有效用户组 newgrp注意是切换,而且是以另外一个shell的方式实现,等搞完了,需要exit退出,有效用户组就又切换回来了。 账号管理 新增与删除用户(系统管理员能使用的功能) useradd useradd [-u UID] [-g 初始用户组] [-G 次要用户组] usernameuseradd参考文件 useradd -D/etc/default/useradd passwdchage 账号密码的详细设置 usermod 新建没建好,需要修改的话 userdel userdel -r username 删除用户和home目录一起 新增删除用户组 groupaddgroupmodgroupdel ACL Access Control List,访问控制列表,作用是提供chmod的那几个之外的权限的详细设置; 用户身份切换 susudo 主机上的用户信息传递 查询用户 id 查看用户UID,GID,groups(支持的所有用户组) w 查看目前系统已登录的用户 who 同上,信息少一点 last 获得目前已登录用户的最后登录时间lastlast username lastlog 获得所有用户的最后登录时间 用户对谈 write write 用户账号,用户所在的终端界面(也就是shell界面)Ctrl + d退出发送消息之前,可以使用who看一下对方在不在线,在那个终端界面,也可以给root发,不过root一般不接受 mesg mesg n 拒绝接收别人的信息,除了root mesg 查看当前状态 mesg y wall 向当前在线所有用户广播消息,包括你自己 用户邮箱 mail /var/spool/mail,存放着每个用户的邮箱mail -s “邮件标题”username@localhost 如果是同一个主机,直接写username就行可以先写好文件,再这样发:mail -s “邮件标题”username@localhost < filename mail内容,以“.”单独一行为结束 文件管理 tree 以树形结构显示文件和目录的层次结构-d 只显示目录,不显示文件。 -L number 指定显示的层级数。 -a 显示所有文件和目录,包括隐藏文件和目录。 -I 指定要忽略的文件或目录 ELF文件相关 readelf 查看ELF文件的头部信息、节表、符号表等-h 查看ELF文件的文件头信息 -S 查看ELF文件的节表信息 -I 查看ELF文件的程序头信息 -s 查看ELF文件的符号表信息 -r 查看ELF文件的重定位表信息 -d 查看ELF文件的动态段信息 -V 查看ELF文件的版本信息 -A 查看ELF文件的体系结构信息 -x 查看ELF文件中指定节的内容readelf -x <section> <filename> -a 查看ELF文件的所有信息 -c 显示.a和.o的函数名 nm 查看ELF文件中的符号表 磁盘配额和高级文件系统管理 磁盘配额(Quota)高级文件系统管理 磁盘阵列RAID逻辑卷管理器LVM 进程管理 任务管理(job control) 在同一个终端,同时执行多个任务,其实就是挂后台(这里是bash的后台,不是系统的后台);& 命令的最后加&会被放到后台执行,不过输出还是打印到屏幕上,所以不想看到输出就重定向; ctrl+z 将目前的这个任务丢到后台中,并且暂停,比如vim文件中,要找别的信息,在一般模式下ctrl+z,回到终端然后找完再fg回来就行 jobs 查看目前的后台状态,仅是你的 fg 将后台任务拿到前台处理fg %jobnumber %可省略 bg 让任务在后台的状态变为运行中bg %jobnumber %可省略 kill 管理后台中的任务kill %jobnumber -1 reload-9 立刻强制删除-15(默认) 以正常的进程方式终止 脱机管理 atnohup ... & 命令输出会重定向到~/nohup.out中,再次使用nohup命令会提示; tmux tmux new -s your_session_namepython your.pyCtrl + B then D 会话分离,脚本继续在后台运行 进程管理 僵尸进程 进程已经终止但却无法被删除纸内存外ps S列是Z,CMD列是defunct 查看进程 ps 查看某个时间点的ps -l 只看自己当前bash的进程 ps aux 查看所有系统运行的进程 top 查看实时的进程运行情况top -u usernametop -p PID htoppstree 查看进程的相关性 进程的管理 kill -signal PID 进程的执行顺序 Priority值和Nice值 priority(PRI) 内核动态调整,用户无法直接调整,PRI值越小,优先级越高 Nice值 PRI(new)= PRI(old)+ nicenice 开始执行进程就立即给一个特定的nice值nice -n [number] cmd renice 调整某个已经存在的PID的nice值renice [number] PID nice值的范围是-20~19,一般用户的范围是0~19,确只能调大; 查看系统资源信息 free 查看内存使用情况 uname 查看系统与内核的相关信息uname -a 显示当前系统的所有信息 uptime 查看系统启动时间和任务负载 netstat 追踪网络或者socket文件 dmseg 分析内核产生的信息 vmstat 检测系统资源变化 cat /etc/issue 显示的是发行版本信息 cat /proc/cpuinfo 查看cpu信息 top -d 2 查看CPU占用 查看系统CPU详细信息 lscpu 查看软连接 ld -l 软件管理 安装包安装:rpm和dpkg .rpm和.deb rpm CentOS rpm -i xxx.rpm deb ubuntu dpkg -i xxx.deb rpm (CentOS) rpm -qarpm -e dpkg (ubuntu) dpkg -l 查看安装列表 dpkg -r 删除软件 软件管家 yum (CentOS) searchinstallerase apt-get (Ubuntu) searchinstallpurge apt 几个旧的apt-xx命令的集成 配置下载的服务器 /etc/yum.repos.d/CentOS-Base.repo/etc/apt/sources.list tarball文件安装 tarball文件,就是软件的源码打包压缩之后的安装包;下载压缩包直接解压,配置环境变量,自行安装 文件下载 wget (World Wide Wed + Get):文件下载命令 支持的协议 HTTP, HTTPS, FTP 例: wget www.baidu.com ## 示例: 下载百度首页 常用选项 -d(调试模式) -d参数能够打印出wget运行时的调试信息:如HTTP报文头等 -O: 指定本地文件名 wget www.sina.com -O sina.html表示将www.sina.com 的内容下载到sina.html。 -b: 后台运行 压缩解压 zip zip -runzip tar tar -zcvftar -xzvf 程序的存放(命令安装) windows 程序的所有文件存在一个文件夹下 Linux /usr/bin or /usr/bins 主执行文件 /var 库文件 /etc 配置文件