IPv4
使用32位地址,地址范围0.0.0.0到255.255.255.255。
IPv6
使用128位地址
私有IP地址
私有IP地址用于局域网(LAN)内部,不在互联网中传输。常见的私有IP地址范围有:
- 10.0.0.0 ~ 10.255.255.255
- 172.16.0.0~172.31.255.255
- 192.168.0.0 ~ 192.168.255.255
公有IP地址
公有IP地址由互联网服务提供商(ISP)分配,可以在全球互联网中唯一识别。
静态IP地址
静态IP地址是手动分配的,不会改变。适用于需要长期保持相同IP地址的设备,如服务器。
动态IP地址
动态IP地址由DHCP服务器动态分配,每次连接网络时可能会关闭。
路由器
路由器是一种网络设备,用于在计算机网络之间转发数据包。它主要用于连接不同的网络,并确定数据包的最佳路径。路由器通过分析数据包的目标地址,选择最有效的路由路径,将数据包传输到目的地。
应用层——DNS协议
- 用户请求:用户在浏览器中输入一个域名www.baidu.com
- 本地缓存检查:客户端首先检查本地缓存中是否有该域名的IP地址。如果有,直接返回结果,如果没有,继续下一步。
- 递归查询
- 查询本地DNS服务器:客户端向本地DNS服务器发送递归查询请求。
- 查询根域名服务器:本地DNS服务器向根域名服务器查询。根域名服务器返回顶级域名服务器的地址。
- 查询顶级域名服务器:本地DNS服务器向顶级域名服务器查询,顶级域名服务器返回权威DNS服务器的地址。
- 查询权威DNS服务器:本地DNS服务器向权威DNS服务器,权威DNS服务器返回目标IP地址。
- 返回结果:本地DNS服务器将获得的IP地址返回给客户端。
- 访问目标网站:客户端使用获得的IP地址访问目标网站。
数据链路层
在两个网络实体之间提供数据链路连接的建立、维持和释放管理。
构成数据链路数据单元(frame:数据帧),并对帧定界、同步、收发顺序控制。包括传输过程中的网络流量控制、差错检测和差错控制等方面。
只提供导线的一端到另一端的数据传输。
MAC地址
每个设备在全球范围内都应该具有一个唯一的MAC地址。
MAC地址工作在数据链路层,用于设备间通信。
ARP协议
地址解析协议,用于将IP地址转换为物理MAC地址。
这个转换过程在局域网内是必须的,因为以太网帧是通过MAC地址传输的,而网络层数据包使用IP地址。
交换机工作在数据链路层。
守护进程
守护进程是在操作系统后台运行的一种特殊类型的进程,它独立于前台用户界面,不与任何终端设备直接关联。这些进程通常在系统启动时启动,并持续运行直到系统关闭,或者它们完成其任务自行终止。
守护进程通常用于服务请求、管理系统或执行周期性任务。
控制终端
控制终端是与会话关联的终端设备,它是用户输入和输出的通道。进程通常通过其控制终端与用户交互,接收输入和用户显示输出。
对于守护进程来说,它必须从任何控制终端中脱离,确保其独立于任何用户会话在后台运行,这样才能保证其稳定性和安全性,不受用户直接控制和会话结束的影响。
- 创建子进程并结束父进程,让其变成孤儿进程,否则父进程结束其子进程也会结束。
- 设置会话ID:setsid()创建一个新会话,并使调用它的进程成为新会话的领导者,这样做的目的是让守护进程摆脱原来的控制终端。这样守护进程就不会接收到终端发出的任何信号,例如挂断信号(SIGHUP),从而保证其运行不受前台用户操作影响。
- 第二次fork():使得守护进程不是会话领导,没有获取控制终端的能力,避免意外获取控制终端。
- 更改工作目录:将工作目录更改到根目录/,主要是为了避免守护进程占用其启动时的文件系统,这对于可移动的或网络挂载的文件系统很重要,确保这些文件系统不需要时可以卸载掉。
- 重设文件权限掩码:调用umask(0)确保守护进程创建的文件权限不会受继承的umask的值的影响,守护进程可以精确控制器创建的文件和目录的权限。
- 关闭文件描述符:守护进程不需要标准输入、输出和错误文件描述符,因为它们不与终端交互。关闭这些不需要的文件描述符可以避免资源泄露,提高守护进程的安全性和效率。
- 处理信号:SIGHUP:虽然守护进程和终端断开,但仍然有可能收到其它进程或内核发来的SIGHUP信号,守护进程不应该因为它而终止。
- SIGTERM:SIGTERM信号是终止信号,用于请求守护进程优雅地终止。通过命令行kill 命令可以发送SIGTERM信号,接收到这个信号之后,守护进程终止子进程,并清理回收资源,最后退出。
- 执行具体任务。比如说监听网络请求、定期清理文件系统、执行系统备份等。
I/O多路复用
I/O多路复用是Linux中用于处理多个I/O操作的机制,使得单个线程或进程可以同时监视多个文件描述符,以处理多路I/O请求。
主要通过select、poll和epoll。
作用和意义
- 节省资源:I/O多路复用允许单个线程或进程同时监视多个文件描述符,而不是为每个I/O操作创建一个线程或进程。只需要维护文件描述符,极大节约了资源,减少了系统开销。
- 效率高:使用IO多路复用省去了进程或线程上下文切换的开销,提升了处理效率,减少了系统资源的消耗(如内存和CPU时间),从而提高了应用程序的整体性能和响应速度。
- 简化编程模型:尽管IO多路复用增加了代码的复杂性,但它简化了高并发程序的设计,使得程序员可以更容易地管理多个I/O操作,而不必处理大量的线程同步问题。
select和poll底层都是基于线性结构实现的,需要对文件描述符集执行多次遍历和拷贝,效率底下,而epoll底层是基于红黑树(一种平衡二叉树)实现的,且通过维护就绪事件链表,效率更高。
在epoll的使用中,有两种事件触发模式:边缘触发和水平触发,这两种模式决定了epoll如何通知应用程序有事件发生。
水平触发是epoll的默认模式。在这种模式下,只要文件描述符上有未处理的事件,epoll就会不断通知应用程序。
边缘触发模式,当文件描述符从未就绪状态变为就绪状态时,epoll会通知应用程序。如果应用程序没有在通知后及时处理事件(例如,读出所有可读的数据),epoll不会再次通知,除非文件描述符再次从未就绪变为就绪状态。即在状态变化时通知一次。
传感器驱动框架
现在,为物联网开发的 Sensor 已经很多了,有加速度计(Accelerometer),磁力计(Magnetometer),陀螺仪(Gyroscope),光感计(Ambient light sensor),接近光(Proximity),气压计(Barometer/pressure),湿度计(Humidometer)等等。
这些传感器,世界上的各大半导体厂商都有出产,虽然增加了市场的可选择性,同时也加了应用程序开发难度。
因为不同的传感器厂商,不同的传感器都需要配套自己独有的驱动才能运转起来。这样在开发应用程序的时候就需要针对不同的传感器做适配,自然加大了开发难度。为了降低应用开发的难度,增加传感器驱动的可复用性,RTT设计了 Sensor 驱动框架。
Sensor驱动框架的作用:为上层提供统一的操作接口,提供上层代码的可重用性;简化底层驱动开发的难度,只需要实现简单的ops就可以将传感器注册到系统上。
上层提供的是标准device接口open/close/read/write/control,为底层驱动提供的是简单的ops接口:fetch_data/control,并且框架支持模块,为底层存在耦合的传感器设备提供服务。
Sensor设备其实是对标准设备rt_device的一个丰富,是在原有标准设备的基础上增加Sensor自己独有的一部分属性和控制命令。
整个 Sensor 设备包括两个部分:
- 集成自标准设备的一些特性,包括:标准的控制接口、回调函数。device_id。
- Sensor设备独有的部分,包括Sensor的类型、相关信息,特有控制命令,ops以及一些数据结构。
struct rt_sensor_device
{
struct rt_device parent; /* The standard device */
struct rt_sensor_info info; /* The sensor info data */
struct rt_sensor_config config; /* The sensor config data */
void *data_buf; /* The buf of the data received */
rt_size_t data_len; /* The size of the data received */
const struct rt_sensor_ops *ops; /* The sensor ops */
struct rt_sensor_module *module; /* The sensor module */
rt_err_t (*irq_handle)(rt_sensor_t sensor); /* Called when an interrupt is generated, registered by the driver */
};
typedef struct rt_sensor_device *rt_sensor_t;
sensor_info在传感器设备注册的时候提供,在使用过程中不应该修改。
struct rt_sensor_info
{
rt_uint8_t type; /* The sensor type */
rt_uint8_t vendor; /* Vendor of sensors */
const char *model; /* model name of sensor */
rt_uint8_t unit; /* unit of measurement */
rt_uint8_t intf_type; /* Communication interface type */
rt_int32_t range_max; /* maximum range of this sensor's value. unit is 'unit' */
rt_int32_t range_min; /* minimum range of this sensor's value. unit is 'unit' */
rt_uint32_t period_min; /* Minimum measurement period,unit:ms. zero = not a constant rate */
rt_uint8_t fifo_max; /* Maximum depth of fifo */
};
Sensor的类型有几种,如果有新的传感器类型,可以提PR添加上:
#define RT_SENSOR_CLASS_ACCE (1) /* Accelerometer */
#define RT_SENSOR_CLASS_GYRO (2) /* Gyroscope */
#define RT_SENSOR_CLASS_MAG (3) /* Magnetometer */
#define RT_SENSOR_CLASS_TEMP (4) /* Temperature */
#define RT_SENSOR_CLASS_HUMI (5) /* Relative Humidity */
#define RT_SENSOR_CLASS_BARO (6) /* Barometer */
#define RT_SENSOR_CLASS_LIGHT (7) /* Ambient light */
#define RT_SENSOR_CLASS_PROXIMITY (8) /* Proximity */
#define RT_SENSOR_CLASS_HR (9) /* Heart Rate */
#define RT_SENSOR_CLASS_TVOC (10) /* TVOC Level */
#define RT_SENSOR_CLASS_NOISE (11) /* Noise Loudness */
#define RT_SENSOR_CLASS_STEP (12) /* Step sensor */
#define RT_SENSOR_CLASS_FORCE (13) /* Force sensor */
其他的几个成员,分别是厂商、model(如:“mpu6050”)、传感器数据的单位、通信接口类型、测量的最大范围、测量的最小范围、最小测量周期、硬件 FIFO 的最大深度。