











一、安装包分类
在Linux平台下,软件包的类型可以划分为两类:源码包、二进制包。
源码包:即程序软件的源代码(一般也叫Tarball,即将软件的源码以tar打包后再压缩的资源包)。
二进制包:如 Red Hat发行版的.rpm包,Debian发行版的.deb包。
这篇文章将要介绍的是Linux平台下的源码安装,关于二进制包的安装可以查看我的另两篇文章:《Linux软件安装管理之——RPM与YUM详解》、《Linux软件安装管理之——dpkg与apt-*详解》
二、源码包安装的主要步骤
源码包的安装主要分为三个步骤,如图:
三、最简单的例子
为了能够更好的理解源码包的安装过程,这里举一个最简单的例子来加以说明。
1、获取源代码文件
这里使用C语言来编写一个最简单的程序,输出“Hello World!”,
首先,使用命令【vim hello.c】创建一个c源文件,内容如下:
#include
int main(void){
printf("Hello World!\n");
}
2、编译
编译的命令为【gcc hello.c】
执行了上面的命令后则可以发现当前目录下多了一个a.out,该文件即为编译后生成的二进制文件。
3、测试结果
运行命令【./a.out】,则可以得到如下结果。
举上面这个例子只是为了能够更加好的理解软件在Linux中安装的原理,在实际中可以说是不会有这么简单的一个程序来让你安装的。一般情况,一个软件是由一系列的程序文件来组成,所以现实中的源码包安装方法并没有像上面那个例子那么简单,那下面就来介绍一般情况下的源码包安装方法。
四、源码包安装详解
现实中,使用一个源码包来安装程序时,基本步骤如:
在上图第二步中的--prefix后面接的路径表示这个软件将要安装到哪个目录去,如果没有指定--prefix=/path这个参数,通常默认为/usr/local。本人推荐安装位置为 /usr/local/XXX,XXX为自己的实际目录,这样会方便以后的管理。
源码包安装方式的man文件默认保存在/usr/local/man或/usr/local/share/man中,如果你的安装路径自定义为如/usr/local/XXX,则man文件则一般是在/usr/local/XXX/share/man中。此时如果你想要通过man来查看你所安装软件的man手册,则需要自行修改man的路径配置文件(可能是man.config或者manpath.config)。需要在相应位置添加如下一行:
MANPATH /usr/local/XXX/share/man
五、其它
1、卸载
通过源码包安装的软件,当你想要卸载的时候,只需要把整个安装路径删除掉就行了,100%卸载,不会像windows那样经常会残留那多注册表之类的垃圾。
根据你的安装时候选择的安装路径,源码包的卸载又仓库两种情况:
如果你安装时候指定的路径为:--prefix=/usr/local/XXX,那么卸载的时候只需要把XXX这个文件夹删除即可,因为该软件安装的所有文件都是放置在XXX这个文件夹。
但如果你进行源码包安装的时候没有指定位置(默认值一般为/usr/local/),或指定的位置为--prefix=/usr/local,则这时候你安装软件生成的文件将分别存储在/usr/local/里面的bin、lib或ect等目录中,这时候卸载起来就相对麻烦一点了。
2、源码包安装与二进制包的区别
源码包的优点:
1)开源,如果有能力可以修改源代码
2)可以自由选择所需的功能
3)软件是编译安装,所以更加适合自己的系统,更加稳定也效率更高
4)卸载方便
源码包的缺点:
1)安装过程步骤较多,尤其安装较大的软件集合时(如LAMP环境搭建),容易出现拼写错误
2)编译过程时间较长,安装比二进制安装时间长
3)因为是编译安装,安装过程中一旦报错新手解决
二进制包的优点:
1)包管理系统简单,只通过几个命令就可以实现包的安装、升级、查询和卸载
2)安装速度比源码快得多、
二进制包的缺点:
1)经过编译,不可以再看到源码
2)功能选择不如源码包灵活
3)依赖性
作者:Nosee123
链接:https://www.jianshu.com/p/ee60a9d6bd7d
记一次废旧手机的折腾
之前在学校的时候玩过单片机做过一个智能小车,最近了解了树莓派相关的知识,原本想自己买一个树莓派玩一玩,可因为最近武汉疫情的情况 大部分快递都停运了 按耐不住想折腾的心,突然想到安卓系统是基于linux内核的底层的架构应该可以支持安装linux系统,因此查阅了相关的知识得到了一套解决方案:
软件准备:
手机端:linuxdeploy下载链接,BusyBox下载链接
电脑端:xshell
步骤如下:
1. BusyBox中设置如下
这里的安装路径保持默认 或者是自定义 但是要记住这个路径 后面会用到
2. linuxDeplou设置
前言Linux内核是Linux操作2347系统的核心,也是整个Linux功能体现的核心,就如同发动机在汽车中的重要性。内核主要功能包括进程管理、内存管理、文件管理、设备管理、网络管理等。Linux内核是单内核设计,但却采用了微内核的模块化设计,支持内核线程以及动态装载内核模块的能力。Linux作为一个自由软件,在广大爱好者的支持下,内核版本不断更新。新的内核修订了旧内核的bug,并增加了许多新的特性。如果用户想要使用这些新特性,或想根据自己的系统定制一个更高效、更稳定的内核,就需要手动编译Linux内核。那么如何编译内核呢?本文将讲解Linux内核编译的详细程。内核获取编译内核的前提是需要有新内核的源码包,获取源码包的渠道有很多,这里就不详细介绍了,建议直接去官方网站(www.kernel.org)下载。我这里准备的是3.10.10版本的源码包,尽量不要直接编译最新版本的内核,可能会造成不兼容等问题。解压源码包编译内核时,一般把源码解压到/usr/src目录下,解压完成后会在该目录下生成一个与源码包版本号一致的目录,为了方便起见,我们可将它做一个链接,链接为linux目录。配置内核编译内核首先需要安装开发环境(Development Tools和Server Platform Development),配置内核之前可以查看当前系统的设备信息,了解系统详细配置。查看主机信息:查看CPU:cat /proc/cpuinfox86info #此工具需手动安装lscpu查看PCI:lspci #可用选项-v查看详细信息查看USB:lsusb #可用选项-v查看详细信息查看块设备:lsblk配置内核可选用多种方法make config #遍历选择编译内核功能make allyesconfig #启用内核全部功能make allnoconfig #内核功能选项全部为否make menuconfig #开启文本菜单选项,对窗口有限制,尽量调大窗口,否则会出错#使用此命令需安装gcc和ncurses-develmake gconfig #依赖GNome桌面环境及GNome的图形开发环境,gtk2make kconfig #依赖KDE桌面环境及KDE的图形开发环境,qt内核功能选项[*] #编译进内核本体[M] #编译成内核模块[ ] #不选择使用使用make menuconfig开启菜单选项,手动选择内核功能配置完成后,配置信息会存储于名为.config的隐藏文件,如果想方便配置,可复制/boot/config文件覆盖.config文件,直接修改即可。编译安装编译时如果是远程连接,一旦断开连接,编译就会出问题。所以我们可使用screen命令(需安装),启动多个窗口,即使连接中断,编译也不会终止。screen #开启窗口Ctrl+A+D #隐藏窗口screen -ls #查看运行的窗口screen -r SCREEN_ID #返回窗口开始编译安装模块安装完成后在/lib/modules/目录下会生成一个同内核版本好的目录,目录下便是新内核的模块了安装内核安装完成后会在/boot目录下生成几个新内核的文件查看grub.conf配置文件,会发现新内核的信息已经写入了以新内核启动查看新内核版本uname -r补充:如果前面多次编译过,在编译开始之前可进行清理make clean #清理编译的文件,但保留配置文件make mrproper #移除所有编译生成的文件、配置文件和备份文件make distclean #完全清理如果想快速编译,可进行如下操作make -j * #*为cup核心数如果想将编译生成的文件保存至别处,可进行如下操作mkdir /path/to/somewhere #创建存放目录cd /path/to/somewhere #进入目录./configure --ksource=/usr/src/linux #指定源目录如何只编译内核的部分代码只编译某子目录中的相关代码:cd /usr/src/linuxmake path/to/dir/只编译部分模块:make M=path/to/dir只编译一个模块:make path/to/dir/MOD_NAME.ko将编译生成的文件保存至别处:make O=/path/to/somewhere转载于:https://www.cnblogs.com/tsw1107/p/ef7022099ad9dd76564a47b448670e9b.html
原创作品转载请注明出处 + https://github.com/mengning/linuxkernel/ ”
学号:SA18225163
目录
一、内核编译
Linux内核是操作系统的核心,也是整个Linux功能体现的核心,就如同发动机在汽车中的重要性。内核主要功能包括进程管理、内存管理、文件管理、设备管理、网络管理等。Linux作为一个自由软件,在广大爱好者的支持下,内核版本不断更新。新的内核修订了旧内核的bug,并增加了许多新的特性。如果用户想要使用这些新特性,或想根据自己的系统定制一个更高效、更稳定的内核,就需要手动编译Linux内核。下面我们简要说明一下Linux5.0内核的编译步骤。
1.安装必备的软件编译工具
apt-get install libncurses5-dev build-essential kernel-package
注意:
(1)libncurses5-dev是为之后配置内核能运行 make menuconfig程序做准备Build-essential为编译工具,kernel-package是编译内核工具
(2)如果系统显示无法查找到这三个文件,输入#apt-get update更新数据源。
下载软件的时间会很长,需要注意保证你的Ubuntu存储空间>40GB,
2.下载Linux5.0内核代码
可以直接下载在本地,然后复制到Ubuntu下进行解压,解压指令:
.zip文件
unzip linux-master.zip
.tar文件
tar -xvf linux-master.tar
3.配置内核
make config #遍历选择编译内核功能 make allyesconfig #启用内核全部功能 make allnoconfig #内核功能选项全部为否 make menuconfig #开启文本菜单选项,对窗口有限制,尽量调大窗口,否则会出错 #使用此命令需安装gcc和ncurses-devel make gconfig #依赖GNome桌面环境及GNome的图形开发环境,gtk2 make kconfig #依赖KDE桌面环境及KDE的图形开发环境,qt //内核功能选项 [*] #编译进内核本体 [M] #编译成内核模块 [ ] #不选择使用
这里我们可以使用多种工具进行内核配置,这里只介绍menuconfig方法,按照下面指令执行:
进入内核文件
cd linux-master
配置内核,找到kernel hacking,->Compile-time checks and compiler options,选择 [*]compile the kernel with debug info
make menuconfig
在执行该命令时会报错,说明编译过程缺少文件,下载缺少的文件即可。
/bin/sh: 1: bison: not found scripts/Makefile.lib:217: recipe for target 'scripts/kconfig/zconf.tab.c' failed make[2]: *** [scripts/kconfig/zconf.tab.c] Error 127 Makefile:514: recipe for target 'silentoldconfig' failed //下载文件 sudo apt-get install bison /bin/sh: 1: flex: not found scripts/Makefile.lib:202: recipe for target 'scripts/kconfig/zconf.lex.c' failed make[2]: *** [scripts/kconfig/zconf.lex.c] Error 127 Makefile:514: recipe for target 'silentoldconfig' failed //下载文件 sudo apt-get install flex
编译内核,编译内核时间会很长,可以选择多线程编译,make -j4
make
二.启动QEMU
qemu -kernel linux-master/arch/x86/boot/bzImage -initrd rootfs.img
1.跟踪分析内核启动
整个Linux的框架如上图所示,在这里我们关注的是内核的作用,内核完成系统启动之前的跟中初始化任务及创建必要的任务进程。下面我们借助QEMU来实现各种内核的启动位置。
执行指令qemu-system-x86_64 -kernel linux-5.0.1/arch/x86/boot/bzImage -initrd rootfs.img -s -S跟踪内核。
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S # 关于-s和-S选项的说明: -S freeze CPU at startup (use ’c’ to start execution) -s shorthand for -gdb tcp::1234 若不想使用1234端口,则可以使用-gdb tcp:xxxx来取代-s选项
再打开另一个shell界面,使用gdb跟踪调试内核,执行下面的指令,实现内核执行跟踪。
gdb (gdb)file linux-3.18.6/vmlinux # 在gdb界面中targe remote之前加载符号表 (gdb)target remote:1234 # 建立gdb和gdbserver之间的连接,按c 让qemu上的Linux继续运行 (gdb)break start_kernel # 断点的设置可以在target remote之前,也可以在之后 (gdb) c #继续执行
Linux内核启动函数为start_kernel()函数(linux/init/main.c),所有的初始化工作均在该函数,先关闭中断,进行完重要的初始化之后,再打开中断,执行内存初始化、进程调度初始化并启用中断(包括时钟中断等)等一些列操作。下图展示了内核启东市的一个简略过程。
三、跟踪分析系统调用
本阶段我们需要用到menuOS进行系统调用跟踪,我们需要下载该文件到目录下直接进行编译即可,由于内核文件名及位置不同,我们需要改动Makefie文件中的指令qemu -kernel ../linux-3.18.6/arch/x86/boot/bzImage -initrd ../rootfs.img为我们自己的文件qemu-system-x86_64 -kernel ../linux-master/arch/x86/boot/bzImage -initrd ../rootfs.img,在进行make rootfs编译即可。
若出现上述错误,修改的方法是执行指令sudo apt-get install libc6 libc6-dev即可。
1.随机选择系统调用号调用进行跟踪分析
在这里随机选择系统调用号为63作为跟踪调用的对象,具体调用为#define SYS_read __NR_read,在menu-master/text.c文件中修改程序:
int rred(void){ char word[30]; FILE*fp; if((fp = fopen("tt.txt","a+")) == NULL){ fprintf(stdout,"ERROR!"); exit(EXIT_FAILURE); } fscanf(fp,"%s",word); printf("%s\n",word); return 0;}
重新编译程序,再次执行emu-system-x86_64 -kernel ../linux-master/arch/x86/boot/bzImage -initrd ../rootfs.img。
由于用gdb跟踪过于复杂,我们采用strace程序进行跟踪,将程序的调用的函数名写入文档中记性查看,具体操作是编译一个简单的读写程序,即将上述的rred()函数复制作为main主函数执行,在执行一下指令:
gcc start.c -o start strace -o hi.text ./start
execve("./t", ["./t"], [/* 61 vars */]) = 0 brk(NULL) = 0x147c000 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 fstat(3, {st_mode=S_IFREG|0644, st_size=100972, ...}) = 0 mmap(NULL, 100972, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f1e1d879000 close(3) = 0 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0P\t\2\0\0\0\0\0"..., 832) = 832 fstat(3, {st_mode=S_IFREG|0755, st_size=1868984, ...}) = 0 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f1e1d878000 mmap(NULL, 3971488, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f1e1d2a3000 mprotect(0x7f1e1d463000, 2097152, PROT_NONE) = 0 mmap(0x7f1e1d663000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1c0000) = 0x7f1e1d663000 mmap(0x7f1e1d669000, 14752, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f1e1d669000 close(3) = 0 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f1e1d877000 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f1e1d876000 arch_prctl(ARCH_SET_FS, 0x7f1e1d877700) = 0 mprotect(0x7f1e1d663000, 16384, PROT_READ) = 0 mprotect(0x600000, 4096, PROT_READ) = 0 mprotect(0x7f1e1d892000, 4096, PROT_READ) = 0 munmap(0x7f1e1d879000, 100972) = 0 brk(NULL) = 0x147c000 brk(0x149d000) = 0x149d000 open("tt.txt", O_RDWR|O_CREAT|O_APPEND, 0666) = 3 fstat(3, {st_mode=S_IFREG|0664, st_size=18, ...}) = 0 read(3, "sdadsadsadadsadsa\n", 4096) = 18 fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 3), ...}) = 0 write(1, "sdadsadsadadsadsa\n", 18) = 18 lseek(3, -1, SEEK_CUR) = 17 exit_group(0) = ? +++ exited with 0 +++
整个执行情况就是频繁的调用内存函数mmap()将数据读取,然后调用read进行读取,并最后调用写函数write将数据打印到屏幕上,从上述的记录可以清楚地看到系统调用函数的整个过程。
四、总结
系统调用时在用户态与内核态之间进行切换,通过sys_call()函数来实现用户态调用内核态的各种功能,既满足了对功能的实现,有防止用户态程序对内核程序的恶意修改,保证了内核的稳定与安全。