- static作用:
限定作用域,将空间定义在静态区. 主要限定如下内容:
函数:限定函数只能在本文件.c内部使用.
全局变量: 限定全局变量只能在本文件.c中使用.
局部变量: 将局部变量定义在静态区域,这样函数下次可以访问同一个空间.
extern:因为其他文件(外部)定义的全局变量.
static inline: 类似宏函数,该参数修饰的函数,在被调用的地方被自动展开,减少函数调用的层次,节省CPU资源,但是会导致程序变大!
- volatile: no cache
- 防止编译器对代码进行优化 每次读写变量,结果都是直接更新到 实际的地址中
主要用在多个执行单元同时访问一个变量/寄存器的情况.
(valotile的使用主要是在以下三个方面)
*:中断 和进程共享变量
*:进程和进程
*:寄存器, 程序读写寄存器结果直接写入寄存器,防止中间 缓存的问题.
- const:分成2方面 1.修饰指针 2.修饰数据 (修饰的数据具有不可变性)
*****(const在*号左侧修饰指针指向的变量,const在*右侧修饰的是指针)
*:int const *p 指针常量
*:const int *p 指针常量,和上面的一致
*:int *congst p 常量指针
*:const int * const p 常量指针常量
- 堆和栈的区别:
一、堆栈空间分配区别:
1、栈(操作系统):由操作系统自动分配释放 ,函数调用过程中,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈;
2、堆(操作系统): 一般由程序员分配释放 (malloc free), 若程序员不释放,程序结束时可能由OS回收,分配方式倒是类似于链表。
二、堆栈数据结构区别:
堆(数据结构):FIFO队列
栈(数据结构):一种先进后出的数据结构 FILO。
- 大端小端:不同的CPU使用的字节序不一致,导致多终端通信的时候数据混乱.
大端是低地址存放高位,高地址存放低位
小端是数据在内存中是高地址存放数据的高位,低地址存放低位
题目:编写程序,测试机器是大端还是小端??? 提示:共用体union
- 结构体对齐:为了提高计算机效率,结构体在内存中存取是按字长对齐的。
比如32bitcpu是按照32bit对齐,64bitcpu按照64bit对齐.
自然对齐: 一个基本类型变量大小和他所在的地址成倍数关系,则成为该变量是自然对齐的.比如 int a,所在的地址应该是 0 4 8 12 16 20……….
网上找几个笔试题,好好看看!
- 全局变量和局部变量的区别: 主要结合平时的用法思考
*:作用域不同
*:存储方式不同:全局变量在全局数据区中,局部变量在栈区
*:生命周期不同:全局变量随程序结束而销毁,局部变量在其作用区结束时销毁
- 程序中都有那些段(堆栈段、代码段、数据段):
堆:堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。
栈:是用户存放程序临时创建的局部变量。
代码段:存放程序执行代码的内存区域。
数据段:存放程序中已初始化的全局变量的一块内存区域。
bss段:全局的未初始化变量,不分配空间。
9.函数指针和指针函数:
指针函数,就是一个函数,只是返回值是一个指针
函数指针呢,是一个指针,指向函数的指针 比如 void (*ptfun)(int yy);
数据结构:
1.栈和队列的区别:
栈是先进后出 FILO,队列是先进先出 FIFO。有顺序栈 链式栈 顺序队列 链式队列.
2.环形队列:
队列,先进先出的结果. 环形队列,首尾相连的队列,一般用作缓存[R W]。
3.链表和数组的区别:
数组占用连续的空间,一次分配不可改动,随机访问, 增删改查细节
链表不占用连续的空间, 动态分配空间, 需要遍历访问 增删改查细节
4.单链表如何逆序:
分离表头和元素,将后面的元素依次插入表头后面即可. 参考笔记:代码
5.双向链表:能访问上一结点的链表,相对于单向链表只记录后一个元素的位置,双向链表也会记录上一个节点的位置。
6.排序方法: 冒泡 快速 选择 查找方法:顺序 二分 hash查找 目录查找
笔试中,一般要求 冒泡/选择 排序
7.进程间通信方式及它们之间的区别:(IPC对象:进程通信方式)
*无名管道:管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
*有名管道;有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
*消息队列通信:消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
*信号量通信:信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
*信号:信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
*共享内存通信:效率最高, 共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间的同步和通信。
*套接字socket通信:套接口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同机器间的进程通信。
- 线程同步:多个线程可能同时使用一个共享资源,使用线程锁解锁问题
- 进程线程区别:
一个进程至少有一个线程
*进程之间执行过程中拥有独立的内存单元,一个进程的多个线程共享内存,极大的提高了运行效率
*线程不能独立执行,必须依赖已存在的应用程序
*多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但 是操作系统并没有把多个线程看作多个独立应用
****优缺点:线程开销小, 但是独立性不高.
- 线程同步/互斥:
*互斥锁:申请一把锁,使用资源时上锁,在用完之后开锁,让资源在同一 时间只有一个线程在使用
*信号量:初始化信号,让使用的线程进行PV(申请、释放)操作,从而使 线程以自己预定的逻辑运行
- 死锁:死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。
- IO模型:
阻塞、非阻塞、异步通知、多路复用。 区别自己整理.
网络编程 TCPIP OSI[7层]
- TCP/IP分层:分为四层。应用层、TCP层、IP层、网络接口层。
- 各层作用:
应用层:负责提供数据
TCP层:负责数据安全性问题, 有端口号可以识别数据包发给那个app
IP层:提供端到端的服务,不负责安全问题,负责数据包在网际中穿梭. 有ip地址可以标识主机.
网络接口层:根据当前使用的不同的物理介质。将数据转换成不同的信号发 送出去
- TCP/UDP优缺点:
TCP是面向连接的、流的、安全可靠的
UDP是面向无连接的、数据包的、不安全可靠的
- 窗口:TCP头里的主要用于流量控制、防止数据溢出
- 组播/广播区别:广播是所有人能听到,在组播中想接收消息需要进入特定组
- 三次握手/四次挥手:用于建立连接和断开连接. 三次握手防止第二条链接出现四次挥手断开所有链接
- ARP协议:根据IP地址获取物理地址的协议
- ICMP协议:是TCP/IP协议族下的一个子协议,用于在IP主机、路由器之间传 递控制消息 比如ping命令
- 套接字类型:流式套接字 数据报套接字 原始套接字
- 多路复用: select 监控有上限 无法获取有事件发生的fd
Poll 监控无上限 无法获取有事件发生的fd
Epoll 监控无上限 可以获取有事件发生的fd
- 服务器并发:
- 多进程/多线程 实时性高 资源占用大
- 多路复用 实时性差 资源占用小
- 对方挂掉通过返回值获取状态
如何获取对方挂掉了? recv返回值0
- 字节序转换/结构体对齐:字节序问题, 发送之前主机转网络字节序,接手之后网络转主机
- 路由器工作在IP层
负责寻址,工作在网络层 交换机工作在[网络接口 网络层]
系统移植
- 内核/uboot使用的是3.14
- Uboot给内核传参:uboot会给内核传很多参数如:串口 RAM videofb MAC 地址等,内核会读取并解析这些数据,两者减通过tag结构体传递参数
- Uboot的几个阶段:一共分为三个阶段
*最开始为汇编代码 核心硬件的初始化 关闭中断/看门狗/内存的初始 化 设置堆栈为后面的C开空间 #自拷贝#
*大部分硬件的初始化 鼠标键盘网卡 自动/交互 加载操作系统
*设置uboot将要传给内核的tag,以及解析uboot头里包含的信息最终跳转到内核,将主控权交给内核
自考呗:uboot将自己从flash拷贝到RAM中 然后去RAM 中执行 速度问题
交互模式:用户可以配置uboot的工作方式
自动模式:uboot自动去加载操作系统
- 内核移植过程:
*搭建交叉开发环境
*bootload的选择和移植
*内核的配置、编译和移植
*根文件系统的制作
- 文件系统:nfs
驱动开发
- 用户和内核的通信方式:
*API:函数接口
*proc文件系统:proc是一种虚 拟文件系统,有别于普通文件,虚 拟文件都是动态创建的
*sysfs文件系统:proc和sysfs可以作为内核和用户交互的手段
*netlink: netlink套接字用以实现用户进程与内核进程通信的一种特 殊进程间通信方式。好处①使用自定义协议完成数据交换,不需要 添加一个文件②支持多点传输③支持内核优先发起会话④异步通 信,支持缓存机制
*文件:较笨拙的方法,内核往文件写数据,用户读数据
*系统调用:将内核空间的地址映射到用户空间
*信号:从内核向进程发送信号
- 用户到内核的过程:
- 内核同步机制和区别:
*原子变量:多用于计数的受保护的值
*自旋锁:没有资源时会一直轮询 反应较快但消耗CPU
*互斥锁:没有资源会睡眠不会消耗CPU
*中断屏蔽:中断拥有硬件优先级 即使上锁也无法阻止 中断
- 系统启动流程:
*加载内核:
*启动初始化:
*确定运行级别:
*加载开机启动程序:
*用户登陆:
*进入login shell:
*打开non-login shell:
- 中断响应流程:保护断点 寻找中断入口 执行中断程序 之后恢复现场继续执行
- 中断下半部分有哪些/区别:
*软中断:内核使用 不用太关心
*tasklet:驱动使用 基于软中断实现 软中断>tasklet>进程不能睡眠 执行 紧急耗时任务
*工作队列:可以睡眠 执行紧急耗时任务 内核中有一个专门的线程,顺 序执行这些工作队列
- Kmalloc/vmalloc的区别:两者都用于内核
*Kmalloc:分配的资源32b--128k 且物理地址和虚拟地址都 连续访问 效率很高
*Vmalloc:申请的空间可以很大 从内存中捡漏组成一个你需要的空间 物理地址可能不连续虚拟地址连续 效率低
- Linux有哪些设备/区别:
*字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设 备内存中的某一个数据,读取数据需按先后
*块设备:指可以从设备的任意位置读取一定长度数据的设备如硬盘
*网络设备:任何网络事务都通过一个接口来进行,能够与其它主机交 换数据
- 内核调试方法有哪些:点灯 printk 日志系统 OOPS proc+sysfs文件系统
- 怎么操作寄存器:ioremap将物理地址映射为虚拟地址 writel/readl 用完 需要释放
- 总线是啥:链接设备和驱动的中间人
*串行总线:数据同时发送 没有固定格式 传输速度快 但传输成本高不适合 远距离使用
*并行总线:数据只能各位逐次收发 速度较慢 但便于远距离传输
*以下三种都为串行总线,都是常见的低速板级通信协议
- I2C:有两根线:分别时SDA(数据)、SCL(时钟),也是一种同步传输协议。 主机开始 信号后,先发送7bit的地址位和1bit的读写位,每个从机都有 自己的I2C地址,当发现该条指令是发给自己的,就会拉低SDA线(即回复 ACK信号),然后主机发送或接受数据,结束时主机发送停止消息
- SPI:有四根线:分别时CS(片选)、MOSI(主发从收)、MISO(从发主收)、 CLK(时 钟),是一种同步传输协议。在启动传输千,需要先拉低(根据具体 芯片决定)对应从机CS管脚,传输完成后再拉高,从机上的SPI模块进入休 眠
- UART:一般由TXD、RXD、GND三根线组成,是一种异步传输协议。主从机 均可自由收发数据,但是UART没有时钟线,所以需要提前约定对应的波特 率,这是一种和简单的传输协议,因为没有时钟线通信时要求双方都要有相 同的波特率,也就是要求要有自己的时钟源
I2C和SPI都是同步协议且都有时钟线,在同一条总线上可以挂多个从设 备,但是I2C的从设备是根据地址来区分的,SPI的从设备是通过CS(片选) 线来区分的,所以SPI总线上每多一个从设备就要多一条线作为片选线,而 I2C只要地址不冲突就可以挂载多个设备,所以在一对多通信时I2C更具优 势,但是I2C总线的速度要低于SPI
- 内核中的文件:
*bin 二进制的可执行命令
*boot 存放系统启动时需要用到的程序
*dev 设备挂载文件
*etc 系统管理和配置文件
*lib 动态链接共享库
*home 用户目录
*root 管理员目录
- 进程的启动和终止方式:
*手动启动:用户在终端发出命令,直接启动一个进程
①前台启动 ②后台启动
*调度启动:系统根据系统资源和进程占用资源情况,事先进行调度安排, 制定任务运行的时间、场合,到时候系统自动完成该任务