当前位置: 首页 > news >正文

网站怎么制作成二维码吉林省干部网络培训学院官网

网站怎么制作成二维码,吉林省干部网络培训学院官网,网站怎么建设微信支付宝支付功能,购物网站设计的目的目录 操作系统篇 1 Linux中查看进程运行状态的指令、查看内存使用情况的指令、 tar解压文件的参数。 2 文件权限怎么修改 3 说说常用的Linux命令 4 说说如何以root权限运行某个程序。 5 说说软链接和硬链接的区别。 6 说说静态库和动态库怎么制作及如何使用#xff0c;区…目录 操作系统篇 1 Linux中查看进程运行状态的指令、查看内存使用情况的指令、 tar解压文件的参数。 2 文件权限怎么修改 3 说说常用的Linux命令 4 说说如何以root权限运行某个程序。 5 说说软链接和硬链接的区别。 6 说说静态库和动态库怎么制作及如何使用区别是什么。 7 简述GDB常见的调试命令什么是条件断点多进程下如何调试。 8 说说什么是大端小端如何判断大端小端 9 说说进程调度算法有哪些 10 简述操作系统如何申请以及管理内存的 11 简述Linux系统态与用户态什么时候会进入系统态 12 简述LRU算法及其实现方式。 13 一个线程占多大内存 14 什么是页表为什么要有 15 简述操作系统中的缺页中断。 16 说说虚拟内存分布什么时候会由用户态陷入内核态 17 简述一下虚拟内存和物理内存为什么要用虚拟内存好处是什么 18 虚拟地址到物理地址怎么映射的 19 说说堆栈溢出是什么会怎么样 20 简述操作系统中malloc的实现原理 22 32位系统能访问4GB以上的内存吗 23 请你说说并发和并行 24 说说进程、线程、协程是什么区别是什么 25 请你说说Linux的fork的作用 26 请你说说什么是孤儿进程什么是僵尸进程如何解决僵尸进程 28 说说进程通信的方式有哪些 29 说说进程同步的方式 30 说说Linux进程调度算法及策略有哪些 31 说说进程有多少种状态 33 简述mmap的原理和使用场景 34 互斥量能不能在进程中使用 35 协程是轻量级线程轻量级表现在哪里 36 说说常见信号有哪些表示什么含义 37 说说线程间通信的方式有哪些 41 单核机器上写多线程程序是否要考虑加锁为什么 42 说说多线程和多进程的不同 43 简述互斥锁的机制互斥锁与读写的区别 44 说说什么是信号量有什么作用 46 简述自旋锁和互斥锁的使用场景 48 多线程和单线程有什么区别多线程编程要注意什么多线程加锁 49 说说sleep和wait的区别 51 进程和线程相比为什么慢 52 简述Linux零拷贝的原理 操作系统篇 1 Linux中查看进程运行状态的指令、查看内存使用情况的指令、 tar解压文件的参数。 参考回答 1. 查看进程运行状态的指令 ps 命令。 “ ps -aux | grep PID ” 用来查看某 PID 进程状态 2. 查看内存使用情况的指令 free 命令。 “ free -m ” 命令查看内存使用情况。 3. tar 解压文件的参数 五个命令中必选一个 - c : 建立压缩档案 - x 解压 - t 查看内容 - r 向压缩归档文件末尾追加文件 - u 更新原压缩包中的文件 这几个参数是可选的 - z 有 gzip 属性的 - j 有 bz2 属性的 - Z 有 compress 属性的 - v 显示所有过程 - O 将文件解开到标准输出 答案解析 //ps 使用示例 // 显示当前所有进程 ps - A // 与 grep 联用查找某进程 ps - aux | grep apache // 查看进程运行状态、查看内存使用情况的指令均可使用 top 指令。 top 2 文件权限怎么修改 参考回答 Linux 文件的基本权限就有九个分别是 owner/group/others 三种身份各有自己的 read/write/execute 权限 修改权限指令 chmod 答案解析 举例文件的权限字符为 -rwxrwxrwx 时这九个权限是三个三个一组。其中我们可以使用数字来代表各个权限。 各权限的分数对照如下 每种身份 (owner/group/others) 各自的三个权限 (r/w/x) 分数是需要累加的 例如当权限为 [-rwxrwx---] 则分数是 owner rwx 421 7 group rwx 421 7 others --- 000 0 所以我们设定权限的变更时该文件的权限数字就是 770 变更权限的指令 chmod 的语法是这样的   [ rootwww ~ ] # chmod [ - R ] xyz 文件或目录 选项与参数 xyz : 就是刚刚提到的数字类型的权限属性为 rwx 属性数值的相加。 - R : 进行递归 ( recursive ) 的持续变更亦即连同次目录下的所有文件都会变更 # chmod 770 douya.c // 即修改 douya.c 文件的权限为 770 3 说说常用的Linux命令 参考回答 1. cd 命令用于切换当前目录 2. ls 命令查看当前文件与目录 3. grep 命令该命令常用于分析一行的信息若当中有我们所需要的信息就将该行显示出来该命令通常与管道命令一起使用用于对一些命令的输出进行筛选加工。 4. cp 命令复制命令 5. mv 命令移动文件或文件夹命令 6. rm 命令删除文件或文件夹命令 7. ps 命令查看进程情况 8. kill 命令向进程发送终止信号 9. tar 命令对文件进行打包调用 gzip 或 bzip 对文件进行压缩或解压 10. cat 命令查看文件内容与 less 、 more 功能相似 11. top 命令可以查看操作系统的信息如进程、 CPU 占用率、内存信息等 12. pwd 命令命令用于显示工作目录。 4 说说如何以root权限运行某个程序。 参考回答 sudo chown root app 文件名 sudo chmod u s app 文件名 输入上面两条指令后即可 5 说说软链接和硬链接的区别。 参考回答 1. 定义不同 软链接又叫符号链接这个文件包含了另一个文件的路径名。可以是任意文件或目录可以链接不 同文件系统的文件。 硬链接就是一个文件的一个或多个文件名。把文件名和计算机文件系统使用的节点号链接起来。因 此我们可以用多个文件名与同一个文件进行链接这些文件名可以在同一目录或不同目录。 2. 限制不同 硬链接只能对已存在的文件进行创建不能交叉文件系统进行硬链接的创建 软链接可对不存在的文件或目录创建软链接可交叉文件系统 3. 创建方式不同 硬链接不能对目录进行创建只可对文件创建 软链接可对文件或目录创建 4. 影响不同 删除一个硬链接文件并不影响其他有相同 inode 号的文件。 删除软链接并不影响被指向的文件但若被指向的原文件被删除则相关软连接被称为死链接即 dangling link 若被指向路径文件被重新创建死链接可恢复为正常的软链接 6 说说静态库和动态库怎么制作及如何使用区别是什么。 静态库的制作          gcc hello.c -c //这样就生成hello.o目标文件 ar rcs libhello.a hello.o//生成libhello.a静态库 静态库的使用 gcc main . c - lhello - o staticLibrary //main.c 和 hello 静态库链接生成 staticLibrary 执行文 件 /* main.c 是指 main 主函数 -lhello 是我们生成的 .a 文件砍头去尾 lib 不要 .a 也不要前面加 -l -L 是指告诉 gcc 编译器先从 -L 指定的路径去找静态库默认是从 /usr/lib/ 或者 /usr/local/lib/ 去找。 ./ 是指当前路径的意思 staticLibrary 是最后想生成的文件名这里可随意起名字 */ 动态库的制作 gcc - shared - fpic hello . c - o libhello . so - shared 指定生成动态库 - fpic fPIC 选项作用于编译阶段在生成目标文件时就得使用该选项以生成位置无关的代码。 动态库的使用 gcc main . c - lhello - L . / - o dynamicDepot /* main.c 是指 main 主函数 -lhello 是我们生成的 .so 文件砍头去尾 lib 不要 .so 也不要前面加 -l -L 是指告诉 gcc 编译器先从 -L 指定的路径去找静态库默认是从 /usr/lib/ 或者 /usr/local/lib/ 去找。 ./ 是指当前路径的意思 dynamicDepot 是最后想生成的文件名这里可随意起名字 */ 区别 1. 静态库代码装载的速度快执行速度略比动态库快。 2. 动态库更加节省内存可执行文件体积比静态库小很多。 3. 静态库是在编译时加载动态库是在运行时加载。 4. 生成的静态链接库 Windows 下以 .lib 为后缀 Linux 下以 .a 为后缀。生成的动态链接库 Windows下以.dll 为后缀 Linux 下以 .so 为后缀。 7 简述GDB常见的调试命令什么是条件断点多进程下如何调试。 参考回答 GDB 调试 gdb 调试的是可执行文件在 gcc 编译时加入 -g 告诉 gcc 在编译时加入调试信息这样 gdb才能调试这个被编译的文件 gcc -g tesst.c -o test。 GDB 命令格式 1. quit 退出 gdb 结束调试 2. list 查看程序源代码 list 5 10 显示 5 到 10 行的代码 list test.c:5, 10: 显示源文件 5 到 10 行的代码在调试多个文件时使用 list get_sum: 显示 get_sum 函数周围的代码 list test,c get_sum: 显示源文件 get_sum 函数周围的代码在调试多个文件时使用 3. reverse-search 字符串用来从当前行向前查找第一个匹配的字符串 4. run 程序开始执行 5. help list/all 查看帮助信息 6. break 设置断点 break 7 在第七行设置断点 break get_sum 以函数名设置断点 break 行号或者函数名 if 条件以条件表达式设置断点 7. watch 条件表达式条件表达式发生改变时程序就会停下来 8. next 继续执行下一条语句 会把函数当作一条语句执行 9. step 继续执行下一条语句会跟踪进入函数一次一条的执行函数内的代码 条件断点 break if 条件 以条件表达式设置断点 多进程下如何调试 用 set follow-fork-mode child 调试子进程 或者 set follow-fork-mode parent 调试父进程 8 说说什么是大端小端如何判断大端小端 参考回答 小端模式 低 的有效字节存储在 低的 存储器地址。小端一般为主机字节序常用的 X86 结构是小端模式。很多的ARM DSP 都为小端模式。 大端模式 高 的有效字节存储在 低的 存储器地址。大端为网络字节序 KEIL C51 则为大端模式。 有些 ARM 处理器还可以由硬件来选择是大端模式还是小端模式。 如何判断我们可以根据 联合体 来判断系统是大端还是小端。因为联合体变量总是从 低地址 存储 。 int fun1(){ union test{ char c; int i; }; test t; t.i 1; //如果是大端则t.c为0x00则t.c ! 1反之是小端 return (t.c 1); } 答案解析 1. 在进行网络通信时是否需要进行字节序转换 相同字节序的平台在进行网络通信时可以不进行字节序转换但是 跨平台进行网络数据通信时必须 进行字节序转换。 原因如下网络协议规定接收到得第一个字节是高字节存放到低地址所以发送时会首先去低地 址取数据的高字节。小端模式的多字节数据在存放时低地址存放的是低字节而被发送方网络协 议函数发送时会首先去低地址取数据想要取高字节真正取得是低字节接收方网络协议函数 接收时会将接收到的第一个字节存放到低地址想要接收高字节真正接收的是低字节所以最 后双方都正确的收发了数据。而相同平台进行通信时如果双方都进行转换最后虽然能够正确收发 数据但是所做的转换是没有意义的造成资源的浪费。而不同平台进行通信时必须进行转换 不 转换会造成错误的收发数据 字节序转换函数会根据当前平台的存储模式做出相应正确的转换如 果当前平台是大端则直接返回不进行转换如果当前平台是小端会将接收到得网络字节序进行 转换。 2. 网络字节序 网络上传输的数据都是 字节流 , 对于一个多字节数值 , 在进行网络传输的时候 , 先传递哪个字节 ? 也就是 说 , 当接收端收到第一个字节的时候 , 它将这个字节作为高位字节还是低位字节处理 , 是一个比较有意 义的问题 ; UDP/TCP/IP 协议规定 : 把接收到的第一个字节当作高位字节看待 , 这就要求 发送端发送的 第一个字节是高位字节 ; 而在发送端发送数据时 , 发送的第一个字节是该数值在内存中的起始地址处 对应的那个字节 , 也就是说 , 该数值在内存中的起始地址处对应的那个字节就是要发送的第一个高位 字节 ( 即 : 高位字节存放在低地址处 ); 由此可见 , 多字节数值在发送之前 , 在内存中因该是以大端法存放 的 ; 所以说 , 网络字节序是大端字节序 ; 比如 , 我们经过网络发送整型数值 0x12345678 时 , 在 80X86 平 台中 , 它是以小端发存放的 , 在发送之前需要使用系统提供的字节序转换函数 htonl() 将其转换成大端 法存放的数值 ; 9 说说进程调度算法有哪些 参考回答 1. 先来先服务调度算法 2. 短作业 ( 进程 ) 优先调度算法 3. 高优先级优先调度算法 4. 时间片轮转法 5. 多级反馈队列调度算法 答案解析 1. 先来先服务调度算法每次调度都是从后备作业进程队列中选择一个或多个 最先进入该队列的 作业 进程将它们调入内存为它们分配资源、创建进程然后放入就绪队列。 2. 短作业 ( 进程 ) 优先调度算法短作业优先 (SJF) 的调度算法是从后备队列中选择一个或若干个 估计运 行时间最短的作业进程 将它们调入内存运行。 3. 高优先级优先调度算法当把该算法用于作业调度时系统将从后备队列中选择若干个 优先权最高的作业装入内存。当用于进程调度时该算法是把处理机分配给就绪队列中优先权最高的进程 4. 时间片轮转法每次调度时 把 CPU 分配给队首进程并令其执行一个时间片。时间片的大小从几 ms 到几百 ms 。当执行的时间片用完时由一个计时器发出时钟中断请求调度程序便据此信号来 停止该进程的执行并将它送往就绪队列的末尾 然后再把处理机分配给就绪队列中新的队首进程同时也让它执行一个时间片。 5. 多级反馈队列调度算法综合前面多种调度算法。 在这些调度算法中有抢占式和非抢占式的区别。 1. 非抢占式优先权算法 在这种方式下系统一旦把处理机分配给就绪队列中优先权最高的进程后该进程便一直执行下 去直至完成或因发生某事件使该进程放弃处理机时系统方可再将处理机重新分配给另一优先 权最高的进程。这种调度算法主要用于批处理系统中也可用于某些对实时性要求不严的实时系统 中。 2. 抢占式优先权调度算法 在这种方式下系统同样是把处理机分配给优先权最高的进程使之执行。但在其执行期间只要 又出现了另一个其优先权更高的进程进程调度程序就立即停止当前进程 ( 原优先权最高的进程 ) 的 执行重新将处理机分配给新到的优先权最高的进程。因此在采用这种调度算法时是每当系统 中出现一个新的就绪进程 i 时就将其优先权 Pi 与正在执行的进程 j 的优先权 Pj 进行比较。如果 Pi ≤ Pj 原进程 Pj 便继续执行但如果是 PiPj 则立即停止 Pj 的执行做进程切换使 i 进程投入执 行。显然这种抢占式的优先权调度算法能更好地满足紧迫作业的要求故而常用于要求比较严格 的实时系统中以及对性能要求较高的批处理和分时系统中。 区别 非抢占式 Nonpreemptive 让进程运行直到结束或阻塞的调度方式容易实现适合专用系统 不适合通用系统。抢占式Preemptive 允许将逻辑上可继续运行的在运行过程暂停的调度方式可防止单一进程长时间 独占 CPU 系统开销大 降低途径硬件实现进程切换或扩充主存以贮存大部分程序。 10 简述操作系统如何申请以及管理内存的 参考回答 操作系统如何管理内存 1. 物理内存 物理内存有四个层次分别是寄存器、高速缓存、主存、磁盘。 寄存器速度最快、量少、价格贵。 高速缓存次之。 主存再次之。 磁盘速度最慢、量多、价格便宜。 操作系统会对物理内存进行管理有一个部分称为 内存管理器 (memory manager) 它的主要工 作是有效的管理内存记录哪些内存是正在使用的在进程需要时分配内存以及在进程完成时回收 内存。 2. 虚拟内存 操作系统为每一个进程分配一个独立的地址空间 但是虚拟内存。 虚拟内存与物理内存存在映射关系通过页表寻址完成虚拟地址和物理地址的转换 。          操作系统如何申请内存 从操作系统角度来看进程分配内存有两种方式分别由两个系统调用完成 *brk 和 mmap。 11 简述Linux系统态与用户态什么时候会进入系统态 1. 内核态与用户态 内核态 系统态与 用户态 是操作系统的两种运行级别。内核态拥有最高权限可以访问所有系统指令用户态则只能访问一部分指令。 2. 什么时候进入内核态 共有三种方式 a 、 系统调用 。 b 、 异常 。 c 、 设备中断 。 其中系统调用是主动的另外两种是被动的。 3. 为什么区分内核态与用户态 在 CPU 的所有指令中 有一些指令是非常危险的如果错用将导致整个系统崩溃。 比如清内存、设置时钟等。所以区分内核态与用户态主要是出于安全的考虑。 12 简述LRU算法及其实现方式。 参考回答 1. LRU 算法 LRU 算法用于 缓存淘汰 。思路是 将缓存中最近最少使用的对象删除掉 2. 实现方式 利用 链表和 hashmap 。 当需要插入新的数据项的时候如果新数据项在链表中 存在 一般称为命中则 把该节点移到链 表头部 如果 不存在 则 新建一个节点放到链表头部 若 缓存满了则把链表最后一个节点删除 即可 。 在访问数据的时候如果数据项在链表中存在则把该节点移到链表头部否则返回 -1 。这样一来在链表尾部的节点就是最近最久未访问的数据项。 答案解析 class LRUCache { listpairint, int cache;//创建双向链表 unordered_mapint, listpairint, int::iterator map;//创建哈希表 int cap; public: LRUCache(int capacity) { cap capacity; } int get(int key) { if (map.count(key) 0){ auto temp *map[key]; cache.erase(map[key]); map.erase(key); cache.push_front(temp); map[key] cache.begin();//映射头部 return temp.second; } return -1; } void put(int key, int value) { if (map.count(key) 0){ cache.erase(map[key]); map.erase(key); } else if (cap cache.size()){ auto temp cache.back(); map.erase(temp.first); cache.pop_back(); } cache.push_front(pairint, int(key, value)); map[key] cache.begin();//映射头部 } }; /** * Your LRUCache object will be instantiated and called as such: * LRUCache* obj new LRUCache(capacity); * int param_1 obj-get(key); * obj-put(key,value); */ 13 一个线程占多大内存 参考回答 一个 linux 的线程大概占 8M 内存 。 linux 的栈是通过缺页来分配内存的不是所有栈地址空间都分配了内存。因此 8M 是最大消耗实际的内存消耗只会略大于实际需要的内存( 内部损耗每个在 4k 以内 ) 。          14 什么是页表为什么要有 参考回答 页表是虚拟内存的概念。 操作系统虚拟内存到物理内存的映射表就被称为页表。 原因 不可能每一个虚拟内存的 Byte 都对应到物理内存的地址。这张表将大得真正的物理地址也放不下于是操作系统引入了页Page 的概念。进行分页这样可以 减小虚拟内存页对应物理内存页的映射表大小 。 答案解析 如果将每一个虚拟内存的 Byte 都对应到物理内存的地址每个条目最少需要 8 字节 32 位虚拟地址 -32位物理地址在 4G 内存的情况下就需要 32GB 的空间来存放对照表那么这张表就大得真正的物理地址也放不下了于是操作系统引入了页Page 的概念。 在系统启动时操作系统将整个物理内存以 4K 为单位划分为各个页。之后进行内存分配时都以页为单位那么虚拟内存页对应物理内存页的映射表就大大减小了4G 内存只需要 8M 的映射表即可一些进程没有使用到的虚拟内存也并不需要保存映射关系而且Linux 还为大内存设计了多级页表可以进一页减少了内存消耗。 15 简述操作系统中的缺页中断。 参考回答 1. 缺页异常 malloc 和 mmap 函数在分配内存时只是建立了进程虚拟地址空间并没有分配虚拟内存对应的物理内存。当进程访问这些没有建立映射关系的虚拟内存时处理器自动触发一个缺页异 常引发缺页中断 。 2. 缺页中断 缺页异常后将产生一个缺页中断此时操作系统会根据页表中的 外存地址 在外存中找到所缺的一页将其调入内存 。 答案解析 两者区别。 缺页中断与一般中断一样需要经历四个步骤 保护 CPU 现场、分析中断原因、转入缺页中断处理程序、恢复CPU 现场继续执行。 缺页中断与一般中断区别 1在指令执行期间产生和处理缺页中断信号 2一条指令在执行期间可能产生多次缺页中断 3缺页中断返回的是执行产生中断的一条指令而一般中断返回的是执行下一条指令。 16 说说虚拟内存分布什么时候会由用户态陷入内核态 参考回答 1. 虚拟内存分布 用户空间 1 代码段 .text 存放程序执行代码的一块内存区域。只读代码段的头部还会包含一些只读的常数变量。 2 数据段 .data 存放程序中 已初始化 的 全局变量和静态变量 的一块内存区域。 3 BSS 段 .bss 存放程序中 未初始化的全局变量和静态变量的一块内存区域。 4 可执行程序在运行时又会多出两个区域 堆区和栈区 。         堆区动态申请内存用。堆从低地址向高地址增长。         栈区存储局部变量、函数参数值。栈从高地址向低地址增长。是一块连续的空间。 5最后还有一个 文件映射区 位于堆和栈之间。         内核空间 DMA 区、常规区、高位区。 1. 什么时候进入内核态 共有三种方式 a 、 系统调用 。 b 、 异常 。 c 、 设备中断 。其中系统调用是主动的另外两种是被动的。 17 简述一下虚拟内存和物理内存为什么要用虚拟内存好处是什么 参考回答 1. 物理内存 物理内存有四个层次分别是寄存器、高速缓存、主存、磁盘。 寄存器速度最快、量少、价格贵。 高速缓存次之。 主存再次之 磁盘速度最慢、量多、价格便宜。 操作系统会对物理内存进行管理有一个部分称为 内存管理器 (memory manager) 它的主要工 作是有效的管理内存记录哪些内存是正在使用的在进程需要时分配内存以及在进程完成时回收 内存。 2. 虚拟内存 操作系统为 每一个进程分配一个独立的地址空间 但是虚拟内存。虚拟内存与物理内存存在映射关系通过页表寻址完成虚拟地址和物理地址的转换 。 3. 为什么要用虚拟内存 因为早期的内存分配方法存在以下问题 1 进程地址空间不隔离。会导致数据被随意修改 。 2 内存使用效率低。 3 程序运行的地址不确定。操作系统随机为进程分配内存空间 所以程序运行的地址是不确定 的。 4. 使用虚拟内存的 好处 1 扩大地址空间 。每个进程独占一个 4G 空间虽然 真实物理内存没那么多 。 2 内存保护防止不同进程对物理内存的争夺和践踏可以对特定内存地址提供写保护防止 恶意篡改。 3可以 实现内存共享方便进程通信 。 4可以 避免内存碎片虽然物理内存可能不连续但映射到虚拟内存上可以连续 。 5. 使用虚拟内存的 缺点 1虚拟内存 需要额外构建数据结构占用空间 。 2虚拟地址到物理地址的转换 增加了执行时间 。 3 页面换入换出耗时 。 4一页如果只有一部分数据浪费内存。 18 虚拟地址到物理地址怎么映射的 参考回答 操作系统为每一个进程维护了一个从虚拟地址到物理地址的映射关系的数据结构叫页表。 页表中的每一项都记录了这个页的基地址。 三级页表转换方法两步 1. 逻辑地址转线性地址 段起始地址 段内偏移地址 线性地址 2. 线性地址转物理地址 1每一个 32 位的线性地址被划分为三部分页目录索引 DIRECTORY 10 位、页表索引 TABLE 10 位、页内偏移 OFFSET 12 位 2从 cr3 中取出进程的页目录地址操作系统调用进程时这个地址被装入寄存器中 页目录地址 页目录索引 页表地址 页表地址 页表索引 页地址 页地址 页内偏移 物理地址 按照以上两步法就完成了一个三级页表从虚拟地址到物理地址的转换。 19 说说堆栈溢出是什么会怎么样 参考回答 堆栈溢出就是不顾堆栈中分配的局部数据块大小 向该数据块写入了过多的数据导致数据越界 。常指调用堆栈溢出本质上一种数据结构的满溢情况。堆栈溢出可以理解为两个方面堆溢出和栈溢出。 1. 堆溢出比如不断的 new 一个对象一直创建新的对象而不进行释放最终导致内存不足。将会报错OutOfMemory Error 。 2. 栈溢出一次函数调用中栈中将被依次压入参数返回地址等而方法如果递归比较深或进去死循环就会导致栈溢出。将会报错StackOverflow Error 。 20 简述操作系统中malloc的实现原理 参考回答 malloc 底层实现 当开辟的空间小于 128K 时调用 brk 函数当开辟的空间大于 128K 时调用mmap。 malloc 采用的是内存池的管理方式以减少内存碎片。先申请大块内存作为堆区然后将堆区分为多个内存块。当用户申请内存时直接从堆区分配一块合适的空闲快。采用隐式链表将所有空闲块每一个空闲块记录了一个未分配的、连续的内存地址。 21 说说进程空间从高位到低位都有些什么 参考回答 如上图 从高地址到低地址一个程序由命令行参数和环境变量、栈、文件映射区、堆、 BSS 段、数据 段、代码段组成。 1. 命令行参数和环境变量 2. 栈区 存储局部变量、函数参数值。栈从高地址向低地址增长。是一块连续的空间。 3. 文件映射区 位于堆和栈之间。 4. 堆区 动态申请内存用。堆从低地址向高地址增长。 5. BSS 段 存放程序中未初始化的全局变量和静态变量的一块内存区域。 6. 数据段 存放程序中已初始化的全局变量和静态变量的一块内存区域。 7. 代码段 存放程序执行代码的一块内存区域。只读代码段的头部还会包含一些只读的常数变量。 22 32位系统能访问4GB以上的内存吗 参考回答 正常情况下是不可以的 。原因是计算机使用二进制每位数只有 0 或 1 两个状态 32 位正好是 2 的 32 次方正好是4G 所以大于 4G 就没办法表示了而在 32 位的系统中因其它原因还需要占用一部分空间所以内存只能识别3G 多。要使用 4G 以上就只能换 64 位的操作系统了。但是使用PAE 技术 就可以实现 32 位系统能访问 4GB 以上的内存。 答案解析 Physical Address Extension PAE 技术最初是 为了弥补 32 位地址在 PC 服务器应用上的不足而推出的 。我们知道传统的 IA32 架构只有 32 位地址总线只能让系统容纳不超过 4GB 的内存这么大的内存对于普通的桌面应用应该说是足够用了。可是对于服务器应用来说还是显得不足因为服务器上可能承载了很多同时运行的应用。 PAE 技术将地址扩展到了 36 位这样系统就能够容纳 2^3664GB的内存。 23 请你说说并发和并行 参考回答 1. 并发 对于单个 CPU 在一个时刻只有一个进程在运行但是线程的切换时间则减少到纳秒数量级多个任务不停来回快速切换。 2. 并行 对于多个 CPU 多个进程同时运行。 3. 区别 。通俗来讲它们虽然都说是 多个进程同时运行 但是它们的 同时 不是一个概念。并行 的 同时 是同一时刻可以多个任务在运行 ( 处于 running) 并发的 同时 是经过不同线程快速切换 使得看上去多个任务同时都在运行的现象。 24 说说进程、线程、协程是什么区别是什么 参考回答 1. 进程 程序是指令、数据及其组织形式的描述而进程则是程序的运行实例包括程序计数器、寄存器和变量的当前值。 2. 线程 微进程一个进程里更小粒度的执行单元。一个进程里包含多个线程并发执行任务。 3. 协程 协程是微线程在子程序内部执行可在子程序内部中断转而执行别的子程序在适当的时候再返回来接着执行。 区别 1. 线程与进程的区别 1一个线程从属于一个进程一个进程可以包含多个线程。 2 一个线程挂掉对应的进程挂掉 一个进程挂掉不会影响其他进程。 3 进程是系统资源调度的最小单位 线程 CPU 调度的最小单位 。 4进程系统开销显著大于线程开销线程需要的系统资源更少。 5 进程在执行时拥有独立的内存单元多个线程共享进程的内存 如代码段、数据段、扩展 段但每个线程拥有自己的栈段和寄存器组。 6 进程切换时需要刷新 TLB 并获取新的地址空间然后切换硬件上下文和内核栈线程切换时只需要切换硬件上下文和内核栈。 7通信方式不一样。 8进程适应于多核、多机分布线程适用于多核 2. 线程与协程的区别 1 协程执行效率极高 。协程 直接操作栈基本没有内核切换的开销 所以上下文的切换非常快 切换开销比线程更小。 2 协程不需要多线程的锁机制因为多个协程从属于一个线程不存在同时写变量冲突效率 比线程高。 3一个线程可以有多个协程。 25 请你说说Linux的fork的作用 参考回答 fork 函数用来创建一个子进程。对于父进程 fork() 函数返回新创建的子进程的 PID 。对于子进程 fork() 函数调用成功会返回0 。如果创建出错 fork() 函数返回 -1 。 答案解析 fork() 函数其原型如下 #include unistd.h pid_t fork ( void ); fork() 函数不需要参数返回值是一个进程标识符 PID 。返回值有以下三种情况 1 对于父进程 fork() 函数返回新创建的子进程的 PID 。 2 对于子进程 fork() 函数调用成功会返回 0 。 3 如果创建出错 fork() 函数返回 -1 。 fork() 函数创建一个新进程后会为这个新 进程分配进程空间将父进程的进程空间中的内容复制到子进程的进程空间中 包括父进程的数据段和堆栈段并且和父进程共享代码段。这时候子进程和父进程一模一样都接受系统的调度。因为两个进程都停留在fork() 函数中最后 fork() 函数会返回两次一次在父进程中返回一次在子进程中返回两次返回的值不一样如上面的三种情况。 26 请你说说什么是孤儿进程什么是僵尸进程如何解决僵尸进程 参考回答 1. 孤儿进程 是指一个父进程退出后而它的一个或多个子进程还在运行那么这些子进程将成为孤 儿进程。孤儿进程将被 init 进程进程号为 1 所收养 并且由 init 进程对它们完整状态收集工作。 2. 僵尸进程 是指一个进程使用 fork 函数创建子进程如果子进程退出而父进程并没有调用 wait() 或者waitpid() 系统调用取得子进程的终止状态 那么 子进程的进程描述符仍然保存在系统中占用系统资源 这种进程称为僵尸进程。 3. 如何解决僵尸进程 1一般为了防止产生僵尸进程在 fork 子进程之后我们都要及时使用 wait 系统调用 同时 当子进程退出的时候内核都会给父进程一个 SIGCHLD 信号所以我们可以建立一个 捕获SIGCHLD信号的信号处理函数在函数体中调用 wait 或 waitpid 就可以清理退出的子进程以 达到防止僵尸进程的目的。 2 使用 kill 命令 。 打开终端并输入下面命令 : ps aux | grep Z 会列出进程表中所有僵尸进程的详细内容。 然后输入命令 kill - s SIGCHLD pid ( 父进程 pid ) 27 请你说说什么是守护进程如何实现 参考回答 1. 守护进程 守护进程是 运行在后台的一种生存期长的特殊进程。它独立于控制终端处理一些系统级别任务。 2. 如何实现 1创建子进程终止父进程。方法是调用 fork() 产生一个子进程然后使父进程退出。 2调用 setsid() 创建一个新会话。 3 将当前目录更改为根目录 。使用 fork() 创建的子进程也继承了父进程的当前工作目录。 4重设文件权限掩码。文件权限掩码是指屏蔽掉文件权限中的对应位。 5关闭不再需要的文件描述符。子进程从父进程继承打开的文件描述符。 实现代码如下 #include stdio.h #include stdlib.h #include string.h #include fcntl.h #include unistd.h #include sys/wait.h #include sys/types.h #include sys/stat.h #define MAXFILE 65535 int main(){ //第一步:创建进程 int pid fork(); if (pid 0) exit(0);//结束父进程 else if (pid 0){ printf(fork error!\n); exit(1);//fork失败退出 } //第二步:子进程成为新的会话组长和进程组长,并与控制终端分离 setsid(); //第三步:改变工作目录到 chdir(/); //第四步:重设文件创建掩模 umask(0); //第五步:关闭打开的文件描述符 for (int i0; iMAXFILE; i) close(i); sleep(2); } return 0; } 28 说说进程通信的方式有哪些 参考回答 进程间通信主要包括 管道 、 系统 IPC 包括消息队列、信号量、信号、共享内存、 套接字 socket 。 1. 管道 包括无名管道和命名管道无名管道半双工只能用于具有亲缘关系的进程直接的通信父子进程或者兄弟进程可以看作一种特殊的文件命名管道可以允许无亲缘关系进程间的通信。 2. 系统 IPC 消息队列 消息的链接表放在内核中。消息队列独立于发送与接收进程进程终止时消息队列 及其内容并不会被删除消息队列可以实现消息的随机查询可以按照消息的类型读取。 信号量 semaphore 是一个计数器可以用来控制多个进程对共享资源的访问。信号量用于实现 进程间的互斥与同步。 信号 用于通知接收进程某个事件的发生。 内存共享 使多个进程访问同一块内存空间。 29 说说进程同步的方式 参考回答 1. 信号量 semaphore 是一个计数器可以用来控制多个进程对共享资源的访问。信号量用于实现 进程间的互斥与同步。P 操作 ( 递减操作 ) 可以用于阻塞一个进程 V 操作 ( 增加操作 ) 可以用于解除阻 塞一个进程。 2. 管道 一个进程通过调用管程的一个过程进入管程。在任何时候只能有一个进程在管程中执行 调用管程的任何其他进程都被阻塞以等待管程可用。 3. 消息队列 消息的链接表放在内核中。消息队列独立于发送与接收进程进程终止时消息队列及其内容并不会被删除消息队列可以实现消息的随机查询可以按照消息的类型读取。 30 说说Linux进程调度算法及策略有哪些 参考回答 1. 先来先服务调度算法 2. 短作业 ( 进程 ) 优先调度算法 3. 高优先级优先调度算法 4. 时间片轮转法 5. 多级反馈队列调度算法 答案解析 1. 先来先服务调度算法每次调度都是从后备作业进程队列中选择一个或多个最先进入该队列的 作业进程将它们调入内存为它们分配资源、创建进程然后放入就绪队列。 2. 短作业 ( 进程 ) 优先调度算法短作业优先 (SJF) 的调度算法是从后备队列中选择一个或若干个估计运 行时间最短的作业进程将它们调入内存运行。 3. 高优先级优先调度算法当把该算法用于作业调度时系统将从后备队列中选择若干个优先权最高 的作业装入内存。当用于进程调度时该算法是把处理机分配给就绪队列中优先权最高的进程 4. 时间片轮转法每次调度时把 CPU 分配给队首进程并令其执行一个时间片。时间片的大小从几 ms 到几百 ms 。当执行的时间片用完时由一个计时器发出时钟中断请求调度程序便据此信号来 停止该进程的执行并将它送往就绪队列的末尾然后再把处理机分配给就绪队列中新的队首进 程同时也让它执行一个时间片。 5. 多级反馈队列调度算法综合前面多种调度算法。 在这些调度算法中有抢占式和非抢占式的区别。 1. 非抢占式优先权算法 在这种方式下系统一旦把处理机分配给就绪队列中优先权最高的进程后该进程便一直执行下 去直至完成或因发生某事件使该进程放弃处理机时系统方可再将处理机重新分配给另一优先 权最高的进程。这种调度算法主要用于批处理系统中也可用于某些对实时性要求不严的实时系统 中。 2. 抢占式优先权调度算法 在这种方式下系统同样是把处理机分配给优先权最高的进程使之执行。但在其执行期间只要 又出现了另一个其优先权更高的进程进程调度程序就立即停止当前进程 ( 原优先权最高的进程 ) 的 执行重新将处理机分配给新到的优先权最高的进程。因此在采用这种调度算法时是每当系统 中出现一个新的就绪进程 i 时就将其优先权 Pi 与正在执行的进程 j 的优先权 Pj 进行比较。如果 Pi ≤ Pj 原进程 Pj 便继续执行但如果是 PiPj 则立即停止 Pj 的执行做进程切换使 i 进程投入执 行。显然这种抢占式的优先权调度算法能更好地满足紧迫作业的要求故而常用于要求比较严格 的实时系统中以及对性能要求较高的批处理和分时系统中。 非抢占式 Nonpreemptive 让进程运行直到结束或阻塞的调度方式容易实现适合专用系统不 适合通用系统。 抢占式Preemptive 允许将逻辑上可继续运行的在运行过程暂停的调度方式可防止单一进程长时间 独占CPU 系统开销大降低途径硬件实现进程切换或扩充主存以贮存大部分程序 31 说说进程有多少种状态 参考回答 进程有五种状态 创建、就绪、执行、阻塞、终止 。一个进程创建后被放入队列处于就绪状态等待 操作系统调度执行执行过程中可能切换到阻塞状态并发任务完成后进程销毁终止。 答案解析 创建状态 一个应用程序从系统上启动首先就是进入 创建状态 需要获取系统资源创建进程管理块 PCB Process Control Block 完成资源分配。 就绪状态 在 创建状态 完成之后进程已经准备好处于 就绪状态 但是还未获得处理器资源无法运行。 运行状态 获取处理器资源被系统调度 当具有时间片 开始进入 运行状态 。如果进程的时间片用完了就进入 就绪 状态 。 阻塞状态 在 运行状态 期间如果进行了阻塞的操作如耗时的 I/O 操作此时进程暂时无法操作就进入到了 阻塞状 态 在这些操作完成后就进入 就绪状态 。等待再次获取处理器资源被系统调度 当具有时间片 就进入 运行状态 。 终止状态 进程结束或者被系统终止进入 终止状态 相互转换如图 32 进程通信中的管道实现原理是什么 参考回答 操作系统在内核中开辟一块 缓冲区 称为 管道 用于通信。 管道 是一种两个进程间进行 单向通信 的机制。因为这种单向性管道又称为半双工管道所以其使用是有一定的局限性的。半双工是指数据只能由一个进程流向另一个进程一个管道负责读一个管道负责写如果是全双工通信需要建立两个管道。管道分为无名管道和命名管道无名管道只能用于具有亲缘关系的进程直接的通信父子进程或者兄弟进程可以看作一种特殊的文件管道本质是一种文件 命名管道可以允许无亲缘关系进程间的通信。 管道原型如下 include unistd . h int pipe ( int fd [ 2 ]); pipe() 函数创建的管道处于一个进程中间因此一个进程在由 pipe() 创建管道后一般再使用 fork() 建立一个子进程然后通过管道实现父子进程间的通信。管道两端可分别用描述字fd[0] 以及 fd[1] 来描述。注意管道的两端的任务是固定的即一端只能用于读由描述字fd[0] 表示称其为管道读端另 一端则只能用于写由描述字fd[1] 来表示称其为管道写端。如果试图从管道写端读取数据或者向管道读端写入数据都将发生错误。一般文件的 I/O 函数都可以用于管道如 close() 、 read() 、 write() 等。 具体步骤 如下 1. 父进程调用 pipe 开辟管道 , 得到两个文件描述符指向管道的两端。 2. 父进程调用 fork 创建子进程 , 那么子进程也有两个文件描述符指向同一管道。 3. 父进程关闭管道读端 , 子进程关闭管道写端。父进程可以往管道里写 , 子进程可以从管道里读 , 管道是 用环形队列实现的, 数据从写端流入从读端流出 , 这样就实现了进程间通信。 答案解析 给出实现的代码实现父子进程间的管道通信 #includeunistd.h #includestdio.h #includestdlib.h #includestring.h #define INPUT 0 #define OUTPUT 1 int main(){ //创建管道 int fd[2]; pipe(fd); //创建子进程 pid_t pid fork(); if (pid 0){ printf(fork error!\n); exit(-1); } else if (pid 0){//执行子进程 printf(Child process is starting...\n); //子进程向父进程写数据关闭管道的读端 close(fd[INPUT]); write(fd[OUTPUT], hello douya!, strlen(hello douya!)); exit(0); } else{//执行父进程 printf (Parent process is starting......\n); //父进程从管道读取子进程写的数据 关闭管道的写端 close(fd[OUTPUT]); char buf[255]; int output read(fd[INPUT], buf, sizeof(buf)); printf(%d bytes of data from child process: %s\n, output, buf); } return 0; } 33 简述mmap的原理和使用场景 参考回答 原理 mmap 是一种内存映射文件的方法 即将一个文件或者其它对象映射到进程的地址空间实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。实现这样的映射关系后进程就可以采用指针的方式读写操作这一段内存而系统会自动回写脏页面到对应的文件磁盘上即完成了对文件的操作而不必再调用read, write 等系统调用函数。相反内核空间对这段区域的修改也直接反映用户空间从而可以实现不同进程间的文件共享。如下图 使用场景 1. 对同一块区域频繁读写操作 2. 可用于实现用户空间和内核空间的高效交互 3. 可提供进程间共享内存及相互通信 4. 可实现高效的大规模数据传输。 34 互斥量能不能在进程中使用 参考回答 能 。 不同的进程之间 存在资源竞争或并发使用的问题 所以需要 互斥量 。 进程中也需要 互斥量 因为一个进程中可以包含多个线程线程与线程之间需要通过互斥的手段进行同步避免导致共享数据修改引起冲突。可以使用互斥锁 属于互斥量的一种。 35 协程是轻量级线程轻量级表现在哪里 参考回答 1. 协程调用跟切换比线程效率高 协程执行效率极高。协程不需要多线程的锁机制可以不加锁的访问全局变量所以上下文的切换非常快。 2. 协程占用内存少 执行协程只需要极少的栈内存大概是 4 5KB 而默认情况下线程栈的大小为1MB 。 3. 切换开销更少 协程直接操作栈基本没有内核切换的开销所以切换开销比线程少。 36 说说常见信号有哪些表示什么含义 参考回答 编号为1 ~ 31 的信号为传统 UNIX 支持的信号是不可靠信号 ( 非实时的 ) 。不可靠信号和可靠信号的区别在于前者不支持排队可能会造成信号丢失而后者不会。编号为1 ~ 31 的信号如下 而常见信号如下 其中最重要的就是 1、9、15、17这几个信号。 37 说说线程间通信的方式有哪些 参考回答 线程间的通信方式包括 临界区、互斥量、信号量、条件变量、读写锁 1. 临界区每个线程中访问临界资源的那段代码称为临界区 Critical Section 临界资源是一次仅允许一个线程使用的共享资源。每次只准许一个线程进入临界区进入后不允许其他线程进入。 不论是硬件临界资源还是软件临界资源多个线程必须互斥地对它进行访问。 2. 互斥量采用互斥对象机制只有拥有互斥对象的线程才可以访问。因为互斥对象只有一个所以可以保证公共资源不会被多个线程同时访问。 3. 信号量计数器允许多个线程同时访问同一个资源。 4. 条件变量通过条件变量通知操作的方式来保持多线程同步。 5. 读写锁读写锁与互斥量类似。但互斥量要么是锁住状态要么就是不加锁状态。读写锁一次只允许一个线程写但允许一次多个线程读这样效率就比互斥锁要高。 38 说说线程同步方式有哪些 参考回答 线程间的同步方式包括 互斥锁、信号量、条件变量、读写锁 1. 互斥锁 采用互斥对象机制只有拥有互斥对象的线程才可以访问。因为互斥对象只有一个所以可以保证公共资源不会被多个线程同时访问。 2. 信号量 计数器允许多个线程同时访问同一个资源。 3. 条件变量 通过条件变量通知操作的方式来保持多线程同步。 4. 读写锁 读写锁与互斥量类似。但互斥量要么是锁住状态要么就是不加锁状态。读写锁一次只允许一个线程写但允许一次多个线程读这样效率就比互斥锁要高。 39 说说什么是死锁产生的条件如何解决 参考回答 1. 死锁 : 是指多个进程在执行过程中 因争夺资源而造成了互相等待 。此时系统产生了死锁。比如两只羊过独木桥若两只羊互不相让争着过桥就产生死锁。 2. 产生的条件 死锁发生有 四个必要条件 1 互斥条件 进程对所分配到的资源不允许其他进程访问若其他进程访问只能等待直到 进程使用完成后释放该资源 2 请求保持条件 进程获得一定资源后又对其他资源发出请求但该资源被其他进程占有 此时请求阻塞而且该进程不会释放自己已经占有的资源 3 不可剥夺条件 进程已获得的资源只能自己释放不可剥夺 4 环路等待条件 若干进程之间形成一种头尾相接的循环等待资源关系。 3. 如何解决 1资源一次性分配从而解决请求保持的问题 2可剥夺资源当进程新的资源未得到满足时释放已有的资源 3资源有序分配资源按序号递增进程请求按递增请求释放则相反。 答案解析 举个例子比如如果此时有两个线程 T1 和 T2 它们分别占有 R1 和 R2 资源 此时 T1 请求 R2 资源的同时 T2 请求 R1 资源。 这个时候 T2 说你把 R1 给我我就给你 R2。 T1 说不行你要先给我 R2 我才能给你 R1 那么就这样死锁产生了。如下图 40 有了进程为什么还要有线程 参考回答 1. 原因 进程在早期的多任务操作系统中是基本的 执行单元 。每次进程切换都要先保存进程资源然后再恢 复这称为上下文切换。 但是进程频繁切换将引起额外开销从而严重影响系统的性能。 为了减少 进程切换的开销人们把两个任务放到一个进程中每个任务用一个更小 粒度 的执行单元来实现并 发执行这就是 线程 。 2. 线程与进程对比 1 进程间的信息难以共享。 由于除去只读代码段外父子进程并未共享内存因此必须采用一 些进程间通信方式在进程间进行信息交换。 但 多个线程共享 进程的内存如代码段、数据段、扩展段线程间进行信息交换十分方便。 2调用 fork() 来创建进程的代价相对较高即便利用写时复制技术仍然需要复制诸如内存页 表和文件描述符表之类的多种进程属性这意味着 fork() 调用在时间上的开销依然不菲。 但创建线程比创建进程通常要快 10 倍甚至更多。 线程间是共享虚拟地址空间的无需采用写时复 制来复制内存也无需复制页表。 41 单核机器上写多线程程序是否要考虑加锁为什么 参考回答 在单核机器上写多线程程序仍然需要线程锁。 原因 因为线程锁通常用来实现线程的同步和通信。在单核机器上的多线程程序仍然存在线程同步的问题。因为在抢占式操作系统中通常为每个线程分配一个时间片当某个线程时间片耗尽时操作系统会将其挂起然后运行另一个线程。如果这两个线程共享某些数据不使用线程锁的前提下可能会 导致共享数据修改引起冲突。 42 说说多线程和多进程的不同 参考回答 1一个线程从属于一个进程一个进程可以包含多个线程。 2一个线程挂掉对应的进程挂掉多线程也挂掉一个进程挂掉不会影响其他进程多进程稳 定。 3进程系统开销显著大于线程开销线程需要的系统资源更少。 4多个进程在执行时拥有各自独立的内存单元多个线程共享进程的内存如代码段、数据段、扩展 段但每个线程拥有自己的栈段和寄存器组。 5多进程切换时需要刷新 TLB 并获取新的地址空间然后切换硬件上下文和内核栈多线程切换时只 需要切换硬件上下文和内核栈。 6通信方式不一样。 7多进程适应于多核、多机分布多线程适用于多核 43 简述互斥锁的机制互斥锁与读写的区别 参考回答 1. 互斥锁机制 mutex 用于保证在任何时刻都只能有一个线程访问该对象。当获取锁操作失败 时线程会进入睡眠等待锁释放时被唤醒。 2. 互斥锁和读写锁 1 读写锁区分读者和写者而互斥锁不区分 2互斥锁同一时间只允许一个线程访问该对象无论读写读写锁同一时间内只允许一个写 者但是允许多个读者同时读对象。 答案解析 原理详解 互斥锁其实就是一个 bool 型变量为 true 时表示锁可获取为 false 时表示已上锁。这里说的是 互斥锁 其实是泛指linux 中所有的锁机制。 我们采用互斥锁保护临界区从而防止竞争条件。也就是说一个线程在进入临界区时应得到锁它在退出临界区时释放锁。函数 acquire() 获取锁而函数 release() 释放锁如图 每个互斥锁有一个布尔变量 available 它的值表示锁是否可用。如果锁是可用的那么调用 acquire() 会成功并且锁不再可用。当一个线程试图获取不可用的锁时它会阻塞直到锁被释放。 按如下定义 acquire() acquire() { while (!available); /* busy wait */ available false; } 按如下定义 release() release () { available true ; } 44 说说什么是信号量有什么作用 参考回答 1. 概念 信号量本质上是一个计数器用于多进程对共享数据对象的读取它主要是用来保护共享资源 信号量也属于临界资源使得资源在一个时刻只有一个进程独享。 2. 原理 由于信号量只能进行两种操作等待和发送信号即 P(sv) 和 V(sv) 具体的行为如下 1 P(sv) 操作如果 sv 的值大于零就给它减 1 如果它的值为零就挂起该进程的执行信号量 的值为正进程获得该资源的使用权进程将信号量减 1 表示它使用了一个资源单位。 2 V(sv) 操作如果有其他进程因等待 sv 而被挂起就让它恢复运行如果没有进程因等待 sv 而 挂起就给它加 1 若此时信号量的值为 0 则进程进入挂起状态直到信号量的值大于 0 若进程 被唤醒则返回至第一步。 3. 作用 用于多进程对共享数据对象的读取它主要是用来保护共享资源信号量也属于临界资 源使得资源在一个时刻只有一个进程独享。 45 进程、线程的中断切换的过程是怎样的 参考回答 上下文切换指的是内核操作系统的核心在 CPU 上对进程或者线程进行切换。 1. 进程上下文切换 1保护被中断进程的处理器现场信息 2修改被中断进程的进程控制块有关信息如进程状态等 3把被中断进程的进程控制块加入有关队列 4选择下一个占有处理器运行的进程 5根据被选中进程设置操作系统用到的地址转换和存储保护信息 切换页目录以使用新的地址空间 切换内核栈和硬件上下文包括分配的内存数据段堆栈段等 6根据被选中进程恢复处理器现场 2. 线程上下文切换 1保护被中断线程的处理器现场信息 2修改被中断线程的线程控制块有关信息如线程状态等 3把被中断线程的线程控制块加入有关队列 4选择下一个占有处理器运行的线程 5根据被选中线程设置操作系统用到的存储保护信息 切换内核栈和硬件上下文切换堆栈以及各寄存器 6根据被选中线程恢复处理器现场 46 简述自旋锁和互斥锁的使用场景 参考回答 1. 互斥锁 用于临界区持锁时间比较长的操作比如下面这些情况都可以考虑   1临界区有 IO 操作   2临界区代码复杂或者循环量大   3临界区竞争非常激烈   4单核处理器 1. 自旋锁就 主要用在临界区持锁时间非常短且 CPU 资源不紧张的情况下。 47 请你说说线程有哪些状态相互之间怎么转换 参考回答 类似进程有以下五种状态 1. 新建状态 (New) 2. 就绪状态 (Runnable) 3. 运行状态 (Running) 4. 阻塞状态 (Blocked) 5. 死亡状态 (Dead)   48 多线程和单线程有什么区别多线程编程要注意什么多线程加锁 需要注意什么 参考回答   1多线程从属于一个进程单线程也从属于一个进程一个线程挂掉都会导致从属的进程挂 掉。 2一个进程里有多个线程可以并发执行多个任务一个进程里只有一个线程就只能执行一 个任务。 3多线程并发执行多任务需要切换内核栈与硬件上下文有切换的开销单线程不需要切 换没有切换的开销。 4多线程并发执行多任务需要考虑同步的问题单线程不需要考虑同步的问题。 2. 多线程编程需要考虑 同步 的问题。线程间的同步方式包括 互斥锁、信号量、条件变量、读写锁 。 3. 多线程加锁主要需要注意 死锁 的问题。破坏死锁的必要条件从而避免死锁。 49 说说sleep和wait的区别 参考回答 1. sleep sleep 是一个 延时函数 让进程或线程进入休眠。休眠完毕后继续运行 。 在 linux 下面 sleep 函数的参数是秒而 windows 下面 sleep 的函数参数是毫秒。 windows 下面 sleep 的函数参数是毫秒。 例如 #include windows.h // 首先应该先导入头文件 Sleep ( 500 ) ; // 注意第一个字母是大写。 // 就是到这里停半秒然后继续向下执行。 2. wait wait 是父进程回收子进程 PCB 资源的一个系统调用。进程一旦调用了 wait 函数就立即阻塞自己 本身 然后由 wait 函数自动分析当前进程的某个子进程是否已经退出当找到一个已经变成僵尸的 子进程 wait 就会收集这个子进程的信息并把它彻底销毁后返回如果没有找到这样一个子进 程 wait 就会一直阻塞直到有一个出现为止。函数原型如下 子进程的结束状态值会由参数 status 返回而子进程的进程识别码也会一起返回。如果不需要结束 状态值则参数 status 可以设成 NULL 。 3. 区别 1 sleep 是一个延时函数让进程或线程进入休眠。休眠完毕后继续运行。 2 wait 是父进程回收子进程 PCB Process Control Block 资源的一个系统调用。 50 说说线程池的设计思路线程池中线程的数量由什么确定 参考回答 1. 设计思路 实现线程池有以下几个步骤 1设置一个生产者消费者队列作为临界资源。 2初始化 n 个线程并让其运行起来加锁去队列里取任务运行 3当任务队列为空时所有线程阻塞。 4当生产者队列来了一个任务后先对队列加锁把任务挂到队列上然后使用条件变量去通 知阻塞中的一个线程来处理。 2. 线程池中线程数量 线程数量和哪些因素有关 CPU IO 、并行、并发 如果是 CPU 密集型应用则线程池大小设置为 CPU 数目 1 如果是 IO 密集型应用则线程池大小设置为 2 * CPU 数目 1 最佳线程数目 线程等待时间与线程 CPU 时间之比 1 * CPU 数目 所以线程等待时间所占比例越高需要越多线程。线程 CPU 时间所占比例越高需要越少线程。 答案解析 1. 为什么要创建线程池 创建线程和销毁线程的花销是比较大的这些时间有可能比处理业务的时间还要长。这样频繁的创 建线程和销毁线程再加上业务工作线程消耗系统资源的时间可能导致系统资源不足。 同时线 程池也是为了提升系统效率。 2. 线程池的核心线程与普通线程 任务队列可以存放 100 个任务此时为空线程池里有 10 个核心线程若突然来了 10 个任务那么 刚好 10 个核心线程直接处理若又来了 90 个任务此时核心线程来不及处理那么有 80 个任务先 入队列再创建核心线程处理任务若又来了 120 个任务此时任务队列已满不得已就得创建 20 个普通线程来处理多余的任务。 以上是线程池的工作流程。 51 进程和线程相比为什么慢 参考回答 1. 进程系统开销显著大于线程开销线程需要的系统资源更少。 2. 进程切换开销比线程大。多进程切换时需要刷新 TLB 并获取新的地址空间然后切换硬件上下文和 内核栈多线程切换时只需要切换硬件上下文和内核栈。 3. 进程通信比线程通信开销大。进程通信需要借助管道、队列、共享内存需要额外申请空间通信 繁琐而线程共享进程的内存如代码段、数据段、扩展段通信快捷简单同步开销更小。 52 简述Linux零拷贝的原理 参考回答 1. 什么是零拷贝 所谓「零拷贝」描述的是计算机操作系统当中 CPU 不执行将数据从一个内存区域拷贝到另外一 个内存区域的任务。通过网络传输文件时这样通常可以节省 CPU 周期和内存带宽。 2. 零拷贝的好处 1节省了 CPU 周期空出的 CPU 可以完成更多其他的任务 2减少了内存区域之间数据拷贝节省内存带宽 3减少用户态和内核态之间数据拷贝提升数据传输效率 4应用零拷贝技术减少用户态和内核态之间的上下文切换 3. 零拷贝原理 在传统 IO 中用户态空间与内核态空间之间的复制是完全不必要的因为用户态空间仅仅起到了 一种数据转存媒介的作用除此之外没有做任何事情。 1 Linux 提供了 sendfile() 用来减少我们的数据拷贝和上下文切换次数。 过程如图 a. 发起 sendfile() 系统调用操作系统由用户态空间切换到内核态空间第一次上下文切换 b. 通过 DMA 引擎将数据从磁盘拷贝到内核态空间的输入的 socket 缓冲区中第一次拷贝 c. 将数据从内核空间拷贝到与之关联的 socket 缓冲区第二次拷贝 d. 将 socket 缓冲区的数据拷贝到协议引擎中第三次拷贝 e. sendfile() 系统调用结束操作系统由用户态空间切换到内核态空间第二次上下文切换 根据以上过程一共有 2 次的上下文切换 3 次的 I/O 拷贝。我们看到从用户空间到内核空间并没 有出现数据拷贝 从操作系统角度来看这个就是零拷贝 。内核空间出现了复制的原因 : 通常的硬 件在通过 DMA 访问时期望的是连续的内存空间。 2 mmap 数据零拷贝原理 如果需要对数据做操作 Linux 提供了 mmap 零拷贝来实现。
http://www.w-s-a.com/news/547367/

相关文章:

  • 生态城门户网站 建设动态it外包收费
  • 网站项目评价老渔哥网站建设公司
  • 哈尔滨寸金网站建设价格178软文网
  • 一个网站建设的成本网站开发过程及要点
  • 监控视频做直播网站中国建筑人才网下载
  • 网站建设公司华网天下买送活动集团网站设计案例
  • 哪些网站比较容易做哪个网站做中高端衣服
  • 做php网站教程wordpress去水印
  • 深圳微网站建设公司哪家好潍坊专业做网站的公司
  • 网站的弹窗广告怎么做软件开发包括
  • 网站开发人员保密做最优秀的自己演讲视频网站
  • 一般做网站要多少钱怎样选择高性价比的建站公司
  • 免费私人网站建设软件高端网站设计平台高端网站设计企业
  • 响应式网站建设的应用场景怎么申请电商平台
  • 怎么做垂直自营网站游戏咨询网站建设目标是什么
  • 建设网站需要给钱吗建立网站三大基础
  • 金融公司网站 htmlwordpress 防火墙
  • 重庆智能建站模板网站投票系统 js
  • 网站维护的内容和步骤网站做什么内容
  • 万网虚拟主机建网站wordpress协调世界时
  • 微网站建设方式应用大全网站
  • 网站速度测速织梦模板下载
  • 环保网站建设公司排名汉阴网站建设
  • 自己做网站的二维码wordpress用户权限在哪改
  • 网站使用说明书网站建设公司的介绍
  • 推广型网站免费建设网站防盗链设置
  • 建设银行网站查开户行网站反链暴增怎么回事
  • centos7做网站软件实施工程师工资一般多少
  • 专业房产网站建设深圳建设交易集团
  • 政务网站建设标准项目经理接到网站开发怎么开展