一、安装
基于win系统安装Linux,一般通过虚拟机(VMware workstation player,虚拟操作系统)安装ubuntu。
VMware:https://www.vmware.com/
Ubuntu:https://cn.ubuntu.com/
二、配置
开机会启动许多程序,在Windows叫做"服务"(service),在Linux就叫做"守护进程"(daemon)。开机成功后,会显示一个文本登录界面,这个界面就是经常看到的登录界面,在这个登录界面中会提示用户输入用户名,用户名将作为参数传给login程序来验证用户的身份,密码是不显示的,输完回车即可!一般来说,用户的登录方式有三种:①命令行登录;②ssh登录;③图形界面登录。
(0)显示
(1)更新系统
sudo apt update #更新
sudo apt upgrade #升级
(2)更改软件源

更新(最重要):sudo apt-get update
(3)配置ssh
sudo apt install openssh-server #安装openssh-server服务
sudo systemctl start ssh #启动
sudo systemctl enable ssh #开机自启动服务
(4)XShell 远程登陆
XShell 是一个远程终端软件. 下载官网 https://www.xshell.com/zh/free-for-home-school/
(5)关机
shutdown # 关机指令,你可以 man shutdown 来看一下帮助文档。
sync # 将数据由内存同步到硬盘中
例如你可以运行如下命令关机:
shutdown -h 10 # 这个命令告诉大家,计算机将在10分钟后关机
shutdown -h now # 立马关机
shutdown -h 20:25 # 系统会在今天20:25关机
shutdown -h +10 # 十分钟后关机
shutdown -r now # 系统立马重启
shutdown -r +10 # 系统十分钟后重启
reboot # 就是重启,等同于 shutdown -r now
half # 关闭系统,等同于shutdown -h now 和 poweroff
三、命令
1. Linux 用户管理
Linux 系统是一个多用户的操作系统,安装系统时被要求注册一个用户 ,此外系统还会默认自带一个root 用户。 Linux 自带了用户管理的命令去管理用户拥有不同的权限,即管理着不同的文件与目录。每个账户都会有自己的一个主目录(~) ,对于普通用户 这个主目录在**/home 对应的用户名文件夹** 下,对于超级用户 在**/root 下,** 是用户登录后的默认工作空间,其核心作用是为用户提供个性化、安全的文件管理和配置环境。

这些账号彼此间独立,可以同时登录,并拥有着自己独有的密码。通过不同的用户,系统可以更好地管理资源,并对用户进行监测。要实现用户账号的管理,需要完成的工作主要有如下几个方面:①用户账号的添加、删除与修改;② 用户口令的管理;③ 用户组的管理。
(1)useradd------添加新的用户
语法:
useradd [opt] 用户名
opt:
• -c:添加描述。
• -d:目录的缩写,用来指定用户主目录。如果此目录不存在,则同时使用-m 选项可以创建主目录。
• -g:指定用户所属的用户组。
• -G:指定用户所属的附加组。
• -s:指定用户的登录 Shell。
• -u:指定用户的用户号。
创建用户:
useradd --d /home/test -m test #此命令创建了一个用户 test,其中-d 和-m 选项用来为登录名 test 产生一个主目录 /home/test。(/home 为默认的用户主目录所在的父目录)
(2)userdel------ 删除账号
删除用户需要删除用户的各种配置文件,如passwd 之类,或许还需要删除该用户的主目录。
语法:
userdel [opt] 用户名
opt:
-r 把用户的主目录一起删除。
示例:
userdel -r test #此命令删除用户 test 在系统文件中(主要是/etc/passwd、/etc/shadow、 /etc/group 等)的记录,同时删除用户的主目录。
(3)passwd------用户密码
创建完的账户是没有密码的,需要使用 passwd 命令进行密码修改操作。超级用户可以为自己和其他用户设定修改密码,普通用户只能修改自己的密码。
语法:
passwd [opt] 用户名
opt:
• -l:锁定密码无权修改,仅能通过 root 修改。
• -u:解除锁定。
• -d:删除密码,只能以 root 身份执行。
• -f:强迫用户下次登录时修改密码,只能以 root 身份执行。
不输入用户名则默认修改自己账户的密码。如 假设当前用户是 test,则下面的命令修改该用户自己的密码:
[root@ubuntu ~]# passwd
[root@ubuntu ~]# Old password:******
[root@ubuntu ~]#
[root@ubuntu ~]# Re-enter new password:*******
如果是超级用户,可用下列形式指定任何用户的密码:
[root@ubuntu ~]# passwd test
[root@ubuntu ~]#
[root@ubuntu ~]# Re-enter new password:*******
普通用户修改自己的密码时,使用 passwd 命令会先询问原密码,验证通过后会再要求用户输入两遍新密码,
如果两次输入的密码一致,则将这个密码设定。
超级用户为用户指定密码时,就不需要知道原密码可直接修改。
设定用户空密码的命令:
passwd -d test #将用户 test 的口令删除,用户 test 在下一次登录时,系统不允许该用户登录
锁定某用户不能登录的命:
[root@ubuntu ~]# passwd -l test
2. Linux 文件与 目录 权限
系统目录结构:在终端(ctrl+alt+t)输入 ls / 命令,可展示所有根目录下的文件。

Linux 的大致文件目录如下图所示:

以下是对这些目录的解释:
/bin:bin 是 Binaries 的缩写,里面是一些普通用户也可以使用的基础命令,比如 ls、cp 等。
/boot:这里存放的是 Linux 系统和内核启动所需要的文件。
/dev:dev 是 Device(设备)的缩写,在 Linux 中一切都是基于文件,外部设备在这里就被抽象成一个文件,对文件的操作就是对外部设备的操作。
/etc:etc 是 et cetera(法语等等的意思)的缩写,这里面有大量的配置文件,是用来配置各种各样设置用的,比如网口的 ip 地址需要修改/etc/network/interfaces 这个文件。
/home:这是普通用户的用户主目录,用来存放用户的文件。在这个文件夹下的文件,默认文件的权限都会比较低,不需要 root 便可读写。
/lib:lib 是 Library(库)的缩写,这个目录是动态连接共享库,与 Windows 里的 DLL 文件类似。几乎所有的应用程序都需要用到这些共享库。
/lost+found:顾名思义,是用来存放丢失文件的,比如强制关机或者意外断电时保存的文件。
/media:用来挂载有关媒体相关的设备,比如光盘,VM 共享文件夹等等。在这个文件夹下可以直接打开文件夹来查看里面的内容。
/mnt:mnt 是 mount 的缩写,这个文件夹是用来挂载设备的,与上面 media 的区别是 mnt 可以默认挂载 u 盘,用途一样,只有用法上有一些小的区别。
/opt:opt 是 optional(可选)的缩写,这个文件夹一般是空的,主要用来存放第三方的软件,如果自己安装的软件可以选用此目录,不过按照习惯安装在/user/local 下更常见。
/proc:proc 是 Processes(进程)的缩写,这个文件夹并不实际存在在硬盘上,而是存在于内存之中,是内存的一个映射,称作虚拟文件系统。其中放置着系统核心、进程信息等等,里面重要的文件比较多,不清楚的情况下不应随意更改。
/root:该目录为超级权限者的用户主目录,和上面的普通用户主目录的作用一致,不过超级用户主目录的文件夹权限要高于普通用户,可以阻止一些没有权限的操作。
/sbin:sbin 是 Superuser Binaries(超级用户的二进制文件)的缩写,作用于上面的 bin 文件夹是一样的,区别是这是给超级用户提供的,普通用户使用普通权限无法运行其中的程序。
/srv:srv 是 service 的缩写,是提供一些网络服务存取数据使用的。
/sys:和 proc 一样,这个文件夹存在于内存之中,是一个特殊文件系统。这个文件夹是设备树思想的集中体现,所有在设备树内注册的设备都会按照一定的顺序组织在这个文件夹内,此外这里还存放着主次设备号文件、块设备、总线等诸多重要文件。
/tmp:tmp 是 temporary(临时)的缩写,用来存放一些临时文件,一般是供系统使用的 。
/usr:usr 是 unix shared resources(共享资源)的缩写,注意不是 user。大部分的软件都安装在这里。
/usr/bin:普通用户使用的应用程序。
/usr/sbin:超级用户使用的应用程序以及系统守护程序。
/usr/src:内核源代码默认的放置目录,自己下载的源码也可放置在这里。
/var:var 是 variable(变量)的缩写,常常用来放置一些缓存、日志文件或者软件运行时产生的文件等等。
/run:是一个存放系统启动时所需文件的文件夹,里面的内容应该在关机时被删除,待下次开机时再重新生成。
在 Linux 系统中大多数目录比较重要,在不熟悉的情况下不要删除或随意更改内部文件。
使用 ll 或 ls -l 查看文件或文件夹的属性,共10位来文件或文件夹的信息。第一位表示文件或文件夹的类型,剩余九位表示文件或文件夹的属组及拥有的权限,即所有者、属组、其它用户 ,权限是可读(r)可写(w)可执行(x),没有对应权限用减号 -- 代替。

由上图可知, uisrc/ 文件夹属性的第一个字母为 d表示目录文件,此外Linux 还有如下字符代表不同含义:
d:目录文件(directory)。
-:普通文件、纯文本文件(ASCII)、二进制文件(Binary)、数据格式的文件(Data)。
l:符号链接文档(link file)。
b:块设备文件(block),比如硬盘。
c:字符设备文件(character),比如键盘鼠标。
s:套接字文件(sockets),通常出现在网络数据连接阶段。
p:管道文件(pipe)。

chgrp: (charge group) 改变文件的属组属性
chgrp [opt] 属组名 文件名
opt:
• -R #递归更改文件属组,该目录下的所有文件的属组都会更改,不带的话只会修改当前文件夹的属组。
chown: (change owner)改变文件的拥有者
语法:
chown [--R] 属主名 文件名
chown [-R] 属主名:属组名 文件名
将主目录的test 的拥有者改为 bin 这个账号:
[root@ubuntu ~]# cd ~
[root@ubuntu ~]# chown bin test
[root@ubuntu ~]# ls -l
-rw-r--r-- 1 bin users 124 Jan 13 13:31 test
将 test 的拥有者与群组改回为 root:
[root@ubuntu ~]# chown root:root test
[root@ubuntu ~]# ls -l
-rw-r--r-- 1 root root 124 Jan 13 14:01 test
chmod: 更改文件 或目录的访问权限。Linux 文件属性可以通过数字设置,也可以通过符号设置,基本权限有九个,分别是owner/group/others( 拥有者 / 组/ 其他)的 read/write/execute( 读取/ 写入/ 执行)权限,各个权限的分数为(r=4, w=2, x=1),没有权限的分数为0。
语法:
chmod [opt] xyz 文件或文件夹
opt:
• xyz:rwx 属性数值的和。
• -R:进行递归的变更,子文件夹于子文件也会一并被修改。
owner = rwx = 4+2+1 = 7
group = r-x = 4+0+1 = 5
others = rw- = 4+2+0 = 6
将 test 这个文件所有的权限都设定启用:
[root@ubuntu ~]# ls -al test
-rw-r--r-- 1 root root 269 Jan 13 14:14 test
[root@ubuntu ~]# chmod 777 test
[root@ubuntu ~]# ls -al test
-rwxrwxrwx 1 root root 269 Jan 13 14:15 test
通过符号改变权限的方法,u表示user用户,g表示group组,o表示 others其他,a表示all,即 u+g+o 的身份。
将文件权限设置为 -r-xr-xr-- ,使用 chmod u=rx,g=rx,o=r 文件名 设定:
[root@ubuntu ~]# touch test1 // 创建 test1 文件
[root@ubuntu ~]# ls -al test1 // 查看 test1 默认权限
-rw-r--r-- 1 root root 0 Jan 13 14:42 test1
[root@ubuntu ~]# chmod u=rx,g=rx,o=r test1 // 修改 test1 权限
[root@ubuntu ~]# ls -al test1
-r-xr-xr-- 1 root root 0 Jan 13 14:43 test1
将权限去掉:
[root@ubuntu ~]# chmod a-x test1
[root@ubuntu ~]# ls -al test1
-r--r--r-- 1 root root 0 Jan 13 14:44 test1
文件与目录管理
Linux 目录结构是一个树状结构,根目录 / 是所有目录的顶端,树的节点是可以增减的,通过挂载或卸载分别添加或删除节点。
绝对路径:由根目录 / 起,如: /home/aaa/music 这个目录。
相对路径:不是由根目录 / 起,如 cd ../movie,意思是由 /usr/aaa/music 到 /usr/aaa/movie 底下。
几个常见的处理目录与查看文件的命令:
• ls:(list files) 列出所有文件与文件夹。
• cd:(change directory) 切换路径。
• pwd:(print work directory) 显示目前的目录路径。
• mkdir:(make directory) 创建一个新的文件夹。
• rmdir:(remove directory) 删除一个文件夹。
• cp:(copy file) 复制文件或文件夹。
• rm:(remove) 移除文件或文件夹。
• mv:(move file) 移动文件或文件夹,或修改文件或文件夹的名称。
• cat: 打印出整个文件。
• tac: 倒着打印整个文件,可以看出 tac 是 cat 反过来写。
• nl: 打印的时候带上行号
• more: 通过键盘控制输出内容
• less: 与 more 的区别是可以向前翻页
• head: 只看头部几行
• tail: 只看尾部几行
(1)ls------列出文件与文件夹
[root@ubuntu ~]# ls [opt] 目录名称
opt:
• -a:列出所有文件,包括隐藏文件。
• -d:仅列出目录本身,不列出目录内的文件。
• -l:以列表形式列出文件和文件夹的详细信息。
将主目录下的所有文件列出来(包括属性与隐藏文件,~代表当前用户主目录,普通用户一般在 /home/用户名/ 这个文件夹下):
[root@ubuntu ~]# ls -al ~
(2)cd------切换路径
cd 是 Change Directory 的缩写,这是用来变换工作路径的命令。
语法:
cd [相对路径或绝对路径]
[root@ubuntu ~]# mkdir test #使用 mkdir 命令创建 test 目录
[root@ubuntu ~]# cd /root/test/ #使用绝对路径切换到 test 目录
[root@ubuntu ~]# cd ./test/ #使用相对路径切换到 test 目录
[root@ubuntu test]# cd ~ # 表示回到超级用户主目录,也就是 /root 这个目录
[root@ubuntu ~]# cd .. # 表示回到目前目录的上一级目录,也就是 /root 的上一级目录
(3)pwd------显示目前所在的目录
pwd 是 Print Working Directory 的缩写,打印当前目录的命令,在 shell 中比较常见。
语法:
[root@ubuntu ~]# pwd [opt]
opt:
• -P:显示出确实的路径,而非使用链接(link)路径。
显示目前的工作目录:
[root@ubuntu ~]# pwd
/root
显示出实际的工作目录,而非链接的目录名:
[root@ubuntu ~]# cd /var/mail #/var/mail 是一个链接目录
[root@ubuntu mail]# pwd
/var/mail #列出目前的工作目录
[root@ubuntu mail]# pwd -P
/var/test/mail #实际的目录
[root@ubuntu mail]# ls -ld /var/mail
lrwxrwxrwx 1 root root 10 Jan 17 13:10 /var/mail -> test/mail
#/var/mail 作为一个链接目录,链接到了/var/test/mail 上,所以实际目录为后者。
(4)mkdir------创建新目录
mkdir 是 make directory 的缩写,创建新的目录。
语法:
mkdir [opt] 目录名称
opt:
• -m:在创建目录的时候直接规定好文件夹权限。
• -p:递归创建多层目录。
在/root 文件夹下尝试创建多级目录:
[root@ubuntu ~]# cd ~
[root@ubuntu ~]# mkdir test #创建一名为 test 的新目录
[root@ubuntu ~]# mkdir test1/test2/test3/test4
mkdir: cannot create directory `test1/test2/test3/test4': No such file or directory
#不能直接创建多级目录
[root@ubuntu ~]# mkdir -p test1/test2/test3/test4 #加了 -p ,就能创建多级目录了
创建权限为 rwx--x--x 的目录:
[root@ubuntu ~]# mkdir -m 711 test2
[root@ubuntu ~]# ls -l
drwxr-xr-x 3 root root 4096 Jan 17 13:42 test
drwxr-xr-x 3 root root 4096 Jan 17 13:45 test1
drwx--x--x 2 root root 4096 Jan 17 13:47 test2
上面的权限部分,如果没有加上 -m 来强制配置属性,系统会使用默认属性。如果要手动分配权限,如上图
中的那个例子一样即可。
(4)rmdir------删除空目录
语法:
rmdir [opt] 目录名称
opt:
• -p:连同上一级的空目录也一起删除
[root@ubuntu ~]# rmdir test/ #删除 test 目录
将 mkdir 实例中创建的目录(/root 目录下)删除:
[root@ubuntu ~]# ls -l
drwxr-xr-x 3 root root 4096 Jan 17 13:42 test
drwxr-xr-x 3 root root 4096 Jan 17 13:45 test1
drwx--x--x 2 root root 4096 Jan 17 13:47 test2
[root@ubuntu ~]# rmdir test #可直接删除
[root@ubuntu ~]# rmdir test1 #因为不为空,所以无法删除
rmdir: `test1': Directory not empty
[root@ubuntu ~]# rmdir -p test1/test2/test3/test4
[root@ubuntu ~]# ls -l
drwx--x--x 2 root root 4096 Jul 18 12:54 test2
利用-p ,就可以将 test1/test2/test3/test4 一次性删除。此外rmdir 仅能删除 空的目录,如果是删除文件,可以使用 rm 命令来删除,rm 命令同样可以用来删除文件夹。
(5)cp------复制文件或目录
copy 的缩写,用于复制文件。
语法:
[root@ubuntu ~]# cp [opt] 来源档(source) 目标档(destination)
[root@ubuntu ~]# cp [opt] source1 source2 source3 .... directory
opt:
• -a:相当于 -dpr 的意思。(常用)
• -d:若为链接文件(link file),则复制链接文件的属性而非文件本身。
• -f:force 的缩写,强制的意思,若目标文件已经存在且无法开启,则会移除后再尝试一次,需要谨慎使用。
• -i:若目标文件已经存在时,在覆盖时会先询问。(常用)
• -l:进行硬链接(hard link)的连结档创建,而非复制文件本身。
• -p:连同文件的属性也一起复制过去。(备份常用)
• -r:递归复制,用于非空目录的复制。(常用)
• -s:复制为符号链接文件 (symbolic link)。
• -u:使用这项参数后只会在源文件的更改时间较目标文件新时,或是名称相互对应的目标文件并不存在时,才复制文件。
用 root 身份 将 root 目录下的 test 文件复制到/tmp 下,并命名为 test2
[root@ubuntu ~]# cp ~/test /tmp/test2
[root@ubuntu ~]# cp -i ~/test /tmp/test2
cp: overwrite `/tmp/test2'? n #选 n 不覆盖,y 覆盖
(6)rm------移除文件或目录
remove 的缩写,用于删除文件或文件夹。
语法:
rm [opt] 文件或目录
opt:
• -f:force 的缩写,强制删除。(常用)
• -i:互动模式,在删除前会先询问。
• -r:递归删除,可以删除空或非空的目录,谨慎使用。(常用)
将在 cp 的实例中创建的 test2 删除掉:
[root@ubuntu tmp]# rm -i test2 #加上 -i 的选项就会主动询问,避免误删。
rm: remove regular file `test2'? y
(7)mv------移动文件与目录 、 修改名称
move 的缩写,常用来移动文件,附带改名的功能。
语法:
[root@ubuntu ~]# mv [opt] source destination
[root@ubuntu ~]# mv [opt] source1 source2 source3 .... directory
opt:
• -f:force 的缩写,强制的意思,如果目标文件已经存在,则不再进行询问就直接覆盖。
• -i:若目标文件已经存在时,询问是否覆盖。
• -u:使用这项参数后只会在源文件的更改时间较目标文件新时,或是名称相互对应的目标文件并不存在时,才移动文件。
[root@ubuntu tmp]# mkdir mvtest #创建一目录,将文件移动到该目录中
[root@ubuntu tmp]# mv test mvtest
[root@ubuntu tmp]# mv mvtest mvtest2 #将目录名称更名为 mvtest2
(8)cat------ 从 第一行开始显示文件内容
语法:
cat [opt]
opt:
• -A:相当于-ETv 的组合选项。
• -b:列出行号,仅对非空白行做行号显示,空白行不标行号。
• -E:将结尾的断行字节用$显示出来。
• -n:列印出行号,连同空白行也会有行号。
• -T:将 Tab 按键以^I 显示出来。
• -v:列出一些打印不出来的特殊字符。
检看/proc/version 这个文件的内容:
[root@ubuntu ~]# cat /proc/version
Linux version 4.15.0-91-generic (buildd@lgw01-amd64-013) (gcc version 7.4.0 (Ubuntu7.4.0-1ubuntu1~18.04.1)) #92-Ubuntu SMP Fri Feb 28 11:09:48 UTC 2020
四、gcc
交叉编译就是在一个平台上生成另外一个平台上的可执行代码。在 win x64 下使用 VS 编译出exe 的过程我们称为本地编译 ,而在 win 下编译出其他架构系统下可执行文件的过程就是**交叉编译,**在 win 下生成 Linux 下 ARM 架构所可以执行的文件在 win 上运行不了。
严格来说,交叉编译器指的是交叉编译版本的 gcc,但我们常说的交叉编译器都是指交叉工具链,即常说的交叉编译版本的 gcc,比如 arm-linux-gnueabi-gcc,实际上指包含了一系列交叉编译版本的交叉工具链(编译器,链接器,汇编工具等)。
在所要运行的目标环境中 各种资源都相对有限,所以很难进行直接的本地编译。嵌入式一般代表了生产环境,对于一个需要大规模部署的项目,可能会有上万块的开发板需要配置。给每块开发板都装上编译工具的行为无疑是出力不讨好,使用交叉编译好的文件可以快速拷贝投入运营。
交叉编译的流程:要得到一个可执行文件,需要经历预处理、编译、汇编、链接 等流程,每个步骤都是可能由不同的工具来完成的,这些工具的集合就是交叉编译链。

预处理:对.c 文件进行处理生成 .c 的扩展文件 .i,这个文件可以被打开查看,可以看到原来的代码和大量的头文件,预处理的任务有以下几点:
• 包含头文件 :写在 include 内的所有头文件都会被包含进来,头文件内一般会存在大量的声明、宏定义,这些内容支持了代码的运行。因此,在编译前需要把这些内容与代码整合到一起再编译。
• 宏替换 :将宏替换为真实的内容,比如程序性中有使用 times 这个宏,那么这个宏的定义为#define times 1,程序中所有的 times 都会被替换为 1。
• 处理条件编译 :处理类似#if、#endif 之类的代码。
• 处理一些特殊的预处理关键字 。
编译:将 c 语言翻译成汇编语言 ,同时这个阶段也会进行语法检查 ,我们得到的 error 与 warning 都是在这个阶段给出的。.i 文件会被翻译成.s 的汇编文件,可以打开查看,学习过汇编的同学应该会很熟悉其中的代码指令。
汇编:将汇编翻译成纯二进制的机器指令,.s 文件被汇编成.o 文件,打开后全是二进制指令,基本就是完全看不懂了,不必深究其中内容的含义,需要底层优化的话使用汇编足矣。
链接 :目标.o 文件还不能被直接执行,链接阶段会将各个.o 文件链接成一个可执行文件,可执行文件在 win 下的后缀为.exe,Linux 下没有固定的执行文件后缀,一般约定以.out 后缀为文件后缀。链接阶段需要完成的事有以下几件:
• 将大量的.o 合成一个完整的可执行文件。 .o 实现相互依赖的,比如 a.o 中调用的函数,实现在了 b.o 中,如果不链接在一起的话,是无法工作的。
• 链接时 需要加入额外的启动代码。这个启动代码是编译器添加的,main 函数就是由启动代码调用的,而程序也是从启动代码 开始运行的。
• 链接为一个可执行文件时,需要进行符号解析和地址重定位。
两个常用 gcc 编译器gcc-arm-linux-gnueabi、 gcc-aarch64-linux-gnu。交叉编译器的命名规则与具体作用如下:
arch-core-kernel-system
• arch: 针对的目标平台。
• core: 使用的是哪个 CPU Core,如 Cortex A8,这一组命名比较灵活,可能是用硬件平台的名称来命名,也可能是 none。
• kernel: 所运行的 OS,常见的有 Linux,bare(无 OS)。
• systen:交叉编译链所选择的库函数和目标映像的规范,如 gnu,gnueabi 等。其中 gnu 等价于ibc+oabi,
gnueabi 等价于 glibc+eabi。
arm-linux-gnueabi-gcc 和 aarch64-linux-gnu-gcc 适用于 Arm Cortex-A 系列芯片,前者针对 32 位芯片,后者针对 64 位芯片,针对的都是 Linux,使用的是 glibc 库。
交叉编译器的使用:
语法:
gcc [opt] 文件名
gcc 文件名 #gcc 在当前自动生成名为 a.out 的可执行文件
opt:
• -o:FILE 生成指定名称的输出文件。
• -E:只运行 C 预编译器。
• -S:运行编译,将*.i 文件中源码转化为汇编代码*.s 文件
• -c:只编译并生成目标文件。
• -g:生成调试信息。GNU 调试器可利用该信息。
• -O0:不进行优化处理。
• -O1/-O:优化生成代码。
• -O2:进一步优化。
• -O3:比-O2 更进一步优化,包括 inline 函数。
• -w:不生成任何警告信息。
• -Wall:生成所有警告信息。
手动完成编译全流程:按照预处理、编译、汇编、链接的顺序用 gcc 来完整地模拟一遍。
gcc -E helloword.c -o helloword.i
gcc -S helloword.i -o helloword.s
gcc -c helloword.s -o helloword.o
gcc helloword.o -o helloword.out
通过 ls 指令,我们看到文件大了许多,因为预处理将头文件也包含进来了:

通过 cat helloword.i 我们可以看到宏定义的地方也已经被替换了,另外前面还加入了大段的头文件:

预处理阶段会将所有的注释都删除,所以仅仅是预处理完,我们就看不到代码的任何注释了。还有一点就是使用 gcc -E 的选项时,不搭配-o 选项时预处理文件会直接打印在终端内,而不会作为文件保存。
使用 ls 指令查看文件大小,汇编文件又变小了许多:

打开这个.s 文件,就是熟悉的汇编的味道了:

在这个指令中,即使不使用-o 选项,依然会在当前目录下产生.s 文件。在这个阶段,所有有关语法的错误都会被指出,只有语法通过了检查才会生成所需的汇编文件。
依旧使用 ls 查看文件列表:

编译阶段生成的是目标文件,里面包含了机器可以读懂的机器指令,因为.o 文件打开是一堆乱码,所以在此便不作展示。
使用 ls 查看文件列表,可执行文件 helloword.out 就产生了:

最后执行这个.out 文件,就能看见预期的结果:
