记录一次Go打包Docker镜像的问题
在Linux环境下编译好Go源文件以后我尝试将最后的可执行文件复制到Docker镜像alpine中。
这是一个最简单的Go Web代码
12345678910111213141516171819202122232425package mainimport ( "github.com/gin-gonic/gin" "net/http")func main() { var r = gin.Default() r.GET("/ping", func(c *gin.Context) { c.JSON(http.StatusOK, "pong") }) r.GET("/produce", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "msg": "ok", "goods": "apple", ...
Go切片扩容
以下的内容为Go1.20.2版本的扩容方式
Go数组的扩容机制简单来说分为两种情况
一种是原来的容量小于256,此时会将原来的容量翻倍作为新的容量
一种是容量大于等于256,会按照以下方式扩容直至可以满足需求
newcap+=(newcap+3∗256)/4newcap+=(newcap+3∗256)/4
newcap+=(newcap+3∗256)/4
这是大致的分配方式,实际上情况还要更复杂一些,接下来通过切片扩容的代码来分析一些细节
123456789101112131415161718192021222324newcap := oldCapdoublecap := newcap + newcapif newLen > doublecap { newcap = newLen} else { const threshold = 256 if oldCap < threshold { newcap = doublecap } else { // Ch ...
xv6中创建syscall
xv6的启动过程大致可以分为BIOS->bootloader->kernel,三个环节,本小节主要讲述bootloader的相关内容。
BIOS的作用是将磁盘的第一个扇区的内容移入到地址为0x7c00的位置,然后把控制权交给这份内容。这一份内容就是bootloader。
bootloader由bootasm.S和bootmain.c组成,所以接下来主要分析这两个文件的代码。
bootasm.S
代码不算长,我们先贴上完整的代码:
bootasm.S
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687#include "asm.h"#include "memlayout.h"#include "mmu.h"# Start the firs ...
xv6系统启动——bootloader
我们以在xv6中添加一个date系统调用为例,介绍在xv6中添加系统调用的方法和原理。
date syscall介绍
date系统调用可以获取系统当前的UTC时间。
在我们完成date系统调用后,我们利用这个系统调用做一个小小的工具,可以打印当前的系统时间,工具代码如下:
date.c
123456789101112131415161718#include "types.h"#include "user.h"#include "date.h"intmain(int argc, char *argv[]){ struct rtcdate r; if (date(&r)) { printf(2, "date failed\n"); exit(); } // your code to print the time in any format you like... exit();}
变量r是我们获取到的时间,我们可以通过r打印我们想要的时间格 ...
ssh的原理
SSH是一种网络协议,用于计算机间的加密登录。
ssh保证安全的原理
SSH之所以能够保证安全,原因在于它采用了公钥加密。
整个过程是这样的:
远程主机收到用户的登录请求,把自己的公钥发给用户。
用户使用这个公钥,将登录密码加密后,发送回来。
远程主机用自己的私钥,解密登录密码,如果密码正确,就同意用户登录。
这个过程本身是安全的,但是实施的时候存在一个风险:如果有人截获了登录请求,然后冒充远程主机,将伪造的公钥发给用户,那么用户很难辨别真伪。因为不像https协议,SSH协议的公钥是没有证书中心(CA)公证的,也就是说,都是自己签发的。
可以设想,如果攻击者插在用户与远程主机之间(比如在公共的wifi区域),用伪造的公钥,获取用户的登录密码。再用这个密码登录远程主机,那么SSH的安全机制就荡然无存了。这种风险就是著名的"中间人攻击"(Man-in-the-middle attack)。
SSH协议是如何应对的呢?
如果你是第一次登录对方主机,系统会出现下面的提示:
$ ssh user@host
The authenticity of host ‘host ...
mapreduce简介
MapReduce是一个编程模型,用于处理和生成大数据。用户通过编写Map函数处理输入键值对生成中间键值对,通过编写Reduce函数来合并所有的中间键值对并生成结果。在我们的日常生活中,大部分的任务都可以被抽象成一个MapReduce模型,并通过这个模型解决问题。
MapReduce介绍
我们所遇到的大多数计算问题都很直观,但是当计算的数量十分庞大时,我们往往要借助于成百上千的机器共同计算来加速这个过程,但在从一个机器拓展到一个集群时我们会遇到比原来多得多的问题。比如我们该如何并行化计算,如何把数据分发到机器中,如何处理机器宕机带来的问题,毫无疑问,这是一个复杂的问题。
分布式的计算带来了各种各样复杂的问题,但MapReduce的出现给解决分布式计算带来了一个足够简洁的解决方案。
编程模型
整个计算过程接受一组输入键值对,并输出一组键值对。我们需要为这个计算过程提供两个函数,Map和Reduce。
Map函数接受一组键值对输入并生产一组中间键值对,然后按照一定的标准把这些键值对分组并传输给Reduce函数。
Reduce函数接受中间键值对作为输入,合并这些数据并产生一组键值对作为最 ...
C语言的内存模型
程序为什么要被编译器编译之后才可以运行
编译器在把C语言转换成机器码的过程中做了什么
最后编译出来的可执行文件里面是什么,除了机器码还有什么,是如何组织的
#include<stdio.h>是什么意思,这意味着什么,C语言库是如何实现的
不同编译器和不同硬件平台以及不同的操作系统,最终编译出来的结果相同吗,为什么
HelloWorld是如何运行起来的,操作系统如何装载它,它从哪开始,从哪结束
如果没有操作系统我们如何实现HelloWorld,我们需要什么,如何实现
printf是怎么实现的,它为什么可以有不定数量的参数,为什么最后可以在终端上输出字符串
HelloWorld程序运行时在内存中是怎么样的
C语言的编译过程
复习大一
https简述
在了解https之前,我们先来了解一下非对称加密。
非对称加密的数学原理
非对称加密,就是加密和解密用到的不是一个密钥,一般来说,我们用公钥加密,私钥解密。
下面我们来介绍非对称加密的数学原理,我们来举一个简单的例子:
15 ^ 2 mod 7 = 25 mod 7 = x
易知x = 4,然后,我们将x的位置切换
15 ^ x mod 7 = 4
我们通过枚举,似乎也可以得到答案,x = 2,但是如何模数字变得很大呢?
15 ^ x mod 56374677648 = 4
此时的计算量会变得非常巨大,即使是计算机也要花费数年的时间才能计算得出,我们可以认为这是无法计算的。
上面的计算我们可以认为就是将5(原文)加密成了4(密文),我们在已知x的情况下,很容易就可以加密,但是反之,我们在仅知道5(原文)和4(密文)的情况下,我们很难推出x的值,我们认为这是一个不可逆的过程。
那么,我们接下来把x分成p和q
15 ^ (p * q) mod 56374677648 = 4
也就是
1(原文) ^ (p * q) mod N = 密文
接下来,最重要的一步是结合欧拉公式,可以得到
12 ...
80386内存管理
80386转换逻辑地址到物理地址经过下面的两步:
段翻译,把一个逻辑地址(包含一个段选择子和段偏移量)转换成一个线性地址
页翻译,把一个线性地址准换成一个物理地址,这一步是可选的,取决于系统软件的设计者,在保护模式下段翻译是必须的而页翻译是可选的
这些转换对应用程序而言都是不可见的,下图描述了两种翻译的过程。
段翻译
下图展现了段翻译的细节,显示了处理器如何把一个逻辑地址转换成一个线性地址
为了执行段翻译,处理器需要使用下面这些数据结构
段描述符
段描述符表
段选择子
段寄存器
段描述符
段描述符提供了提供了段翻译所需要的数据,段段描述符由编译器,链接器,装载器或者操作系统创建,不能由应用程序编写者创建,下图是一个段段描述符的常见结构。
可以看到DPL之后的一位把段描述符分为了两种类型,第一种用于存放代码段和数据段,第二种用于系统段。
接下来解释一些比较重要的位:
BASE:由三个部分组成,表示4GB空间内段的位置。
LIMIT:指定了端的大小,由两部分组成了一个20位大小的数字。具体表示的大小还要根据G(granularity,粒度)位来决定。
G(granular ...
制作iso镜像文件
本教程会遵照El-Torito标准生成ISO文件。
编写内核文件
这里我们简单的写一个打印helloworld的汇编即可
12345678910111213141516171819202122#define print(x) movb $0x0E, %ah; \ movb $(x), %al; \ int $0x10.globl startstart: .code16 cli cld print('H') print('e') print('l') print('l') print('o') print(' ') print('W') print('o') print('r') print('l') print('d') ...