目录
一、简述GDB常见的调试命令,什么是条件断点,多进程下如何调试?
一、简述GDB常见的调试命令,什么是条件断点,多进程下如何调试?
1、GDB调试
GDB调试是可执行文件,在gcc编译时加入-g,告诉gcc在编译时加入调试信息,这样gdb才能调试这个被编译的文件gcc -g test.c -o test。然后执行命令:gdb ./test ,进入调试状态。
2、GDB常见命令
(1)quit:退出gdb,结束调试;
(2)list:查看程序源代码;
list或者l:直接显示前10行代码,回车后会显示全部代码
list 5,10 :显示5到10行的代码
list test.c:显示test.c的5到10行的代码,尤其是调试多个文件时使用
list get_sum:显示get_sum函数周围的代码
(3)search 字符串:查找这个字符串所在的位置;
(4)run:程序开始运行;
(5)help list/all:查看帮助信息
(6)break:加断点
b 8:在第8行加断点
i b :查看已经设置的断点
p a:用p查看这个变量a的值(print a)
d 8:删除第8行这个断点
(7)next:继续执行下一条语句,会把函数当作一条语句执行,但不会进入到函数内部
(8)step:继续执行下一条语句,会跟踪进入函数,一次一条的执行函数内的代码。
(9)break if:条件 以条件表达式设置断点,break 8 if a==2 在断点8处设置a=2
(10)多进程下如何调试:
用set follow-fork-mode child 调试子进程
用set follow-fork-mode parent 调试父进程
二、makefile的制作
直接写最终版本
OBJS = main.o tool1.o tool2.o
CC=gcc
CFLAGS=-c -Wall -g
mytool:$(OBJS)
$(CC) $^ -o mytool
%.o:%.c
$(CC) $^ $(CFLAGS) -o $@
clean:
$(RM) *.o mytool -r
举例:
“cal.h”
#ifndef _CAL_H_
#define _CAL_H_
int add(int,int);
int sub(int,int);
#endif
"add.c"
#include "cal.h"
int add(int a,int b)
{
return a+b;
}
"sub.c"
#include "cal.h"
int sub(int a,int b)
{
return a-b;
}
"main.c"
#include <stdio.h>
#include "cal.h"
int main()
{
int a=12;
int b=3;
printf("sum=%d\n",add(a,b));
return 0;
}
makefile
OBJS = main.o sub.o add.o
CC=gcc
CFLAGS=-c -Wall -g
mytool:$(OBJS)
$(CC) $^ -o mytool
%.o:%.c
$(CC) $^ $(CFLAGS) -o $@
clean:
$(RM) *.o mytool -r
三、大小端
什么是大端模式,什么是小端模式?
1、大端模式:高的有效字节存储在低的存储器地址,按内存增长的顺序相反。
网络字节序一般为大端模式。
2、小端模式:低的有效字节存储在低的存储器地址,按内存增长的顺序一致。
ASM、DSP、X86等都采用小端模式。
四、说说进程调度算法有哪些
1、先来先服务算法:每次调度都是从后备作业(进程)队列中选择一个或者多个最先进入该队列的作业(进程),将他们调入内存,为他们分配资源,创建进程,然后放入就绪队列。
2、短作业优先算法:从后备队列中选择一个或若干个估计运行时间最短的作业,将他们调入内存运行。
3、高优先级调度算法:系统将从后备队列中选择若干个优先级最高的作业装入内存。当用于调度时,该算法把处理及分配给就绪队列中优先权最高的进程。
4、时间片轮转法:每次调度时,把CPU分配给队首进程,并令其执行一个时间片。时间片的大小从几ms到几百ms。当执行的时间片用完时,由一个计时器发出时钟中断请求,调度便据此信号来停止该进程的执行,并把它送往就绪队列的末尾;然后再把处理机分配给就绪队列的中新的队首进程,同时也让他执行一个时间片。
五、操作系统如何管理内存
1、物理内存
物理内存有四个层次:寄存器、高速缓存、主存、磁盘
寄存器:速度最快,量少,价格贵;
高速缓存:次之;
主存:再次之;
磁盘:速度最慢,量多,价格便宜。
1ns | 寄存器 <1KB |
2ns | 高速缓存 4MB |
10ns | 主存 1~8GB |
10ms | 磁盘 1~4TB |
操作系统会对物理内存进行管理,有一个部分称为内存管理器,它主要的工作是有效的管理内存,记录哪些内存是正在使用的,在进程需要时分配内存以及在进程完成时回收内存。
2、虚拟内存
操作系统为每一个进程分配一个独立的地址空间,这个地址空间是虚拟内存。
虚拟内存与物理内存存在映射关系,通过页表寻址完成虚拟地址与物理内存的转换。
3、为什么使用虚拟内存
因为早期的内存分配存在以下问题:
(1)进程地址空间不隔离,会导致数据被随意修改;
(2)内存使用率低;
(3)程序运行的地址不确定,操作系统随机为进程分配内存空间,所以程序运行的地址是不确定的。
4、使用虚拟内存的好处
(1)扩大地址空间:每个进程独占4G空间,虽然真实物理内存没那么多;
(2)内存保护:防止不同进程对物理内存的争夺和践踏,可以对特定内存地址提供写保护,防止恶意篡改;
(3)可以实现内存共享,方便进程通信;
(4)可以避免内存碎片,虽然物理内存可能不连续,但映射到虚拟内存上可以连续。
5、虚拟内存的缺点
(1)虚拟内存需要额外构建数据结构,占用空间;
(2)虚拟内存到物理内存的转换,增加了执行时间;
(3)页面换入换出耗时。
(4)一页如果只有一部分数据,浪费内存。
6、操作系统如何申请内存
从操作系统角度来看,进程分配内存有两种方式:分别由两个系统调用完成:*brk和mmap