Linux ubuntu环境搭建
资料准备
- 官网下载ubuntu桌面版
- 下载VMware Workstation 15 Player
安装VM,在VM中安装ubuntu系统,作为虚拟机,主要的配置选择:
- 内存:本机内存的一半即可
- CPU核数:与本机CPU核数相同即可
- 网卡:要与接通Linux板子的接通的线路相通即可
相关重要的指令:
- apt-get install <软件包名称>
- apt-get uninstall <软件包名称>
ubuntu下配置系统服务的软件包:
- sysv-rc-conf
安装主要的开发工具
- sudo apt-get install buile-essential
其余的一些工具
- sudo apt-get install autoconf automake (生成makefile的工具)
- sudo apt-get install flex bison(语法扫描分析工具)
- sudo apt-get install manpages-dev(C语言函数用户手册)]\
ubuntu上github的安装:
- sudo apt-get install git (前面是否需要加sudo,取决于你是否用root的身份执行)
- sudo add-apt-repository ppa:git-core/ppa
- sudo apt update; apt install git
中途会遇到[Y/n],输入Y就好
ifconifg无效的方法
这个命令用不了是因为没有安装相关的插件,
- sudo apt-get install net-tools
就可以了
检验
Ctrl + Alt +T可以打开终端,在终端上输入
- gcc --version
- gdb --version
应该会有相应的信息打印出来,如果能打印就正常了。
开始第一个程序
使用vi编辑器
在终端上,输入 vi hello.c,将会进入一个新的编辑界面。
- 在新的界面上,输入i进入插入模式,Esc可以回归浏览模式
- 输入v可以进入可视模式,Esc可以回归浏览模式
- 输入r可以进入覆盖模式,Esc可以回归浏览模式
- 在浏览模式下,输入“:”,“q!”=不保存并退出
- 在浏览模式下,输入“:”,“wq”=保存并退出
q表示退出,w表示保存,e表示编辑
在插入模式下,编写一段程序,如下图:
就是一段很简单的输出hello world的程序,其中的while(1)只是我的习惯,当然也可以如下:
#include "stdio.h"
int main(void)
{
printf("hello world!");
return 0;
}
完成后,使用终端,进入该文件的目录下,执行:
gcc hello.c
然后回车,之后,你会发现没什么动作,这就证明已经编译好了。执行ls,会出现a.out这个文件:
这个怎么用呢?在中断下,输入:
./a.out
回车,就可以看到效果了。
在gcc的编译下,有两种方式
- 动态编译:gcc <文件名>
- 静态编译:gcc -static <文件名>
分析两个的区别,
从内存上看,对比两种编译的效果,使用关键命令strace来查看,先看gcc hello.c的效果,因为刚刚已经编译过了。
执行:
ls -l -h
就可以看到
-rwxr-xr-x 1 sola sola 8.2K 1月 26 12:15 a.out
意思是编译出来只有8.2k的大小。
然后执行
strace ./a.out
就会得到下面的代码:
sola@ubuntu:~/Desktop/learn$ strace ./a.out
execve("./a.out", ["./a.out"], 0x7ffe38ff79a0 /* 66 vars */) = 0
brk(NULL) = 0x5614d39b6000
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)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=78688, ...}) = 0
mmap(NULL, 78688, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f42ed505000
close(3) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/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\0\260\34\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2030544, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f42ed503000
mmap(NULL, 4131552, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f42ecf01000
mprotect(0x7f42ed0e8000, 2097152, PROT_NONE) = 0
mmap(0x7f42ed2e8000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1e7000) = 0x7f42ed2e8000
mmap(0x7f42ed2ee000, 15072, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f42ed2ee000
close(3) = 0
arch_prctl(ARCH_SET_FS, 0x7f42ed5044c0) = 0
mprotect(0x7f42ed2e8000, 16384, PROT_READ) = 0
mprotect(0x5614d2f66000, 4096, PROT_READ) = 0
mprotect(0x7f42ed519000, 4096, PROT_READ) = 0
munmap(0x7f42ed505000, 78688) = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
brk(NULL) = 0x5614d39b6000
brk(0x5614d39d7000) = 0x5614d39d7000
write(1, "hello world\n", 12hello world
) = 12
慢慢看:
1)
这里调用execve()这个函数,进行系统执行
execve("./a.out", ["./a.out"], 0x7ffe38ff79a0 /* 66 vars */) = 0
brk()函数创建进程的数据段
brk(NULL) = 0x5614d39b6000
后面的,就是打开共享库,并且加载到内存里。
不难发现这里有个write()的函数,这是什么呢?其实就是printf所调用的,printf的实际就是调用write()这个函数来实现。
write(1, "hello world\n", 12hello world) = 12
再来类比,看看静态的方式:
先编译,执行:
gcc -static hello.c
然后:
ls -l -h a.out
则出现
-rwxr-xr-x 1 sola sola 825K 1月 26 12:39 a.out
是不是很惊讶,8.2k和825k的差别,真的有点可怕,很明显体现出动态编译的好处了。
然后再执行:
strace ./a.out
就可以看到
execve("./a.out", ["./a.out"], 0x7ffc32223ed0 /* 66 vars */) = 0
brk(NULL) = 0x24df000
brk(0x24e01c0) = 0x24e01c0
arch_prctl(ARCH_SET_FS, 0x24df880) = 0
uname({sysname="Linux", nodename="ubuntu", ...}) = 0
readlink("/proc/self/exe", "/home/sola/Desktop/learn/a.out", 4096) = 30
brk(0x25011c0) = 0x25011c0
brk(0x2502000) = 0x2502000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
write(1, "hello world\n", 12hello world
) = 12
^C--- SIGINT {si_signo=SIGINT, si_code=SI_KERNEL} ---
strace: Process 2460 detached
没错,大同小异,少了很多。