Linux操作系统基础:
1、Linux概述:
Linux是类UNIX操作系统,是一个UNIX兼容的系统,大部分通用的UNIX工具和程序都可以在Linux系统下运行。
使用GNU(GNU is Not Unix)工具开发:
gcc,glibc,binutils,make。
GPL = General Public License
Linux优点:
提供了先进的网络支持;多任务、多用户;符合IEEE POSIX标准;支持数十种文件系统格式;完全运行于保护模式;开放源代码;采用先进的内存管理机制,更加有效地利用物理内存。
Linux作为嵌入式操作系统的优势;
低成本开发系统;可应用于多种硬件平台;可定制的内核;性能优异;良好的网络支持。
一种开放源码、软实时、多任务的嵌入式操作系统。
2、linux系统结构
2.1、Linux系统的一般结构:
由四个主要部分组成:
- 内核
- shell
- 文件系统
- 应用程序
内核、shell、文件系统一起形成了基本的操作系统结构,他们使得usr可以运行程序、管理文件并使用系统。
内核、Shell和用户的关系:
用户在最外层,内核在最内层,Shell作为沟通内核和用户的媒介。
Linux内核:
- 内存和进程管理
- 设备驱动程序
- 文件系统
- 网络管理等
2.2、内存和进程管理:
内存管理:
采用了“虚拟内存”的内存管理方式;
虚拟内存采用动态地址映射方式(进程的地址空间和存储空间的对应关系是在程序的执行过程中实现的);
虚拟内存使计算机可以操纵更大的地址空间,使得每个进程都有一个自己的虚拟地址空间;
共享虚拟内存机制,虽然允许进程拥有分离(虚拟)的地址空间,但有时也需要进程之间共享内存;
x86体系架构上,把线性地址映射到物理地址分为两个步骤。提供给进程的线性地址被分为三个部分:一个页目录索引,一个页表索引和一个偏移量。
进程管理:
1)启动进程:手工启动、调度启动;
2)调度进程:
ps——查看系统中的进程;top——动态显示系统的中的进程;
nice——按用户指定的优先级运行进程;renice——改变正咋运行进程的优先级;
kill——结束进程(包括后台进程);bg——将挂起的进程在后台执行;
fg——把后台运行的进程放到前台运行。
2.3、设备驱动程序:
设备驱动程序提供一组操作系统可理解的抽象接口完成和操作系统之间的交互,而与硬件具体的操作细节则由设备驱动程序完成。
驱动程序分为四个主要组成部分:
- 自动配置和初始化程序;
- 完成用户进程请求的程序(永恒进程对设备的操控部分)
- 设备中断服务程序
2.4、文件系统:
文件系统——对一个存储设备上的Data进行组织的机制;
文件系统的功能和特性:
- 提供用户或程序对数据管理的接口,如数据的存储和操作等;
- 提供数据和目录的分层组织形式支持;
- 提供文件、创建和删除功能支持;
- 尽可能保证文件中数据的有效性;
- 提供对不同存储设备的I/O支持
文件分类:
文件类型 | 类型符号 | 描述 |
普通文件 | - | ASCII文本文件、二进制可执行文件、硬链接文件 |
块设备文件 | b | 块输入/输出设备文件 |
字符设备文件 | c | 原始输入/输出设备文件,每次I/O只送一个字符 |
目录文件 | d | 包含若干文件或子目录 |
符号链接文件 | l | 只保留了所指向文件的地址,而不是文件本身 |
管道文件 | p | 用于进程之间通信的管道文件 |
套接字文件 | s | 方便进程之间通信的特殊文件,与管道不同的能通过网络连接使不同计算机的进程之间通信 |
目录结构:
目录 | 功能说明 |
/bin | 常用命令存放目录 |
/boot | 包含内核和启动文件 |
/dev | 设备文件存放目录(与底层驱动打交道) |
/etc | 存放系统配置文件 |
/home | 用户注目礼,新建用户后,用户的源文件存于此处 |
/lib | 常用库文件的目录 |
/mnt | 挂载目录 |
/root | root |
/usr | 应用程序存放目录 |
/proc | process |
支持的文件系统:
- ext2和ext3
- swap
- FAT
- vaft
- NFS
- ISO9660
- 内存文件系统:proc,sys,ramdisk
- 嵌入式文件系统:cramfs,jffs,yaffs
虚拟文件系统(VFS):
内核中的一个软件层,用于给用户空间程序提供文件系统接口,也提供内核的一个抽象功能,允许不同的文件系统共存。
设计思想:
1)对多个文件系统的共同特性进行抽象基础上,形成一个与具体文件系统实现无关的虚拟层,在此处定义与用户一致性的接口;
2)文件系统的具体实现层使用类似于开关表的技术进行文件系统转接,实现各文件的具体细节,每个文件系统都是自包含,包含文件系统实现的各种设施。
3、shell命令
Shell及时linux内核的一个外层保护工具,并负责完成用户与内核之间的交互;
命令——用户向系统内核发出控制请求,与之交互的文本流;
Shell——一个命令解释器(用户输入命令,shell解释命令,返回给用户不同结果)
Shell脚本——将多条命令和控制语句编辑为脚本文件,给Shell批量处理。
Shell命令提示符号:
username@hostname:direction$
username:用户名,显示当前的用户名。
hostname:主机名,远程登陆后,显示登陆的主机名。
direction: 目录名,显示当前所处的路径。
命令的三要素:
- Command——命令名称,Shell命令或程序,严格区分大小写
- Options:命令选项,用于改变命令所执行的类型,由"-"号引导,可有多个选项;
- Argument:命令参数,之处命令作用的对象或目标,允许多个。
一条命令的三要素要用空格号隔开;若多个命令在一行内书写要用“;”号将命令隔开。
一条命令在一行内写不完,用反斜杠\表明未结束。
用户系统相关命令:
1)用户切换命令:su
作用:变更为其它使用者身份,将普通用户身份转变为超级用户。
格式:su [选项] [使用者]
选项 | 参数含义 |
-,-l,--login | 该用户登陆,大部分环境变量和工作目录都是以该使用者为主,缺省为root |
-m,-p | 执行su时不改变环境变量 |
-c,--command | 变更账号为USER的使用者,执行完指令(conmmand)后再变回原来的使用者 |
2)用户管理指令:(useradd和passwd)
useradd:添加用户账号;passwd:更改对应用户账号密码。
选项 | 参数含义 |
-g | 指定用户所属的群组 |
-m | 自动创建用户的登入目录 |
-n | 取消建立以用户为名的群组 |
3)系统管理命令:(ps和kill)
ps:显示当前系统中由该用户运行的进程列表;
-ef——查看所有进程机器PID、系统时间、命令详细目录、执行者;
-aux——除上述外还可以显示CPU以及内存占用率;
-w——显示交款并且可以显示较多的信息
kill:输出特定的信号给指定PID(进程号)的经常,并根据该信号完成指定行为。
文件目录相关命令:
1)改变工作目录命令:cd
其中的路径为要改变的工作目录,可为绝对路径或相对路径;
./表示当前目录;../表示上一级目录。
2)列出目录的内容命令:ls
-l,--format=single-column——一行输出一个文件;
-a,-all——列出目录中所有文件,包括“.”开头的文件;
-f——不排序目录内容,按tm在磁盘上存储的顺序输出。
3)创建一个目录文件:mkdir
-m——对新建目录设置存取权限,也可以用chmod命令设置;
-p——可以是一个路径名称,加上此选项后,系统将自动创建好那些尚且不存在的目录,即一次创建多个目录。
4)删除一个文件:rm
-r——递归处理删除目录及其子目录;
-f——删除文件或目录;
-rf——删库跑路(绷)
压缩打包相关命令(只介绍两个,要看文件后缀哦):
1)压缩与解压缩命令:gzip(有目录不会压缩)
-c——将输出信息写到标准输出上,并保留原有文件;
-d——将文件解压缩;
-l——对每个压缩文件,显示压缩文件的大小、未压缩文件的大小、压缩比、未压缩文件名;
-r——查找指定目录并压缩或解压缩其中的所有文件;
-t——测试,检查压缩文件是否完整;
-v——对每一个压缩和解压缩的文件显示文件名和压缩比
2)打包和解压缩命令tar:
-c——建立新的打包文件
-r——向打包文件末尾追加文件;
-x——从打包文件中解出文件;
-o——从文件解开到标准输出;
-v——处理过程中输出相关信息;
-f——对普通文件操作;
-z——调用gzip来压缩打包文件,与-x连用完成解压缩
-j——调用bzip2来压缩打包文件,与-x...
-z——调用compress来压缩打包文件,与-x...
4、linux下C语言程序基础
C语言介绍:
C语言具有高效性、灵活性、可移植性的特点;其为面向过程的语言(编程时需要明确指定程序实现的步骤;程序由函数/子程序构成);也是接近硬件的编程语言(开发驱动程序,开发嵌入式系统程序、操作系统);一种流行的编程语言。
C程序包含4部分:
程序文档说明部分、预处理部分、全局声明部分、程序代码部分。
//1. Docunment Section 文档说明
// The role of the program(这段程序的作用)
// Author:
// Data:
//2. Pre-processor Direction Section 预处理部分
#include<stdio.h> // Standard I/o 标准输入输出
//3. Global Declarations section 全局声明部分
const int N = 1e6 + 10
//4. Program Section
int main(void){
return 0;
}
基础操作:
1)位运算:
存在六种位操作符:
运算符 | 含义 | 运算符 | 含义 |
& | 按位与 | ~ | 取反 |
| | 按位或 | << | 左移 |
^ | 按位异或 | >> | 右移 |
unsigned int a = 60; //60 = 0011 1100
unsigned int b = 13; //13 = 0000 1101
int c = 0;
c = a & b; //12 = 0000 1100
c = a | b; //61 = 0011 1101
c = a ^ b; //49 = 0011 0001 异或可以看做是不带进位的加法。
c = ~a; //-61 = 1100 0011,由于c为int类型,第一位为符号位,此时是补码。
c = a << 2; //左移相当于乘2,此时左移两次相当于乘4,240 = 1111 0000
c = a >> 2; //右移相当于除2,,15 = 0000 1111
unsigned int x = 0010 1000;
//设置某位的bit
x |= (1<<n);
// 清除某位的bit
x &= ~(1<<n);
// 翻转某位的bit
x ^= (1<<n);
// 测试某位的比特
x &= (1<<n);
2)define宏定义关键词:
define是C语言中的一个预处理命令,用宏名来表示一个字符串,在宏展开时又以该字符串取代宏名。
语法:
#define 标识符 字符串
标识符为宏名,字符串可以是常数、表达式、格式串等。
3)ifdef条件编译:
嵌入式程序开放中,当满足某条件时对一组语句进行编译,而当条件不满足是则编译另一组语句。一般呢用于多文件组合时,避免多次编译相同的头文件导致报错。
语法:
#ifdef 标识符
程序段1
#else
程序段2
#endif
4)extern变量声明:
放在变量或函数前,表示该变量(函数)的定义在别的文件中,编译器应该去其他模块中寻找其定义。
extern声明变量可以多次但是该变量的定义只能有一次。
main.c文件下:
int n = 10;
test.c文件:
extern int n;
定义与main.c下,test文件中使用extern来使用main文件下的n。
不使用该关键字时,不同文件的同名变量没有直接联系。
5)typedef类型别名:
用于为现有类型创建一个别名,简化变量的定义。
typedef 原类型 新类型(别名);
6)结构体:
构造类型;表示不同类型的变量。
Struct 结构体名{
成员列表;
}变量名列表;
应用格式:
变量名.成员
结构体指针变量:
Struct 结构体名 *变量名;
引用:->表示指针
变量名->成员名;
其优点在于可以不改变入口参数,通过改变成员变量来改变入口参数。
串口初始化程序中入口参数为结构体类型的变量或者指针变量。
添加新参数只需要在结构中加入新的成员变量,不需要修改函数定义。
7)static关键字:
C语言中,static声明的变量具有隐藏功能,仅在其作用范围内可见;
static声明的变量内容能够保持,放在全局存储区,下一次调用保持原来的值;
默认初始化为0。
例子:
src1.c
static char a = 'A';
static void msg(){
printf("hello\n");
}
此时a和msg()都被static修饰,其作用域为文件作用域,仅在src1.c文件中可见。
main.c
int main(void){
extern char a;
extern void msg();
printf("%c",a);
msg();
return 0;
}
此时虽然加入了extern关键字,但是a和msg()均被限制在src1.c文件中可见,故extern关键字无效,a和msg()函数并不能被编译器识别。
C语言编程环境:
1、vi编辑器:
暂时感觉没必要展开,时间多日后补充,直接vscode编写好了(懒)。
2、gcc编译器:
GNU C compiler的简称,是一组编译工具的总称,主要任务为预处理和编译,提供与编译器相关的运行库支持。
可以完成C、C++、Objectiver C等源文件想运行在特定CPU硬件上的目标代码转换。
gcc编译流程分为4个步骤:
1)预处理(Pre-Processing):对代码中#开通的命令进行处理;
2)编译(Compiling):检查代码规范性以及是否有语法错误,无则翻译为汇编语言;
3)汇编(Assembling):将编译阶段生成的“.s”文件转换成目标文件.obj;
4)链接(Linking):把目标文件和标准库进行连接,生成可执行文件.exe。
3、gdb调试器:
4、make工程管理:
管理较多的文件,是个自动编译管理器(自动——能更具文件时间戳发现更新过的文件二减少编译的工作量,同时读入Makefile文件的内容来执行大量的编译工作)。
大大提高了实际项目的工作效率,几乎所有Linux下的项目编程均会涉及他。
1)Makefile基本结构:
Make读入的唯一配置文件,通常包含:
Make工具常见的目标体(target),通常是目标文件或可执行文件;
要创建的目标体依赖文件(dependency_file);
创建每个目标体时需要运行的命令(command),必须一制表符(tab键)开头。
格式:
target:dependency_files
command
# the simplest example
hello.o:hello.c hello.h
gcc -c hello.c -o hello.o
接着便可以使用make了
make target
这样make就会自动读入Makefile并执行target的command语句,并会找到相应的依赖文件。
2)创建和使用makefile变量:
同来代替一个文本字符串;
变量定义的两种方法:1、递归展开式VAR = var;2、简单方式VAR: =var;
变量使用:$(VAR)
OBJS = kang.o yul.o
CC = gcc
CFLAGS = -Wall -O -g
david:$(OBJS)
$(CC) $(OBJS) -o david
kang.o:kang.c kang.h
$(CC) $(CFLAGS) -c kang.c -o kang.o
yul.o:yul.c yul.h
$(CC) $(CFLAGS) -c yul.c -o yul.o
3)Makefile变量:
- 童虎自定义变量
- 预定义变量
- 自动变量
- 环境变量
自动变量 | 含义 |
$< | 第一个依赖文件名称 |
$@ | 目标文件完整名称 |
$^ | 所有不重复的依赖文件,以空格号隔开 |
暂时只写这三个常用的自动变量。
OBJS = main.o file1.o file2.o file3.o file4.o
CC = gcc
CFLAGS = -Wall -O -p
david:$(OBJS)
$(CC) $^ -o $@
main.o:main.c file1.h file2.h file3.h file4.h
$(CC) $(CFLAGS) $< -o $@
file1.o:file1.c file1.h
$(CC) $(CFLAGS) $< -o $@
file2.o:file2.c file2.h
$(CC) $(CFLAGS) $< -o $@
file3.o:file3.c file3.h
$(CC) $(CFLAGS) $< -o $@
file4.o:file4.c file4.h
$(CC) $(CFLAGS) $< -o $@
嵌入式Linux程序设计:
Linux系统调用与API:
1.1、系统调用:
Linux中将程序的运行空间分为内核空间和用户空间(内核态与用户态),分别运行在不同的级别上,逻辑上相互隔离。
用户通常不能访问内核数据,也不能使用内核函数,只能在用户空间中操作用户数据和用户函数。
用户空间的进程需要获得一定的系统服务(调用内核空间程序)。
- 操作系统提供给用户一组接口来获得系统内核提供的服务;
- 系统调用规定用户进程进入内核空间的具体位置;
- 系统调用时,程序运行空间需要从用户空间进入内核空间,处理完成红再返回到用户空间;
- 用户通过进程控制相关的系统调用来创建进程、实现进程调度、进程管理等。