什么是netlink?

netlink提供的是内核态和用户态之间的通信机制,也可以用于用户态和用户态的两个进程之间通信。

netlink的优势

一般的用户态和内核空间通信方式有三种,ioctl,proc,netlink。而前两种都是单向的,而netlink可以实现双向通信。基于BSD socket和AF_NETLINK协议簇。使用32位的端口号寻址。每个netlink协议,通常与一个或者一组内核服务/组件相关联。NETLINK_ROUTE用于获取和设置路由与链路信息、NETLINK_KOBJECT_UEVENT用于内核向用户空间的udev进程发送通知等。

netlink的特点

  • 支持全双工,异步通信
  • 在内核空间使用专门的内核api接口
  • 支持多播,可以实现总线式订阅
  • 在内核端可以用于进程上下文和中断上下文
  • 用户空间使用标准BSD Socket接口

关键数据结构

image-20240805200041276

msghdr

我们知道socket消息的发送和接收函数一般有这几对:recv/send、readv/writev、recvfrom/sendto。当然还有recvmsg/sendmsg,前面三对函数各有各的特点功能,而recvmsg/sendmsg就是要囊括前面三对的所有功能,当然还有自己特殊的用途。msghdr的前两个成员就是为了满足recvfrom/sendto的功能,中间两个成员msg_iov和msg_iovlen则是为了满足readv/writev的功能,而最后的msg_flags则是为了满足recv/send中flag的功能,剩下的msg_control和msg_controllen则是满足recvmsg/sendmsg特有的功能。

sockaddr_nl

image-20240805200415939

1
2
3
4
5
6
7
struct sockaddr_nl
{
sa_family_t nl_family; /*该字段总是为AF_NETLINK */
unsigned short nl_pad; /* 目前未用到,填充为0*/
__u32 nl_pid; /* process pid */
__u32 nl_groups; /* multicast groups mask */为0代表不希望加入任何多播组
};
struct nlmsghdr

netlink报文消息由头和消息体构成。

1
2
3
4
5
6
7
8
struct nlmsghdr
{
__u32 nlmsg_len; /* Length of message including header */ 整个消息的长度,按字节计算。包括了Netlink消息头本身。
__u16 nlmsg_type; /* Message content */ 消息的类型,数据消息还是控制消息
__u16 nlmsg_flags; /* Additional flags */ 附加的额外信息
__u32 nlmsg_seq; /* Sequence number */
__u32 nlmsg_pid; /* Sending process PID */
};

用户空间使用netlink

1.创建socket
1
2
3
4
int socket(int domain, int type, int protocol)
domain指代地址族,即AF_NETLINK;
套接字类型为SOCK_RAW或SOCK_DGRAM,因为netlink是一个面向数据报的服务;
protocol选择该套接字使用哪种netlink特征。
1
bind(fd, (struct sockaddr*)&, nladdr, sizeof(nladdr));
3.发送netlink消息

为了发送一条netlink消息到内核或者其他的用户空间进程,另外一个struct sockaddr_nl nladdr需要作为目的地址,这和使用sendmsg()发送一个UDP包是一样的。

  • 如果该消息是发送至内核的,那么nl_pid和nl_groups都置为0.
  • 如果消息是发送给另一个进程的单播消息,nl_pid是另外一个进程的pid值而nl_groups为零。
  • 如果消息是发送给一个或多个多播组的多播消息,所有的目的多播组必须bitmask必须or起来从而形成nl_groups域。sendmsg(fd, &, msg, 0);
4.接收netlink消息

一个接收程序必须分配一个足够大的内存用于保存netlink消息头和消息负载。然后其填充struct msghdr msg,再使用标准的recvmsg()函数来接收netlink消息。

当消息被正确的接收之后,nlh应该指向刚刚接收到的netlink消息的头。nladdr应该包含接收消息的目的地址,其中包括了消息发送者的pid和多播组。同时,宏NLMSG_DATA(nlh),定义在netlink.h中,返回一个指向netlink消息负载的指针。调用close(fd)关闭fd描述符所标识的socket;recvmsg(fd, &, msg, 0);

内核空间使用netlink

1
2
3
4
struct sock *netlink_kernel_create(struct net *net,
int unit,unsigned int groups,
void (*input)(struct sk_buff *skb),
struct mutex *cb_mutex,struct module *module);
发送单播信息
1
2
int netlink_unicast(struct sock *ssk, struct sk_buff *skb, u32 pid, int nonblock)
ssk为kernel create返回的socket,skb存放消息,data段指向netlink消息结构,skb控制块保存了消息的地址信息。pid为接收消息的进程信息。nonblock表示是否阻塞。
发送广播信息
1
int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid, u32 group, gfp_t allocation)
1
int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid, u32 group, gfp_t allocation)

设备树

argparse介绍

argparse 模块是 Python 内置的一个用于==命令项选项与参数解析==的模块,argparse 模块可以让人轻松编写用户友好的命令行接口。通过在程序中定义好我们需要的参数,然后 argparse 将会从 sys.argv 解析出这些参数。argparse 模块还会自动生成帮助和使用手册,并在用户给程序传入无效参数时报出错误信息。

官方地址:https://docs.python.org/zh-cn/3/library/argparse.html#argumentparser-objects

使用介绍

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import argparse

# 创建一个解析器。创建argumentparser对象
#大多数对argumentparser构造方法的调用都会使用description=关键词参数。这个参数简要描述
parser = argparse.ArgumentParser(description='test')

# 调用add_argument方法添加参数信息是通过调用add_argument方法完成的。
parser.add_argument('--sparse', action='store_true', default=False, help='GAT with sparse version or not.')
parser.add_argument('--seed', type=int, default=72, help='Random seed.')
parser.add_argument('--epochs', type=int, default=10000, help='Number of epochs to train.')

# 使用parse_args解析添加的参数
args = parser.parse_args()
print(args.sparse)
print(args.seed)
print(args.epochs)

add_argument()

其中,这个方法定义了如何解析命令行参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
ArgumentParser.add_argument(name or flags...[, action][, nargs][, const][, default][, type][, choices][, required][, help][, metavar][, dest])

name or flags:选项字符串的名字或者列表,例如foo或者-f,--foo
avtion:命令行遇到参数时的动作。默认值是store
(action=storce_true命令行遇到参数时的动作,默认是store,只要运行该变量有传参就将该变量设置为true)
store_const:表示赋值为const
append:将遇到的值存储成列表,如果参数重复会保存多个值。
append_const,将参数规范中定义的一个值保存到一个列表;
count,存储遇到的次数;此外,也可以继承 argparse.Action 自定义参数解析;
nargs - 应该读取的命令行参数个数,可以是具体的数字,或者是?号,当不指定值时对于 Positional argument 使用 default,对于 Optional argument 使用 const;或者是 * 号,表示 0 或多个参数;或者是 + 号表示 1 或多个参数。
const - action 和 nargs 所需要的常量值。
default - 不指定参数时的默认值。
type - 命令行参数应该被转换成的类型。
choices - 参数可允许的值的一个容器。
required - 可选参数是否可以省略 (仅针对可选参数)。
help - 参数的帮助信息,当指定为 argparse.SUPPRESS 时表示不显示该参数的帮助信息.
metavar - 在 usage 说明中的参数名称,对于必选参数默认就是参数名称,对于可选参数默认是全大写的参数名称.
dest - 解析后的参数名称,默认情况下,对于可选参数选取最长的名称,中划线转换为下划线.

命令行下单点调试的方式,python -m pdb xxx.py

补充串口库

pyserical库可以非常方便和串口的通讯

官方文档

https://pyserial.readthedocs.io/en/latest/pyserial.html

1
2
3
4
5
6
import serial.tools.list_ports

# 列出当前连接的串口设备
ports_list = list(serial.tools.list_ports.comports())
for comport in ports_list:
print(comport[0], comport[1])

打开串口,参数说明

1
__init__(port=None, baudrate=9600, bytesize=EIGHTBITS, parity=PARITY_NONE, stopbits=STOPBITS_ONE, timeout=None, xonxoff=False, rtscts=False, write_timeout=None, dsrdtr=False, inter_byte_timeout=None, exclusive=None)

bytesize : 数据位,可取值five six seven eight等等

parity : 校验位,可取值none,even,odd,mask,spcae等等。

stop:停止位,one,two,five等等

timeout:超时时间,读超时时间,可取值为 None, 0 或者其他具体数值(支持小数)。当设置为 None 时,表示阻塞式读取,一直读到期望的所有数据才返回;当设置为 0 时,表示非阻塞式读取,无论读取到多少数据都立即返回;当设置为其他数值时,表示设置具体的超时时间(以秒为单位),如果在该时间内没有读取到所有数据,则直接返回

xonxoff:软件流控。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#举例 
import serial.tools.list_ports
s = serial.Serial('COM75', 115200, timeout=0.5)
print(s.isOpen()) # True

#发送数据 发送数据使用write方法,发送的数据只能是byte类型,因此需要对发送的字符串进行编码操作
cmd = 'ifconfig\r\n' # 命令带换行符
length = s.write(cmd.encode('utf-8'))
# 发送字符串
str = "serial"
ser.write(str.encode())
# 发送 bytes
data = [0x55,0xAA,0x5A]
ser.write(data)
# 发送数字
num = 100
ser.write(num.to_bytes(1,"little")) # 长度1,小端模式

#读取数据 可以使用read readall readlines...
#read默认读取一个字节,可以通过传入参数指定每次读取的字节数,返回值bytes类型
#readall读取串口接收的全部数据,返回bytes类型
#readlines读取多行数据,返回list类型,列表元素类型为bytes类型
print(s.read(1024))
s.read()[0] --》 读取一个字节
print(s.readlines())
print(s.readall())

#关闭串口 直接调用close方法即可
s.close()

#其他方法
in_waiting():返回接收缓存中的字节数
flush():等待所有数据写出
flushinput():丢弃接收缓存中的所有数据
flushOutput():终止当前写操作,并丢弃发送缓存中的数据。

备份区域以及RTC介绍

摄影参数介绍

  • 白平衡:通过调整色温尽量保持白色为原本的白色,即平衡白色的颜色。(本质是通过调整色温来调整蓝色/红色的互补色 )(90%的场景可以使用自动白平衡)

    • 白色优先/氛围优先
    • 环境中光源很多的时候,自动白平衡可能效果不好,手动不知道设置什么的时候,设置一下白卡校准。延时拍摄需要手动设置,不然会收到忽然出现物体的影响。RAW格式后期可以无损更改白平衡
  • 色温:颜色的温度,色温越高 颜色越偏蓝,色温约低,颜色越偏红。

  • 色相:后期修改偏色,颜色发绿等等。

  • 对焦:主要依靠镜头来完成。镜头外圈单位为m,内圈单位为inch,AF自动对焦,MF手动对焦 (当环境较暗,色彩很多的时候,自动对焦可能会不准。镜头有最小对焦距离,不得小于此,否则会无法对焦。)

  • AF-S:单次对焦,移动相机对焦距离也不会改变。

  • AF-A:自动检测物体是否移动。

  • AF-C:连续对焦模式。(80%)

  • DMF:自动对焦后,可手动精细对焦调节

  • 广域对焦:屏幕范围内任何都可以对焦

  • 点对焦SML,小中大。自由选择对焦点。

  • 扩展点:点无法对焦的时候在附近找扩展点进行对焦

  • 跟踪对焦:选择对焦区域。对焦点会一直跟着指定物体。

  • AF过渡速度:从一个对焦点移动到另一个对焦点的速度

  • AF转移灵敏度:如果焦点前有物体掠过的时候,是否会快速对焦到物体身上。

  • 测光模式

    • 全局测光:分割画面,单独测光,提高焦点附近权重,计算均值。(90%)
    • 中心测光:对画面中央物体进行测光,比如拍人的时候。
    • 点测光;顾名思义。
  • 曝光补偿:白+黑-,拍摄人物可以适当增加一点曝光补偿。因为人体反射率25%左右。相机自动曝光会拉低曝光值,导致人物偏暗。打开直方图也可以。

  • 光圈:F值。数字越大,光圈越小。

    • 光圈越大,进光亮越多。
    • 光圈越大,虚化越明显,景深越浅。拍摄人物的时候放大光圈,拍摄风景的时候缩小光圈。
  • 快门:单位:s 1/100秒。会计算0.01s的进光量到传感器。

    • 快门速度越慢,进光量越多。
    • 快门速度还会影响拖影。 运动速度较快的设备使用较快的快门速度。轨迹则用慢速快门。
    • 一般可以设置快门速度值比焦段数值更高。
    • 果冻效应:物体运动过快导致每一行图像数据有时间差。导致图片会倾斜。用全域快门来解决。因为全域快门一次读取的是所有的数据。
    • 电子快门,不用机械快门。但是画质会减少,因为cpu还要处理电子快门逻辑。
    • 电子前lian快门。
    • 拍摄视频的时候的快门。和帧数相关。快门速度越快,每一帧记录物体移动时间越少。动态模糊越少。
    • 设置相机的快门速度一般为帧数的2倍数。
  • ISO:ISO越高,画面越亮,噪点越多。增加增益,通电量。一般情况通过光圈和快门来控制曝光,实在没办法了,才会通过ISO提高。增加ISO的时候信噪比会提高。会放大本底噪声。主要是由于进光量不足,被迫只能放大信号,导致噪点被放大变得可见了。

挡位介绍

  • auto:全自动
  • P:程序自动曝光+手动曝光补偿
  • A:光圈优先,相机自动调整快门和ISO。 拍摄人像的时候,大光圈优先
  • S:快门优先挡位,相机自动调整光圈ISO。拍摄运动物体的时候。
  • C1:C2 C3,自定义挡位。

布隆过滤器介绍

基本概念:它实质上是一个很长的二进制向量和一系列随机映射函数 (Hash函数)。

作用:它是一个空间效率高的概率型数据结构,用来告诉你:一个元素一定不存在或者可能存在

优点:

  • 在存储空间和时间都是常数,即hash函数的个数
    
  • Hash 函数相互之间没有关系,方便由硬件并行实现。
    
  • 布隆过滤器不需要存储元素本身,在某些对保密要求非常严格的场合有优势。
    
  • 布隆过滤器可以表示全集,其它任何数据结构都不能。
    

缺点:

  • 有误判率存在
  • 不支持删除

适用场景:

  • 预防缓存穿透:布隆过滤器快速判断数据是否存在,避免通过查询数据库来判断数据是否存在。
  • 网络爬虫:布隆过滤器可以用来去重已经爬取过的URL。
  • 邮箱的垃圾邮件过滤。
  • 黑白名单。

原理

结构

布隆过滤器实现原理就是一个超大位数的数组(BitMap)和多个不同Hash算法函数。与寻常数组不同的是,BitMap一个数组元素占一个bit,这一特性决定了BitMap能够极大地节省空间

image-20240509090000811

添加元素

将要添加的元素分别通过k个哈希函数计算得到k个哈希值,这k个hash值对应位数组上的k个位置,然后将这k个位置设置为1。

image-20240509090026138

当不同元素在计算到相同的值后,依旧保持这一位为1即可。

image-20240509084931019

查询元素

将要查询的元素分别通过k个哈希函数计算得到k个哈希值,这k个hash值对应位数组上的k个位置。如果这k个位置中有一个位置为0,则此元素一定不存在集合中。如果这k个位置全部为1,则这个元素可能存在。

误判

需要注意的是,布隆过滤器无法确定元素存在,只能确定元素不存在。出现的原因是多个输入经过哈希之后在相同的bit位置1了,这样就无法判断究竟是哪个输入产生的,因此误判的根源在于相同的 bit 位被多次映射且置 1。

这种情况也造成了布隆过滤器的删除问题,即布隆过滤器不存在删除操作。因为布隆过滤器的每一个 bit 并不是独占的,很有可能多个元素共享了某一位。如果我们直接删除这一位的话,会影响其他的元素。

应用场景

防止缓存穿透。缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大。使用布隆过滤器能够避免频繁查询不存在的数据,减轻数据库的压力。

业务场景中判断用户是否阅读过某视频或文章,比如抖音或头条,当然会导致一定的误判,但不会让用户看到重复的内容。

gun hash表, 主要是利用 Bloom Filter, 在常量时间内判断, 字符是否存在, 以及对应 .dynsym 的位置. 使用 gcc -g -o hello -Wl,--hash-style=sysv(gnu) hello.c 可以产生旧版本的 hash 表.

名词解释

(1)VCC:C=circuit 表示电路的意思, 即接入电路的电压

(2)VDD:D=device 表示器件的意思, 即器件内部的工作电压;

(3)VSS:S=series 表示公共连接的意思,通常指电路公共接地端电压

(4)VEE:负电压供电;场效应管的源极(S)

(5)VBAT:当使用电池或其他电源连接到VBAT脚上时,当VDD 断电时,可以保存备份寄存器的内容和维持RTC的功能。如果应用中没有使用外部电池,VBAT引脚应接到VDD引脚上。

(6)VPP:编程/擦除电压。

(7)GND:在电路里常被定为电压参考基点。

(8)CC与DD的区别是:供电电压与工作电压的区别(通常VCC>VDD)

(9)V与VA的区别是:数字与模拟的区别

1
2
3
4
- 数字电路供电VCC
- 模拟电路供电VCCA
- VDD是指数字工作电压,就是供电进芯片的
- VDDA是模拟电压或者叫模拟正电源,是从芯片向外供电的

应用解释

1、对于数字电路来说,VCC是电路的供电电压,VDD是芯片的工作电压(通常Vcc>Vdd),VSS是接地点。例如,对于ARM单片机来说,其供电电压VCC一般为5V,一般经过稳压模块将其转换为单片机工作电压VDD = 3.3V

2、有些IC既带VDD引脚又有VCC引脚,说明这种器件自身带有电压转换功能。

3、在场效应管(或COMS器件)中,VDD为漏极,VSS为源极,VDD和VSS指的是元件引脚,而不表示供电电压。

4、一般来说VCC=模拟电源,VDD=数字电源,VSS=数字地,VEE=负电源

5、从电气意义上说,GND分为电源地和信号地。PG是 Power Ground(电源地)的缩写。另一个是 Signal Ground(信号地)。实际上它们可能是连在一起的(不一定是混在一起哦!)。两个名称主要是便于对电路进行分析。

进一步说,还有因电路形式不同而必须区分的两种“地”:数字地,模拟地。

数字地和模拟地都有信号地、电源地两种情况。数字地和模拟地之间,某些电路可以直接连接,有些电路要用电抗器连接,有些电路不可连接。

原码补码反码移码

反码:解决负数加法运算问题,将减法运算转换为加法运算,从而简化运算规则;
补码:解决负数加法运算正负零问题,弥补了反码的不足。

总之,反码与补码都是为了解决负数运算问题,跟正数没关系,因此,不管是正整数还是正小数,原码,反码,补码都全部相同。

总结:

  • 正数的原码、补码、反码均为其本身;
  • 负数(二进制)的原码、补码、反码公式:
    反码 = 原码(除符号位外)每位取反
    补码 = 反码 + 1
    反码 = 补码 - 1
    移码 = 补码符号位取反

计算机可靠性模型

串联系统

系统可靠性image-20240418103809734

系统失效率image-20240418103855822

并联系统

系统可靠性image-20240418103948295

系统失效率image-20240418104000114

hisi常用debug查看

  • hiddrs查看ddr占用
  • cat /dev/logmpp 查看设备mpplog

媒体处理部分

0%