Update
This commit is contained in:
parent
b437ab2b25
commit
9f2ad7386f
Binary file not shown.
After Width: | Height: | Size: 194 KiB |
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 106 KiB |
|
@ -0,0 +1,135 @@
|
|||
---
|
||||
title: 从编译内核开始的内核更新之旅
|
||||
date: 2021-07-03 23:34:27
|
||||
tags:
|
||||
- Ubuntu
|
||||
- Linux
|
||||
- Debootstrap
|
||||
thumbnail: /assets/Tux.png
|
||||
---
|
||||
|
||||
正如你所见的那样, 这是一篇有关于内核 更新/编译 的文章.
|
||||
|
||||
<!--more-->
|
||||
|
||||
> 头图来自 [github:garrett/Tux](https://github.com/garrett/Tux), 使用 CC0 授权.
|
||||
|
||||
{% note info %}
|
||||
|
||||
### 0.0 提示
|
||||
|
||||
该文章还未写完, 写完再说 (
|
||||
|
||||
{% endnote %}
|
||||
|
||||
{% note warning %}
|
||||
|
||||
### 0.1 警告
|
||||
|
||||
本文仅为一篇 ***教程性*** 文章, 将不会讨论有关更深层次的技术问题.
|
||||
若有错误, 欢迎在评论区进行指正或发送邮件至 `i@186526.xyz`.
|
||||
|
||||
{% endnote %}
|
||||
|
||||
## 1.0 获取所需材料
|
||||
|
||||
你可能会需要以下物品来完成你的内核编译.
|
||||
|
||||
1. 一台可用的且运行 GNU/Linux 并有 Root 权限 的设备
|
||||
2. 正常且快速的 Internet 链接
|
||||
3. ~~空调~~ ~~快乐水~~ 正常且可用并且出问题会自己 Google 的大脑
|
||||
|
||||
## 1.1 启动设备
|
||||
|
||||
我们这里使用运行在 FireCracker / KVM 上的 Debian Buster 作为编译设备.
|
||||
为了安全, 我们建议创建
|
||||
|
||||
```bash
|
||||
# 使用 ignite 快速的创建使用 Debian Buster 的 FireCracker 系统容器.
|
||||
|
||||
$ sudo ignite run registry.186526.xyz/186526/ignite-debian \
|
||||
--cpus 12 \
|
||||
--memory 8GB \
|
||||
--size 30g \
|
||||
--ssh --name kernel-builder \
|
||||
-k registry.186526.xyz/186526/ignite-kernel:5.10.39-amd64
|
||||
|
||||
INFO[0001] Created VM with ID "95b84f2c9e92ffa7" and name "kernel-builder"
|
||||
INFO[0002] Networking is handled by "cni"
|
||||
INFO[0002] Started Firecracker VM "95b84f2c9e92ffa7" in a container with ID "ignite-95b84f2c9e92ffa7"
|
||||
INFO[0002] Waiting for the ssh daemon within the VM to start...
|
||||
|
||||
# 连接至该容器
|
||||
|
||||
$ sudo ignite ssh kernel-builder
|
||||
|
||||
# 创建用于内核编译的用户, 名为 builder
|
||||
|
||||
(inFireCrackerContainer) # adduser builder
|
||||
|
||||
Adding user `builder' ...
|
||||
Adding new group `builder' (1000) ...
|
||||
Adding new user `builder' (1000) with group `builder' ...
|
||||
Creating home directory `/home/builder' ...
|
||||
Copying files from `/etc/skel' ...
|
||||
New password:
|
||||
Retype new password:
|
||||
passwd: password updated successfully
|
||||
Changing the user information for builder
|
||||
Enter the new value, or press ENTER for the default
|
||||
Full Name []:
|
||||
Room Number []:
|
||||
Work Phone []:
|
||||
Home Phone []:
|
||||
Other []:
|
||||
Is the information correct? [Y/n] Y
|
||||
|
||||
```
|
||||
|
||||
## 1.2 安装所需编译依赖
|
||||
|
||||
我们这里使用的是 Debian, 使用的是 DPKG/APT 包管理.
|
||||
其他发行版请参考对应文章进行编译依赖的安装.
|
||||
若使用APT, 你需要加入 Source 源来完成依赖的安装.
|
||||
|
||||
``` bash
|
||||
# 更新 APT 的缓存信息
|
||||
|
||||
apt update -y
|
||||
|
||||
# 安装 编译依赖
|
||||
apt install build-essential libncurses5-dev xz-utils wget -y
|
||||
apt-get build-dep linux -y
|
||||
```
|
||||
|
||||
## 1.3 准备源代码
|
||||
|
||||
我们这里将会选择截止本文章编写时最新 (2021.07.03) 的 [Stable Kernel](https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.12.14.tar.xz) (即 5.12.14)
|
||||
|
||||
你可以在 [kernel.org](https://kernel.org) 选择所需 Kernel 来编译.
|
||||
|
||||
``` Bash
|
||||
# 进入 builder 账户
|
||||
|
||||
su - builder
|
||||
|
||||
# 下载 linux-5.12.14.tar.xz 源码文件
|
||||
|
||||
mkdir -p build && cd build && wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.12.14.tar.xz
|
||||
|
||||
# 解压内核源码
|
||||
|
||||
tar xvf linux-5.12.14.tar.xz && cd linux-5.12.14
|
||||
```
|
||||
|
||||
## 2.1 配置内核
|
||||
|
||||
配置内核是个细心活, 你可能能需要大量的时间和精力来配置一个针对你设备最好的内核.
|
||||
如果你觉得你很懒, 你可以选择我在这里配置好的针对 KVM/QEMU 环境的内核配置.
|
||||
你也可以在 `/boot/config-$(uname -r)` 中找到你当前内核的配置.
|
||||
|
||||
```bash
|
||||
# 我们这里选择下载
|
||||
|
||||
|
||||
```
|
|
@ -50,10 +50,8 @@
|
|||
valinenow();
|
||||
}
|
||||
}
|
||||
document.dispatchEvent(new window.Event("LoadValine"));
|
||||
valinedo();
|
||||
if(!window.whenAvailable){
|
||||
let whenAvailable = function(name, callback){
|
||||
window.whenAvailable = function(name, callback){
|
||||
var interval = 100;
|
||||
window.setTimeout(function () {
|
||||
if (window[name]) {
|
||||
|
@ -64,4 +62,6 @@
|
|||
}, interval);
|
||||
}
|
||||
}
|
||||
document.dispatchEvent(new window.Event("LoadValine"));
|
||||
valinedo();
|
||||
</script>
|
|
@ -0,0 +1 @@
|
|||
../../../assets
|
|
@ -35,13 +35,13 @@
|
|||
return;
|
||||
}
|
||||
|
||||
if (!window.dataLayer) {
|
||||
var d = document,
|
||||
a = d.createElement("script");
|
||||
a.async = true;
|
||||
a.src = "https://www.googletagmanager.com/gtag/js?id=G-ENYRL7T64N";
|
||||
d.head.appendChild(a);
|
||||
}
|
||||
(function(e,t,n,i,s,a,c){e[n]=e[n]||function(){(e[n].q=e[n].q||[]).push(arguments)}
|
||||
;a=t.createElement(i);c=t.getElementsByTagName(i)[0];a.async=true;a.src=s
|
||||
;c.parentNode.insertBefore(a,c)
|
||||
})(window,document,"galite","script","https://cdn.jsdelivr.net/npm/ga-lite@2/dist/ga-lite.min.js");
|
||||
|
||||
galite('create', 'UA-174554903-1', 'auto');
|
||||
galite('send', 'pageview');
|
||||
|
||||
if (typeof navigator.connection !== "undefined") {
|
||||
if (navigator.connection.rtt <= 600 & navigator.connection.downlink >= 0.5) {
|
||||
|
@ -53,14 +53,6 @@
|
|||
setTimeout(fontsInit, 1000);
|
||||
}
|
||||
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
|
||||
function gtag() {
|
||||
dataLayer.push(arguments);
|
||||
}
|
||||
|
||||
gtag('js', new Date());
|
||||
gtag('config', 'G-ENYRL7T64N');
|
||||
});
|
||||
|
||||
var fontsInit = function fontsInit() {
|
||||
|
@ -82,14 +74,6 @@
|
|||
whenAvailable("LazyLoad", function () {
|
||||
new LazyLoad(globalThis.lazyLoadOptions);
|
||||
});
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
|
||||
function gtag() {
|
||||
dataLayer.push(arguments);
|
||||
}
|
||||
|
||||
gtag('js', new Date());
|
||||
gtag('config', 'G-ENYRL7T64N');
|
||||
};
|
||||
|
||||
document.addEventListener('LoadValine', function () {
|
||||
|
|
|
@ -5,11 +5,11 @@ workbox.setConfig({
|
|||
});
|
||||
|
||||
const { core, precaching, routing, strategies, expiration, cacheableResponse, backgroundSync } = workbox;
|
||||
const { CacheFirst, NetworkFirst, NetworkOnly } = strategies;
|
||||
const { CacheFirst, NetworkFirst, NetworkOnly,StaleWhileRevalidate } = strategies;
|
||||
const { ExpirationPlugin } = expiration;
|
||||
const { CacheableResponsePlugin } = cacheableResponse;
|
||||
|
||||
const cacheSuffixVersion = '-210703a',
|
||||
const cacheSuffixVersion = '-210703b',
|
||||
// precacheCacheName = core.cacheNames.precache,
|
||||
// runtimeCacheName = core.cacheNames.runtime,
|
||||
maxEntries = 100;
|
||||
|
@ -196,194 +196,6 @@ routing.registerRoute(
|
|||
"POST"
|
||||
)
|
||||
|
||||
const assert_js = core._private, cacheNames_js = core._private, cacheWrapper_js = core._private, fetchWrapper_js = core._private, getFriendlyURL_js = core._private, logger_js = core._private, WorkboxError_js = core._private;
|
||||
|
||||
const cacheOkAndOpaquePlugin = {
|
||||
/**
|
||||
* Returns a valid response (to allow caching) if the status is 200 (OK) or
|
||||
* 0 (opaque).
|
||||
*
|
||||
* @param {Object} options
|
||||
* @param {Response} options.response
|
||||
* @return {Response|null}
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
cacheWillUpdate: async ({
|
||||
response
|
||||
}) => {
|
||||
if (response.status === 200 || response.status === 0) {
|
||||
return response;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const messages = {
|
||||
strategyStart: (strategyName, request) => `Using ${strategyName} to respond to '${getFriendlyURL_js.getFriendlyURL(request.url)}'`,
|
||||
printFinalResponse: response => {
|
||||
if (response) {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class StaleWhileRevalidate {
|
||||
/**
|
||||
* @param {Object} options
|
||||
* @param {string} options.cacheName Cache name to store and retrieve
|
||||
* requests. Defaults to cache names provided by
|
||||
* [workbox-core]{@link module:workbox-core.cacheNames}.
|
||||
* @param {Array<Object>} options.plugins [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins}
|
||||
* to use in conjunction with this caching strategy.
|
||||
* @param {Object} options.fetchOptions Values passed along to the
|
||||
* [`init`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters)
|
||||
* of all fetch() requests made by this strategy.
|
||||
* @param {Object} options.matchOptions [`CacheQueryOptions`](https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions)
|
||||
*/
|
||||
constructor(options = {}) {
|
||||
this._cacheName = cacheNames_js.cacheNames.getRuntimeName(options.cacheName);
|
||||
this._plugins = options.plugins || [];
|
||||
|
||||
if (options.plugins) {
|
||||
const isUsingCacheWillUpdate = options.plugins.some(plugin => !!plugin.cacheWillUpdate);
|
||||
this._plugins = isUsingCacheWillUpdate ? options.plugins : [cacheOkAndOpaquePlugin, ...options.plugins];
|
||||
} else {
|
||||
// No plugins passed in, use the default plugin.
|
||||
this._plugins = [cacheOkAndOpaquePlugin];
|
||||
}
|
||||
|
||||
this._fetchOptions = options.fetchOptions;
|
||||
this._matchOptions = options.matchOptions;
|
||||
}
|
||||
/**
|
||||
* This method will perform a request strategy and follows an API that
|
||||
* will work with the
|
||||
* [Workbox Router]{@link module:workbox-routing.Router}.
|
||||
*
|
||||
* @param {Object} options
|
||||
* @param {Request|string} options.request A request to run this strategy for.
|
||||
* @param {Event} [options.event] The event that triggered the request.
|
||||
* @return {Promise<Response>}
|
||||
*/
|
||||
|
||||
|
||||
async handle({
|
||||
event,
|
||||
request
|
||||
}) {
|
||||
const logs = [];
|
||||
|
||||
if (typeof request === 'string') {
|
||||
request = new Request(request);
|
||||
}
|
||||
|
||||
const fetchAndCachePromise = this._getFromNetwork({
|
||||
request,
|
||||
event
|
||||
});
|
||||
|
||||
let response = await cacheWrapper_js.cacheWrapper.match({
|
||||
cacheName: this._cacheName,
|
||||
request,
|
||||
event,
|
||||
matchOptions: this._matchOptions,
|
||||
plugins: this._plugins
|
||||
});
|
||||
let error;
|
||||
|
||||
if (response) {
|
||||
{
|
||||
logs.push(`Found a cached response in the '${this._cacheName}'` + ` cache. Will update with the network response in the background.`);
|
||||
}
|
||||
|
||||
if (event) {
|
||||
try {
|
||||
event.waitUntil(fetchAndCachePromise);
|
||||
} catch (error) {
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
{
|
||||
logs.push(`No response found in the '${this._cacheName}' cache. ` + `Will wait for the network response.`);
|
||||
}
|
||||
|
||||
try {
|
||||
response = await fetchAndCachePromise;
|
||||
} catch (err) {
|
||||
error = err;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
for (const log of logs) {
|
||||
}
|
||||
|
||||
messages.printFinalResponse(response);
|
||||
}
|
||||
|
||||
if (!response) {
|
||||
throw new WorkboxError_js.WorkboxError('no-response', {
|
||||
url: request.url,
|
||||
error
|
||||
});
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
/**
|
||||
* @param {Object} options
|
||||
* @param {Request} options.request
|
||||
* @param {Event} [options.event]
|
||||
* @return {Promise<Response>}
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
|
||||
|
||||
async _getFromNetwork({
|
||||
request,
|
||||
event
|
||||
}) {
|
||||
const response = await fetchWrapper_js.fetchWrapper.fetch({
|
||||
request,
|
||||
event,
|
||||
fetchOptions: this._fetchOptions,
|
||||
plugins: this._plugins
|
||||
});
|
||||
const responseRealClone = response.clone();
|
||||
const responseClone = new Response(await responseRealClone.blob(), {
|
||||
status: responseRealClone.status,
|
||||
statusText: responseRealClone.statusText,
|
||||
headers: {
|
||||
...Object.fromEntries(responseRealClone.headers.entries()),
|
||||
"server": '186526 Edge',
|
||||
}
|
||||
});
|
||||
const cachePutPromise = cacheWrapper_js.cacheWrapper.put({
|
||||
cacheName: this._cacheName,
|
||||
request,
|
||||
response: responseClone,
|
||||
event,
|
||||
plugins: this._plugins
|
||||
});
|
||||
|
||||
if (event) {
|
||||
try {
|
||||
event.waitUntil(cachePutPromise);
|
||||
} catch (error) {
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
const StaleWhileRevalidateInstance = new StaleWhileRevalidate();
|
||||
/*
|
||||
* Others img
|
||||
|
|
|
@ -92,7 +92,7 @@
|
|||
background-color: #252d38 !important;
|
||||
}
|
||||
.v[data-class="v"] .vsys,
|
||||
.v[data-class="v"] .vtime {
|
||||
.v[data-class="v"] .vtime ,.v[data-class=v] .status-bar, .v[data-class=v] .veditor, .v[data-class=v] .vinput, .v[data-class=v] p, .v[data-class=v] pre code{
|
||||
color: hsla(0, 0%, 100%, 0.86) !important;
|
||||
}
|
||||
.bg-gray {
|
||||
|
|
Loading…
Reference in New Issue