kernel编译与源码阅读配置

作为一个软件开发者都有一个想了解我们程序运行基础内核的想法,今天无意间又打开了kernel的页面,那就编一个学习下吧。

官网的下载速度比较慢,国内有很多的mirrors站点,这里我用的是网易的加速,下载的是5.6.15的版本。

编译

下载后解压缩,我本机是ubuntu 18.04,开始编译之前要配置下内核的编译参数,这里我们采用简单的界面配置方式,运行make menuconfig打开图形配置界面,按照自己需求配置内核并保存配置。接下来就可以执行make命令进行编译了,由于内核文件实在太多了,这里我们可以采用并行编译的方式,执行make -j8开启8个并行任务,这时你可以选择去喝杯咖啡了,或者开始我们的vscode源码阅读之旅。

vscode 配置

这里vscode需要安装c/c++插件,安装完插件需要配置下.vscode/c_cpp_properties.json文件,包含includePathcStandard,我的配置如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/arch/arm64/include/**",
"${workspaceFolder}/include/**",
"${workspaceFolder}/include/linux/**",
"${workspaceFolder}/arch/arm64/**",
"${workspaceFolder}/**"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
"cStandard": "c89",
"cppStandard": "c++17",
"intelliSenseMode": "clang-x64"
}
],
"version": 4
}

接下来就可以开启我们苦逼的源码阅读之旅了。

istio 初体验

前面我们介绍了在本地安装k8s的方式,今天我们就体验下Mesh带给我们的刺激吧。
这里我使用之前创建好的minikube集群,首先需要安装我们的istioctl工具,参考官网命令如下

将需要的工具和一些示例文件下载到本地

1
curl -L https://istio.io/downloadIstio | sh -

进入下载的目录,这里我的版本是1.4.0

1
cd istio-1.4.0

你会看到几个文件夹,bin这里放着我们的istioctl工具,需要将工具移动到bin目录;install文件夹存放这我们的安装yaml文件;samples存放的是一下示例程序,供我们学习使用。

安装istio,istio有几个默认的配置文件组合,这里我们学习使用,就选择一个功能比较多的demo模式,其他模式参照,自定义配置参照.

1
istioctl manifest apply --set profile=demo

到此,整个安装就结束了。这时要下载一些镜像,就看大家网速了。

minikube 安装

在本地环境学习k8s的首选方案,个人还是推荐官方的minikube的方案,使用中和集群模式基本一致,下面就开始我们的k8s之旅吧。

安装kubectl

1
2
3
4
5
curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.16.0/bin/linux/amd64/kubectl

chmod +x ./kubectl

sudo mv ./kubectl /usr/local/bin/kubectl

安装minikube

1
2
3
4
curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 \
&& chmod +x minikube

sudo install minikube /usr/local/bin/

因为我的本机支持docker,这里我就不使用虚拟机安装k8s了,如果你的机器不支持docker,可以在安装时选用支持docker的driver,需要增加--vm-driver参数即可。另外k8s的镜像在国外被墙,这里我们使用--image-repository参数替换为国内的仓库,另外推荐加上仓库加速器--registry-mirror,这样最终的启动脚本就变为了如下:

1
minikube start --vm-driver=none --registry-mirror=https://registry.docker-cn.com --image-repository=registry.cn-hangzhou.aliyuncs.com/google_containers

只需要静静的等待完成即可,到此就完成了我们整个的安装,开始我们的探索之旅吧。

对了,不要忘记验证一下pod的启动情况,方式如下:

1
sudo kubectl get all -A

NetworkManager介绍

介绍

NetworkManager是一个程序,用于为系统自动提供检测和配置以自动连接到网络。NetworkManager的功能对于无线和有线网络都非常有用。对于无线网络,NetworkManager首选已知的无线网络,并且能够切换到最可靠的网络。支持NetworkManager的应用程序可以从联机和脱机模式切换。与无线连接相比NetworkManager更喜欢有线连接,它支持调制解调器连接和某些类型的VPN。NetworkManager最初是由Red Hat开发的,现在由GNOME项目托管。

在linux中默认以systemd的形式运行,可以执行一下命令查看信息:

1
2
3
4
5
6
7
8
9
10
11
# systemctl  status network-manager.service
输出类似以下信息:
● NetworkManager.service - Network Manager
Loaded: loaded (/lib/systemd/system/NetworkManager.service; enabled; vendor preset: enabled)
Active: active (running) since Sun 2019-10-13 19:38:49 CST; 1h 21min ago
Docs: man:NetworkManager(8)
Main PID: 862 (NetworkManager)
Tasks: 4 (limit: 4915)
CGroup: /system.slice/NetworkManager.service
├─ 862 /usr/sbin/NetworkManager --no-daemon
└─1930 /sbin/dhclient -d -q -sf /usr/lib/NetworkManager/nm-dhcp-helper -pf /run/dhclient-wlp3s0.pid -lf /var/lib/NetworkManager/dhclient-9ec39b13-6d0c-468c-9a5b-fc4a2a6ea85e-wlp3s0.lease -cf /var/lib/NetworkManager/dhclient-wlp3s0.conf wlp3s0

NetworkManager分为两个程序,一个/usr/sbin/NetworkManager的服务端,一个/sbin/dhclient客户端。

NetworkManager的配置工具有多种形式,如下:

  1. nmcli:命令行。这是最常用的工具。
  2. nmtui:在shell终端开启文本图形界面。
  3. nm-applet:GUI界面配置工具。
1
2
3
4
5
nm                                           (Executable link, 43kB)  nmtui           (Text User Interface for controlling NetworkManager)
nm-applet (Network monitor and control GUI applet) nmtui-connect (Text User Interface for controlling NetworkManager)
nm-connection-editor (Network connection editor for NetworkManager) nmtui-edit (Text User Interface for controlling NetworkManager)
nm-online (Ask NetworkManager whether the network is connected) nmtui-hostname (Text User Interface for controlling NetworkManager)
nmcli (Command-line tool for controlling NetworkManager)

nmcli使用方法

nmcli使用方法非常类似linux ip命令、cisco交换机命令,并且支持tab补全,也可在命令最后通过-h、–help、help查看帮助。在nmcli中有2个命令最为常用:

nmcli connection

译作连接,可理解为配置文件,相当于ifcfg-ethX。可以简写为nmcli c
connection有2种状态:
▷ 活跃(带颜色字体):表示当前该connection生效
▷ 非活跃(正常字体):表示当前该connection不生效

nmcli device

译作设备,可理解为实际存在的网卡(包括物理网卡和虚拟网卡)。可以简写为nmcli d
device有4种常见状态:
▷ connected:已被NM纳管,并且当前有活跃的connection
▷ disconnected:已被NM纳管,但是当前没有活跃的connection
▷ unmanaged:未被NM纳管
▷ unavailable:不可用,NM无法纳管,通常出现于网卡link为down的时候(比如ip link set ethX down)

常用命令

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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# 查看ip(类似于ifconfig、ip addr)
nmcli
# 创建connection,配置静态ip(等同于配置ifcfg,其中BOOTPROTO=none,并ifup启动)
nmcli c add type ethernet con-name ethX ifname ethX ipv4.addr 192.168.1.100/24 ipv4.gateway 192.168.1.1 ipv4.method manual
# 创建connection,配置动态ip(等同于配置ifcfg,其中BOOTPROTO=dhcp,并ifup启动)
nmcli c add type ethernet con-name ethX ifname ethX ipv4.method auto
# 修改ip(非交互式)
nmcli c modify ethX ipv4.addr '192.168.1.200/24'
nmcli c up ethX
# 修改ip(交互式)
nmcli c edit ethX
nmcli> goto ipv4.addresses
nmcli ipv4.addresses> change
Edit 'addresses' value: 192.168.1.200/24
Do you also want to set 'ipv4.method' to 'manual'? [yes]: yes
nmcli ipv4> save
nmcli ipv4> activate
nmcli ipv4> quit
# 启用connection(相当于ifup)
nmcli c up ethX
# 停止connection(相当于ifdown)
nmcli c down
# 删除connection(类似于ifdown并删除ifcfg)
nmcli c delete ethX
# 查看connection列表
nmcli c show
# 查看connection详细信息
nmcli c show ethX
# 重载所有ifcfg或route到connection(不会立即生效)
nmcli c reload
# 重载指定ifcfg或route到connection(不会立即生效)
nmcli c load /etc/sysconfig/network-scripts/ifcfg-ethX
nmcli c load /etc/sysconfig/network-scripts/route-ethX
# 立即生效connection,有3种方法
nmcli c up ethX
nmcli d reapply ethX
nmcli d connect ethX
# 查看device列表
nmcli d
# 查看所有device详细信息
nmcli d show
# 查看指定device的详细信息
nmcli d show ethX
# 激活网卡
nmcli d connect ethX
# 关闭无线网络(NM默认启用无线网络)
nmcli r all off
# 查看NM纳管状态
nmcli n
# 开启NM纳管
nmcli n on
# 关闭NM纳管(谨慎执行)
nmcli n off
# 监听事件
nmcli m
# 查看NM本身状态
nmcli
# 检测NM是否在线可用
nm-online

例子:创建一个连接(connection)

1
nmcli c add type ethernet con-name ethX-test ifname ethX ipv4.addresses '192.168.1.100/24,92.168.1.101/32' ipv4.routes '10.0.0.0/8 192.168.1.10,192.168.0.0/16 192.168.1.11' ipv4.gateway 192.168.1.254 ipv4.dns '8.8.8.8,4.4.4.4' ipv4.method manual

▪ type ethernet:创建连接时候必须指定类型,类型有很多,可以通过 nmcli c add type-h看到,这里指定为ethernet。
▪ con-name ethX ifname ethX:第一个ethX表示连接(connection)的名字,这个名字可以任意定义,无需和网卡名相同;第二个ethX表示网卡名,这个ethX必须是在 nmcli d里能看到的。
▪ ipv4.addresses ‘192.168.1.100/24,192.168.1.101/32’:配置2个ip地址,分别为192.168.1.100/24和192.168.1.101/32
▪ ipv4.gateway 192.168.1.254:网关为192.168.1.254
▪ ipv4.dns ‘8.8.8.8,4.4.4.4’:dns为8.8.8.8和4.4.4.4
▪ ipv4.method manual:配置静态IP

参考资料

  1. 基于RHEL8/CentOS8的网络IP配置详解
  2. Arch NetworkManager
  3. gnome NetworkManager/

ubuntu 18.04中vscode字体突然变丑了

背景

作为一个程序员,自己一直使用的环境是Ubuntu+vscode进行开发,最近一次系统更新,vscode的编辑器和shell的字体都变的异常难看起来,字间距变长了,而且还有点倾斜。这种情况估计是字体设置出现了问题,那我们就修改下吧。

行动

这里引用Bluestorm的推荐Ubuntu中vscode的字体设置推荐,下面几种好看点的字体:

  1. Courier New
  2. Source Code Pro
  3. WenQuanYi Micro Hei
  4. WenQuanYi Micro Hei Mono
  5. Ubuntu
  6. Droid Sans Mono

我们可以打开vscode的字体设置填入相应喜欢的字体就可以了。

查看系统中安装了的字体方法,如下:

1
2
fc-list 查看所有的字体
fc-list :lang=zh 查看所有的中文字体

rancheros

Launching RancherOS using Docker Machine

Before moving forward, you’ll need to have Docker Machine and VirtualBox installed. Once you have VirtualBox and Docker Machine installed, it’s just one command to get RancherOS running.

1
2
3
4
docker-machine create -d virtualbox \
--virtualbox-boot2docker-url https://releases.rancher.com/os/latest/rancheros.iso \
--virtualbox-memory 2048 \
<MACHINE-NAME>

That’s it! You’re up and running a RancherOS instance.
To log into the instance, just use the docker-machine command.

ssh 登录

1
docker-machine ssh <MACHINE-NAME>

切换docker镜像

1
2
3
4
5
6
7
sudo ros c set  rancher.bootstrap_docker.registry_mirror  https://registry.docker-cn.com

sudo ros c set rancher.system_docker.registry_mirror https://registry.docker-cn.com

sudo ros c set rancher.docker.registry_mirror https://registry.docker-cn.com

sudo ros c set rancher.defaults.registry_mirror https://registry.docker-cn.com

重启已加载配置

1
sudo reboot

切换为Ubuntu

1
2
sudo ros console switch ubuntu
sudo ros engine switch docker-17.03.2-ce

替换源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse

deb-src http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse

deb http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse

deb-src http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse

deb http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse

deb-src http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse

deb http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse

deb-src http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse

deb http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse

deb-src http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse

AutoScalingWorker

介绍

传统基于channel的生产者与消费者模式,采用固定消费者个数形式,在面对生产数量猛增情况时,不能做到动态伸缩,容易致使队列积压。基于此 autoscalingworker 采用检测队列积压情况动态创建与销毁worker,来保证消费与避免性能的浪费。

探索

首先我们需要定义我们Worker的上下限,基于多少队列积压情况进行扩容与缩容。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
type AutoScalingWorker struct {
MinWorker int
MaxWorker int
QueueDepth int
CurrentWorker int
Process Process
Queue chan interface{}
Interval time.Duration

stop chan int
workerStop chan int
lock sync.RWMutex
}

有了这些后,我们要做的就是循环检查我们的队列进行扩容与缩容了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
func (auto *AutoScalingWorker) Start() {
auto.workerStop = make(chan int)
auto.stop = make(chan int)

t := time.NewTicker(auto.Interval)
for {
select {
case <-t.C:
if len(auto.Queue) > auto.QueueDepth {
auto.Expansion()
} else {
auto.Shrinkage()
}
case <-auto.stop:
return
}
}
}

在golang中对worker进行扩容很简单,只需使用关键子go就可以了,但是对以运行的goroutines 并没有kill办法,如果让其退出,只能等待起运行结束。此时,我们就需要借用golang中的另一神器channel了,将我们的close信号传递进goroutines中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
func (auto *AutoScalingWorker) job() {
auto.lock.Lock()
auto.CurrentWorker = auto.CurrentWorker + 1
auto.lock.Unlock()
for {
select {
case <-auto.workerStop:
goto close

case data, ok := <-auto.Queue:
if !ok {
goto close
}
auto.Process(data)
}
}

close:
auto.lock.Lock()
auto.CurrentWorker = auto.CurrentWorker - 1
auto.lock.Unlock()
}

这样大体结构就完成了,我们使用起来就像这样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
   c := make(chan interface{}, 1000)

auto := worker.AutoScalingWorker{
MinWorker: 0,
MaxWorker: 10,
QueueDepth: 8,
Interval: time.Second,
Process: func(i interface{}) {
time.Sleep(time.Millisecond * 100)
},
Queue: c,
}

go auto.Start()

输出结果如下,auto worker 表示当前运行的worker,QueueDepth 表示队列中积压的消息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
auto worker: 0  QueueDepth: 60
auto worker: 2 QueueDepth: 79
auto worker: 3 QueueDepth: 89
auto worker: 4 QueueDepth: 89
auto worker: 5 QueueDepth: 49
auto worker: 5 QueueDepth: 0
auto worker: 3 QueueDepth: 0
auto worker: 2 QueueDepth: 0
auto worker: 1 QueueDepth: 0
auto worker: 0 QueueDepth: 150
auto worker: 1 QueueDepth: 149
auto worker: 2 QueueDepth: 138
auto worker: 3 QueueDepth: 118
auto worker: 4 QueueDepth: 88
auto worker: 5 QueueDepth: 48
auto worker: 4 QueueDepth: 0
auto worker: 3 QueueDepth: 0
auto worker: 2 QueueDepth: 0
auto worker: 1 QueueDepth: 0
auto worker: 0 QueueDepth: 0

完成代码示例请查看这里

关于MySql区分大小写

方式一

mysql大小写敏感配置相关的两个参数,lower_case_file_system 和 lower_case_table_names。

查看当前mysql的大小写敏感配置

1
show global variables like '%lower_case%';

Variable_name Value
lower_case_file_system ON
lower_case_table_names 0

lower_case_file_system 表示当前系统文件是否大小写敏感,只读参数,无法修改。

  • ON 大小写不敏感
  • OFF 大小写敏感

lower_case_table_names 表示表名是否大小写敏感,可以修改。

  • lower_case_table_names = 0时,mysql会根据表名直接操作,大小写敏感。
  • lower_case_table_names = 1时,mysql会先把表名转为小写,再执行操作。

设置lower_case_table_names的值,打开my.cnf文件,加入以下语句后重启。

1
lower_case_table_names = 0 或 lower_case_table_names = 1

方式二

mysql中varchar类型的字符集一般设置成utf8,然而mysql默认是对大小写不敏感(不区分),如果想要mysql区分大小写需要设置排序规则,规则详解如下:

  1. utf8_bin将字符串中的每一个字符用二进制数据存储,区分大小写。
  2. utf8_genera_ci不区分大小写,ci为case insensitive的缩写,即大小写不敏感。
  3. utf8_general_cs区分大小写,cs为case sensitive的缩写,即大小写敏感。

用utf8_genera_ci没有区分大小写,导致这个字段的内容区分大小写时出问题,比如作为区分大小写的code或者验证码时就出问题了。
utf8_general_cs这个选项一般没有,所以只能用utf8_bin区分大小写

方式三

mysql在查询时显示声明排序规则

1
2
3
SELECT * FROM case_test WHERE word LIKE COLLATE atin1_bin 'F%'
# or
SELECT * FROM case_test WHERE word LIKE 'F%' COLLATE latin1_bin;

方式四

mysql查询区分大小写也可以:

1
select  * from  table_name where  binary  a like  'a%'

也可以在建表时,加以标识

1
2
3
create  table  table_name(
a varchar (20) binary
)