导图社区 嵌入式
嵌入式系统是一种专用的计算机系统,它被设计用于执行特定的任务,通常被嵌入到其他设备中作为一个重要组成部分。它以应用为中心,以计算机技术为基础,能够根据用户需求(功能、可靠性、成本、体积、功耗、环境等)灵活裁剪软硬件模块。希望能帮到期末复习嵌入式的你!
编辑于2024-06-10 17:21:30嵌入式
第一章
组成结构
硬件层
中间层
软件层
功能层
内核——操作系统的核心
将一些与硬件紧密相关的、基本的、公共的、运行频率较高的模块以及关键性数据结构独立开来,使之常驻内存,并对他们进行保护
这一部分称之为操作系统的内核
API(应用程序接口)
程序与操作系统的接口
为程序员在编程时使用的,系统和应用程序通过这个接口,可以在执行中访问系统中的资源和获取OS的服务
第二章
系统调用
重要意义——(往用户程序怼,后两个集中于用户程序和内核)
用户程序通过系统调用来使用硬件,而不用关心具体的硬件设备
系统调用使得用户程序有更好的可移植性
系统调用使得内核能更好地管理用户程序,增强了系统的稳定性
系统调用有效地分离了用户程序和内核的开发
分类——按功能
设备管理:完成设备的请求/释放/启动等功能
文件管理:完成文件的读/写/创建/删除等功能
进程控制:完成进程的创建/撤销/阻塞/唤醒等功能
进程通信;完成进程之间的消息传递/信号传递等功能
内存管理:完成内存的分配/回收等功能
运行空间分为内核空间和用户空间
kernel space是Linux内核的运行空间,User space是用户程序的运行空间。为了安全,他们都是隔离的,即使用户的程序崩溃了,内核也不受影响
kernel space可以执行任意命令,调用系统的一切资源;User space只能执行简单的运算,不能直接调用系统资源,必须通过系统接口(system call),才能向内核发出指令。
基本文件操作
open()用于打开或创建文件
close()用于关闭被打开的文件
read()用于从一个指定文件读取指定长度的数据到一个指定的缓冲区
write()用于向一个打开的文件写入数据,写操作是从文件的当前位置开始的
lseek()用于在指定的文件描述符中将文件指针定位到相应的位置
文件描述符
是非负整数
每一个文件描述符会与一个打开文件相对应
Linux文件权限
1-3位代表文件所有者的权限,4-6位代表同组用户的权限,7-9位代表其他用户的权限
类型
r 可读 值为4
w 可写 值为2
x 可执行 值为1
基本文件操作
read()用来从文件描述符fd所指定的文件中读取“count”字节的大小到“buf”所指向的缓冲序列
返回值是实际读取到的字节数
文件锁
包括
建议性锁
要求每个上锁文件的进程都要检查是否有锁存在,并且尊重已有的锁
强制性锁
由内核执行的锁,当一个文件被上锁进行写入操作时,内核将阻止其他任何文件对其进行读写操作
上锁的函数
lockf()
用于对文件施加建议性锁
fcntl()
不仅可以施加建议性锁,还可以施加强制性锁
还能对文件的某一记录上锁,也就是记录锁
功能
当一个进程正在读或者修改文件的某一部分时,它可以阻止其他进程修改同一文件区
分类
读取锁
又称共享锁,能够使多个进程都能在文件的同一部分建立读取锁
写入锁
又称排斥锁,在任何时刻只能有一个进程在文件的某个部分上建立写入锁
第三章
I/O处理模型
区别
信号驱动I/O是由内核通知我们何时可以启动一个I/O操作
异步I/O模型是由内核通知进程I/O操作何时完成
进程
区别
程序:
静态的,存放在磁盘上的可执行文件
一些指令的有序集合
进程:
动态的,运行在内存中的程序的执行实例
程序的一次执行过程
进程的状态是变化的,包括进程的创建、调度和消亡
进程状态
就绪态
进程已经具备执行的一切条件,正在等待分配CPU的处理时间
执行态
该进程正在占用CPU运行
等待态
该进程因不具备某些执行条件而暂时无法继续执行的状态
并发处理
多个线程在单个核心运行,同一时间一个线程运行,系统不停的切换线程
(轮转)
线程与进程
关系
一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程
资源分配给进程,同一进程内的所有线程共享该进程的所有资源
线程在执行过程中需要协作同步。不同进程中的线程之间要利用消息通信的方法实现同步
真正在处理机上运行的是线程
线程是进程的一个执行单元,也是进程内的可调用实体
区别
线程共享内存空间,进程的内存是独立的
内存空间
同一个进程的线程之间可以直接交流;两个进程想通信,必须通过其中一个代理来实现
交流
创建新线程很简单,创建新进程需要对其父进程进行一个克隆
创建
一个线程可以控制和操作同一进程里的其他线程,但是进程只能操作子进程
控制
改变主线程(如优先权),可能会影响其他线程;改变父进程,不影响子进程
连坐
线程作为分配和调度的基本单位,进程作为拥有资源的基本单位
调度
进程号
进程号(PID)
标识进程的一个非负整型数
父进程号(PPID)
任何进程(除init进程)都是由另一个进程创建,该进程称为被创建进程的父进程
进程组号(PGID)
进程组是一个或多个进程的集合
默认的情况下,当前的进程号会当做当前的进程组号
函数
exit()和_exit()函数区别
所包含的头文件不一样
exit()属于标准库函数;_exit()属于系统调用函数
其他类型进程
僵尸进程
什么是:
一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中
危害
僵尸进程虽然不占有任何内存空间,但如果父进程不调用wait()或waitpid()的话,那么保留的信息就不会释放,其进程号就会一直被占用。
而系统所能使用的进程号是有限的,如果大量的产生僵尸进程,将因为没有可用的进程号而导致系统不能产生新的进程
孤儿进程
什么是:
父进程运行结束,但子进程还在运行(未运行结束)的子进程就称为孤儿进程
没有什么危害
每当出现一个孤儿进程时,内核就把孤儿进程的父进程设置为init,而init进程会循环地wait()它的已经退出的子进程
注:
如果是64位系统,孤儿进程的父进程号并不是1号
进程间通信
信号量
信号周期
包括
信号的产生
信号在进程中的注册、注销
执行信号处理函数
信号的产生
键盘
ctrl+c
SIGINT
ctrl+\
SIGQUIT
ctrl+z
SIGSTOP
信号的类型
不可靠信号(非实时)
编号为1-31
可靠信号(实时)
编号为32-64
区别
不可靠信号不支持排队,可能会造成信号丢失,可靠信号不会
不可靠信号一般都有确定的用途和意义,可靠信号则可以让用户自定义使用
信号的常用操作
处理信号:sighandler_t signal(int signum, sighandler_t handler);
signum——信号的编号,指明了要处理的信号类型
handler——表示我们要对信号进行的处理方式
管道
有名管道
又称命名管道,可以在任意两个进程之间进行通信
无名管道
只能在父子进程之间通信
消息队列
键(key)值
系统建立IPC通讯(如消息队列、共享内存时)必须指定一个ID值
创建
int msgget(key_t key, int msgflg);
创建一个新的或打开一个已经存在的消息队列。不同的进城调用此函数,只要用相同的key值就能得到同一个消息队列的标识符
共享内存
应用
创建共享内存区域
映射共享内存
访问共享内存
特点
共享内存是进程间共享数据的一种最快的方法
一个进程向共享的内存区域写入了数据,共享这个内存区域的所有进程就可以立刻看到其中的内容
使用共享内存要注意的是多个进程之间对一个给定存储区访问的互斥
若一个进程正在向共享内存区写数据,则在他做完这一步操作前,别的进程不应当去读、写这些数据
套接字
总结
简要分析在linux下实现进程通信的几种方式及其各自特点:
匿名管道
具有亲缘关系的进程间,半双工,数据在内存中
有名管道
可用于任意进程中,双工,有文件名,数据在内存中
信号
唯一的异步通信方式
信号量
用于解决进程间的同步与互斥问题的一种进程间通信机制
共享内存
效率最高(直接访问内存),需要同步、互斥机制
消息队列
常用于cs模式中,按消息类型访问,可有优先级,无须同步机制
总结
第四章
线程池
一种并发编程中常用的技术,用于管理和重用线程
由线程池管理器、工作队列和线程池线程组成
基本概念
在应用程序启动时创建一定数量的线程,并将他们保存在线程池中
当需要执行任务时,从线程池中获取一个空闲的线程,将任务分配给该线程执行
当任务执行完毕后,线程将返回到线程池,可以被其他任务复用
进程间相互关系
互斥
竞争同一资源而发生相互制约
即多个进程由于共享了独占性资源,必须协调各进程对资源的存取顺序,确保没有任何两个或以上的进程同时进行存取操作
互斥和资源共享相关
同步
协同完成一项任务
进程同步就是指协调这些完成某个共同任务的并发线程,在某些位置上指定线程的先后执行次序、传递信号或消息
通信
交互信息
进程同步互斥机制
信号量
PV操作
P-1;V+1
互斥锁
操作流程
在访问共享资源后临界区域前,对互斥锁进行加锁
在访问完成后释放互斥锁导上的锁
对互斥锁进行加锁后,任何其他试图再次对互斥锁加锁的线程将被阻塞,直到锁被释放
网络编程概述
TCP
传输控制协议
面向连接(三次握手建立连接)
提供可靠的通信服务
传送的数据无差错、不丢失、不重复、按序到达
面向字节流
只能是点到点的
首部开销20字节
全双工的可靠信道
UDP
用户数据报协议
无连接
无需进行握手和建立连接的过程
不保证数据传输的可靠性,但能够提供低延迟的传输服务
面向报文的,没有拥塞控制
支持一对一,一对多,多对一和多对多
首部开销8字节
不可靠信道
socket编程步骤
创建套接字——socket()
为套接字添加信息(IP地址和端口号)——bind()
监听网络连接——listen()
监听到有客户端接入,接受一个连接——accept()
数据交互
关闭套接字,断开连接