自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

choumin的专栏

记录一些小点

  • 博客(45)
  • 收藏
  • 关注

原创 在debian上构建软件包

在 debian 上编译 glibc 挺方便的,使用下面这条命令即可。虽然简单,但可能还是有人不知道,就像我刚开始接触 debain 一样。$ cd ./glibc_src$ dpkg-buildpackage -b在运行这条命令时可能报错,大部分应该都是依赖的问题,根据错误信息提示,使用 apt install xxx 进行安装即可,比如安装 gettext:$ apt install gettext...

2020-12-30 17:50:32 667

原创 将只读文件系统remount为可写文件系统

有些时候可能需要重新 mount 一个已经 mount 的文件系统,改变 mount 标记,比如,将只读的文件系统重新 mount 为可写文件系统。mount 命令的 remount 选项可以将只读文件系统 remount 为可读写文件系统,命令如下:$ mount -o remount,rw /dev/vad1 /...

2020-12-30 10:42:14 2712

原创 Chain ‘MASQUERADE‘ does not exist 报错解决

今天在执行 iptables 相关命令时遇到了 Chain 'MASQUERADE' does not exist 的报错,报错信息如下所示:$ iptables -t nat -A POSTROUTING -s 192.168.122.0/24 ! -d 192.168.122.0/24 -j MASQUERADEiptables v1.8.2 (nf_tables): Chain 'MASQUERADE' does not existTry `iptables -h' or 'iptables

2020-12-29 19:32:46 5120

原创 编译内核后手动升级

这里总结一下,当我们拿到一个内核编译后的结果如何进行手动升级,假设内核编译后我们拿到的内容如下。当然,内核编译后会生成很多文件,这里我们只关心上面 vmlinuz 和 modules 目录,其中 modules 目录里存放了编译出的各个模块文件(*.ko),假设编译出的内核版本是3.10.0。$ ls -1drwxrwxr-x modules-rwxr-xr-x vmlinuz-3.10.0主要分为以下三步,1) 更新 vmlinuz 文件,2) 更新 modules 文件,3)生成 in

2020-12-29 17:28:51 293

原创 读取进程空间中vdso段的内容

下面是 dump vdso 内存区域内容的 shell 脚本,仅供参考:#!/bin/sh[ -z "$1" ] && echo "Usage: $0 out_file" && exitmem_start=`cat /proc/$$/maps |grep vdso |awk -F'-' '{print $1}'`skip=$((16#$mem_start))count=16384 # 在 mips 上 vdso 的大小是 16K (16384),在 x86

2020-12-29 14:36:16 219

原创 find、xargs和cat的小问题

使用 find 查找某种类型的文件是一个非常普遍的需求,比如,下面命令可以查找当前目录下所有以 ".txt" 结尾的文件:$ find ./ -name “*.txt”./a.txt./b.txt./c.txt找到文件往往只是第一步,很多时候我们还想对那些文件做进一步的处理,这时候我们可以使用 xargs 或者 find 自带的 -exec 参数去逐一处理那些文件,比如查看文件内容:$ find ./ -name "*.txt" |xargs cathello, world0123

2020-12-28 19:10:53 2299

原创 gcc中的-D选项

有时候我们想在 C 源文件中使用 Makefile 中定义的某些变量,根据变量的取值做出不同的处理,比如 debug 开关、版本信息等,这时候我们可以通过 gcc 的 -D 选项来满足这一需求,它等同于在 C 文件中通过#define 语句定义一个宏。比如,我们可以在 Makefile 中定义以下变量,并通过 gcc -D 选项传给源文件,然后在源文件中使用这些变量。Makefile:CC=gccversion=0.0.2release_number=2all: testtest...

2020-12-27 14:13:08 5187

原创 binutils、gcc和glibc

binutils、gcc 和 glibc 是 GNU 工具链里三个重要的组成部分。binutils 是一系列的二进制工具,最重要的两个工具是:as(汇编器)和 ld(链接器)。as 将 gcc 生成的汇编代码转换为二进制代码,ld 将多个目标文件代码转换为一个库文件或者一个可执行程序。除了 as 和 ld,binutils 还包括ar、nm、objcopy、objdump、readelf 等工具。gcc 是工具链中的编译器套装,目前不仅支持 C 语言,还支持C++, Java, Fortran,..

2020-12-27 00:04:22 512 1

原创 文件描述符和文件指针的区别

文件描述符是一个内核级的整形数值,用来表示一个打开的文件,由open()、creat()、dup()、pipe() 等系统调用获得,由read()、write() 等系统调用来使用。文件描述符不带缓存功能,在可移植性和读写效率方面存在一定的问题。文件指针是一个C标准库的结构体指针,用来表示一个文件。文件指针封装了文件描述符,由fopen()等系统调用获得,由fread()、fwrite()等系统调用使用。文件指针是一个更高级别的接口,具有缓存功能,以及错误标示和EOF检查等功能,具有更好的可移植性和读写效

2020-12-25 10:55:46 443 1

原创 C语言中的旧式函数声明语法

在看UnixBench源码的时候,看到这样一个函数:void wake_me(seconds, func) int seconds; void (*func)();{ /* set up the signal handler */ signal(SIGALRM, func); /* get the clock running */ alarm(seconds);}这个函数在定义的时候,参数部分是不是看着有点陌生?查了一下,这其实是C语言中一种老

2020-12-24 10:30:04 1899

原创 借用nc自动同步时间

当系统中没有ntp时,我们可以借助 nc 工具实现自动同步系统时间。当然,至少由一台机器的时间是准确的。原理比较简单,借助 nc 构建 server 和 client,然后在 server 端通过文件传输时间信息,在 client 端通过文件接收时间信息,最后设置系统时间。代码如下所示:server 端,./nc_server.sh:#!/bin/shtmp_file=./time.txttouch $tmp_filewhile truedo date +"%Y-%m-%d %H:%

2020-12-23 16:33:29 521

原创 C99中的可变长数组

在C99标准中开始支持可变长数组,即在声明数组时可以用变量来指示数组的大小,而不一定是常量表达式。看下面的示例程序:#include <stdio.h>int main(int argc, char **args) { int n = 5; if (argc > 1) { n = atoi(args[1]); } double A[n][n]; typeof(A) B; printf("sizeof B[%d][%d]:

2020-12-22 20:48:33 1488

原创 make内置函数之流程控制

make中主要有下面几个与流程控制相关的内置函数1)if 函数根据condition的值选择then-part和else-part中的某一个宏扩展,其中,如果condition的宏扩展中包含任意字符(包括空格),那么condition的值为true,在这种情况下,then-part被展开,否则如果condition 的宏扩展为空,那么condition的值为false,else-part被展开。$(if condition, then-part, else-part)2)error 函数用来

2020-12-22 11:06:31 184

原创 make内置函数之文件名处理

make中主要有下面几个与文件名处理相关的内置函数1)wildcard 函数接受一个pattern列表,并对每个pattern进行扩展,最后返回与之匹配的文件名。$(wildcard pattern ...)2)dir 函数返回list中每个文件的目录部分。$(dir list ...)3)not-dir 函数返回name中每个文件的文件名部分。$(not-dir name ...)4)suffix 函数返回name中每个文件的后缀部分。$(suffix name .

2020-12-22 11:03:32 182

原创 make内置函数之字符串处理

make中主要有下面几个字符串处理相关的内置函数1)filter 函数会将text视为一系列被空格隔开的单词,会返回与pattern匹配的单词。$(filter pattern ..., text)2)filter-out 函数所做的事情刚好跟filter相反,用来选出与pattern不匹配的单词。$(filter-out pattern ..., text)3)findstring 函数用来在text中查找string,如果string被找到了,那么该函数返回string,否则返回

2020-12-22 10:58:19 402

原创 make内置函数call

在make中,内置函数call用来扩展变量或者宏,它的语法如下:$(call macro-name[, param1 ...])call会扩展它的第一个参数并把其余参数依次替换到出现$1、$2 ......的地方,macro-name 可以是任何宏或变量的名称。macro-name之后是宏的参数,并以逗号为分隔符。call的第一个参数是一个非扩展式变量名称,即它并非以一个美元符号开始。call的参数检查机制非常简单,你可以为call指定任意多个参数。如果一个宏引用了一个参数$n,但是调用它的ca

2020-12-22 10:48:31 1563

原创 make中的自动变量

make中主要有以下几个自动变量$@ 目标的文件名$% 库文件成员结构中的文件名元素库文件中某个成员也可以作为目标,形如:archive(member),例如:如果目标是foo.a(bar.o),那么 $% 是bar.o,而 $@ 是foo.a$< 第一个依赖的文件名$? 时间戳大于目标的所有依赖项,以空格隔开$^ 所有依赖项的文件名,以空格隔开,已去重$+ 如同$^,未去重$* 目标的主文件名...

2020-12-22 08:46:40 258

原创 GNU C中数组指定初始化

在GNU C中,数组支持指定初始化。简单来说,就是在初始化数组和结构体时,可以通过指定数组下标或者具体成员名来赋初值。例如支持下面这样的初始化:int array[6] = { [4] = 29, [2] = 15 }; // 可以不按顺序赋值还支持将数组中指定范围内的元素赋值为相同的值:int array[] = { [0 ... 9] = 1, [10 ... 99] = 2, [100] = 3 };利用这个特性,我们可以在申请数组的同时进行初始化,比如全部清零:int a

2020-12-21 20:51:32 818

原创 python中目录文件相关操作

0)涉及的包import os1)得到一个目录下的所有文件files = os.listdir(_dir)2) 获得一个文件的绝对路径_file = os.path.abspath(_file)3) 获得一个文件所在的目录_dir = os.path.dirname(_file)4) 文件路径分割# _dir = /a/b/c# items = ['/a/b', ‘c’]items = os.path.split(_dir)5) 文件路径连接pat

2020-12-21 08:59:37 70

原创 python中时间字符串处理

0)涉及的包from from datetime import datetime, timedelta1)时间字符串转datetime对象date_str = "2020122008"date_obj = datetime.strptime(date_str, "%Y%m%d%H")2)datetime对象加一个时间差得到另外一个datetime对象date_start = date_obj + timedelta(hours=int(value)-1)date_end = d

2020-12-21 08:57:46 687

原创 使用daemon()让C程序运行在后台

在linux中,可以使用daemon()函数让程序运行在后台,这个函数的原型是:#include <unistd.h>int daemon(int nochdir, int noclose);其中,如果 nochdir 为 0,则 daemon() 将当前工作目录改变为 "/",否则当前工作目录保持不变;如果 nocolose 为 0,则 daemon() 将标准输入、标准输出、标准错误输出 重定向为/dev/null,否则保持不变。示例程序:#include &l.

2020-12-20 20:52:40 890

原创 /etc/fstab文件编辑

/etc/fstab文件里包含各种文件系统的描述信息,每个文件系统占据一行,每行有六列,中间用 tab 或者空格隔开。这个这六列分别是:设备信息,例如:/dev/cdrom、/dev/sda1、/dev/vda1、<host>:<dir>(针对NFS挂载点) 挂载点,例如:/、/home、/boot 文件系统类型,例如:ext2、nfs、xfs等 挂载选项,参见 mount 命令,default 表示使用默认选项 使用dump命令时是否需要备份该文件系统 重启时文件系统

2020-12-19 22:16:15 1906

原创 VFS: Unable to mount root fs on unknown-block(0,0)问题解决

这个问题貌似很多人都遇到过,因为在网上搜了一下,结果还不少,由一个引用比较多的网页是:https://unix.stackexchange.com/questions/414655/not-syncing-vfs-unable-to-mount-root-fs-on-unknown-block0-0这上面总结的解决方案是:1)确认内核是否支持/dev/vda1设备(假设root=/dev/vda1)上的文件系统,2)确认指定的root是否正确,比如应该是/dev/vda2,而不是/dev/vda1。

2020-12-19 17:46:50 14294

原创 getpid()的缓存问题

glibc 2.3.4 到 2.25 之间的版本实现了getpid()的结果缓存功能,通过glibc的fork()、vfork()、clone()等函数进行支持,但由于上层应用可以通过syscall来旁路glibc的fork()等函数,这会导致如果在创建子进程之前有调getpid(),那么子进程通过getpid()获取的结果是之前缓存的父进程的pid。通过strace命令可以看到这一过程,虽然程序中有多处调用了getpid()函数,但getpid()系统调用只出现了一次。因此,在glibc 2.25以后ge

2020-12-18 18:24:13 361 1

原创 auxiliary vector学习

auxiliary vector 是内核ELF二进制加载器提供给用户空间的一些信息的集合,包括可执行的入口地址、线程的gid、线程uid、vdso入口地址等等。不过,普通应用程序通常不需要关心这些信息,目前主要是动态链接器(ld-linux.so)在使用这些信息。通过auxiliary vector,动态链接器可以方便的获取那些它所需要的来自内核的信息。内核为动态链接器提供了一种方便的获取系统信息的途径。可以方便的将一些标准信息提供给动态链接器。虽然有些信息也可以通过系统调用来获得,但通过auxiliary

2020-12-18 17:07:41 1365

原创 vdso学习

1、只有一小部分系统调用是通过vdso方式实现的,主要涉及get型的系统调用。例如:类似gettimeofday之类的调用,如果每次都陷入内核去拿一个时间戳,会消耗比较多的上下文切换时间,因此,内核把时间戳放在一个公共的可以暴露给任何用户进程的地方,将其映射进用户进程空间。一般来说,通过vdso方式获得的都是一些不太敏感的信息,此时可以不用考虑特权等级,直接在用户态来获取。同时,vdso功能需要libc支持。2、可以使用这篇博客上介绍的方法将进程地址空间中vdso段的内容dump到文件,可以发现,不同体系

2020-12-18 09:17:47 551

原创 读取进程中某块内存区域的内容

以下python 脚本可以读取一个进程的某个内存区域的内容:#!/usr/bin/env pythonimport reimport sysdef dump_memory_region_by_pid(pid, region, of): print "PID = %d, find region ..." % pid with open("/proc/%d/maps" % pid, 'r') as maps_file: with open("/proc/%d/me

2020-12-17 11:20:47 787

原创 使用sysctl配置内核参数

sysctl可以在运行时查看和修改内核的参数,现在梳理一下它的基本使用方法。1)查看所有参数$ sysctl -a2) 查看某一个参数$ sysctl kernel.ostype3) 修改某一个参数例如,以下命令可以修改hostname,并在bash中体现出来[zhoumin@localhost test]$ sudo sysctl kernel.hostname=zm_host[sudo] zhoumin 的密码:kernel.hostname = zm_host[z

2020-12-17 09:18:51 2314

原创 使用dracut生成initrd文件

在linux中,可以使用 dracut 命令生成 initrd 文件,命令格式是:dracut [OPTION...] [<image> [<kernel version>]]在生成的过程中,可以指定需要添加的驱动模块,例如下面这条命令中的 module1、module2(位于/lib/modules 目录下):$ dracut --add-drivers "module1 module2" image kernel_version...

2020-12-16 22:38:49 2852

原创 在linux C中使用unlink删除文件

在linux C中,unlink() 可以删除一个文件,该函数的定义在 unistd.h 头文件里,下面看一下使用方法:// main.c#include <stdio.h>#include <unistd.h>#include <stdlib.h>int main(void) { int fd; char *fname= "a.txt"; if ((fd = creat(fname, 0600)) == -1) { pri

2020-12-16 13:21:26 1031

原创 UEFI 执行流程学习

UEFI系统的启动遵循UEFI平台初始化标准,从加电到关机可以分为7个阶段:SEC(安全验证)--> PEI(EFI前期初始化)→ DXE(驱动执行环境)→ BDS(启动设备选择)→ TSL(操作系统加载前期)→ RT(Run Time) → AL (系统灾难恢复期)。SEC的执行可以分为两个阶段:Reset Vector阶段 和 SEC入口函数阶段。Reset Vector阶段主要是一些汇编代码,用于设置相关寄存器,该阶段系统还没有RAM,因而不能使用基于栈的程序设计,所有的函数调用都使用jmp指

2020-12-15 11:12:51 1037 1

原创 UEFI调试之memory barrier

最近在调试UEFI固件时遇到了memory barrier相关的问题,现在回过头来梳理一下问题发生的现场,给其他同学一些调试思路。在./OvmfPkg/Library/VirtioLib/VirtioLib.c的第328行有个while循环,其中每次在判断 *Ring->Used.Idx 是否等于 NextAvailIdx时都调用了MemoryFence()函数。... // // virtio-0.9.5, 2.4.2 Receiving Used Buffers From th

2020-12-14 13:06:41 512

原创 跳表实现

跳表是马里兰大学William Pugh教授在1990年发表的一篇名为 Skip lists: a probabilistic alternative to balanced trees的论文上提出的,这篇论文在网上可以下载到PDF版,篇幅不长,只有8页,而且没有废话,前3页就把跳表的原理交代清楚了,如果只想了解跳表的实现原理,看前3页就够了,强烈建议对跳表感兴趣的同学读一读。跳表这种数据结构是之前在看redis相关原理时知道的,在好奇心的驱使下去网上找了几篇博客看,但其实没看太明白。跳表的查找还好理.

2020-12-13 01:55:26 329 1

原创 git clone指定历史提交数量

我们在学习git时,可能学会的第一个命令就是git clone。随着越来越多的使用git,越发觉得它的功能非常强大,每个常用的git命令都值得我们用 git xxx --help去学习一下。我们平时在使用git clone时,可能会面临源仓库太大,而下载太慢的问题。其实,如果我们只是想学习一下其中的源码,那么可以在git clone时指定历史提交数量,这样会加快clone到本地的速度。例如,使用git clone下载github上edk2项目的源码,如果不指定历史提交数量,则需要下载 349834

2020-12-12 09:57:51 1408

原创 借助ncurses库实现模仿密码输入

原理比较简单,直接上代码:#include <stdio.h>#include <curses.h>void refill(char ch, int num) { int i = 0; putchar('\r'); for (i = 0; i < num; ++i) { putchar(ch); }}// gcc ./main.c -o main -lcursesint get_pass(char *passw

2020-12-11 10:08:54 228

原创 MBR、GPT和FAT、EXT2

起这样的标题是想简单说明一下它们之间的关系,给刚入门的同学一些思路。简单理解就是,前两者是磁盘分区格式,后两者是文件系统格式。MBR、GPT是两种比较常见的磁盘分区格式,而且对于磁盘分区而言,目前也主要是这两种格式。一个分区是一个存储设备上的一块独立区域,用户可以针对这块区域进行单独管理。FAT、EXT2是文件系统格式。文件系统给我们提供了一系列管理文件的抽象接口,屏蔽了底层差异和实现细节。文件系统可以让我们轻松的存储、读写文件,而不用去关心底层的实现方式,比如:如何组织大文件、如何找到每个文件块,如何

2020-12-08 11:17:46 1737

原创 基于ISO镜像制作qcow文件

1、挂载iso文件$ mkdir /mnt/loop$ mount -o ro,loop centos7.iso /mnt/loop/2、挂载squashfs$ mkdir /mnt/squashfs$ mount -o ro,loop /mnt/loop/live/squashfs.img -t squashfs /mnt/squashfs/3、创建qcow文件$ qemu-img create -f raw vdisk 10G4、给qcow文件进行分区$ l

2020-12-07 17:12:26 1394

原创 loop设备学习

1、loop设备在类 UNIX 系统里,loop 设备是一种伪设备(pseudo-device),或者也可以说是仿真设备。它能使我们像访问块设备一样访问一个文件。在使用之前,一个 loop 设备必须要和一个文件进行连接。这种结合方式给用户提供了一种替代块特殊文件的接口。因此,如果这个文件包含有一个完整的文件系统,那么这个文件就可以像一个磁盘设备一样被mount起来。对于需要通过loop设备访问的文件类型包括 CD 或 DVD 的 ISO 光盘镜像文件或者是软盘(硬盘)的 *.img 镜像文件。通过这种

2020-12-07 17:08:13 467

原创 网络配置遇到的小问题

记得刚工作那会,公司有个网管小哥哥,人很亲切,经常给我们应届生讲一些网络知识。记得最深的一句话大概是:查网络问题,先从物理层查起。当时觉得好理解,七层结构物数网传会表应,物理层是最底层也最关键的一层。貌似今天就遇到了物理层的坑,以此记录一下。一台测试机,配置好网络后,怎么都ping不通其他机器,最后只好放弃,选择用串口连接来访问。回过头来,干自己的活,但发现自己的机器也ping不通其他机器,这不行啊,测试机网络不通,还能用串口,但本机网络不通,就基本没法工作了,于是开始仔细检查,先看了本机的网络配置,看着

2020-12-05 15:43:41 531

原创 git fetch遇到Permission denied (publickey)问题

在使用git fetch时遇到下面这样的问题:$ git fetchzhoumin@abc.cn: Permission denied (publickey).fatal: Could not read from remote repository.Please make sure you have the correct access rightsand the repository exists.查了一下,是因为~/.ssh/id_rsa.pub里面的内容被别人更新了,以前都是再重新

2020-12-05 09:38:39 1782

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除