从源程序到可执行程序


📝 概述

程序的开发与执行涉及计算机的各个不同层面。我们在编写好程序后通常是被称为用户程序(user program)或应用程序(application program)。

我们以最常使用,也是很经典的C源程序为例,逐步刨析程序的执行过程,源程序如何成功再计算机上运行,中间到底有多少细节。

为了更好的逐步看清执行过程,我们将在Linux系统环境下进行C程序的预处理、编译、汇编、连接,最终将生成可执行目标文件。GCC编译驱动程序对程序进行处理


📝 连接Linux

随着技术不断发展,对于萌新小白来讲,利用SSH来连接到远端Linux系统并没有想象中那么复杂。

Secure Shell(SSH) 是由 IETF(The Internet Engineering Task Force) 制定的建立在应用层基础上的安全网络协议。它是专为远程登录会话(甚至可以用Windows远程登录Linux服务器进行文件互传)和其他网络服务提供安全性的协议,可有效弥补网络中的漏洞。通过SSH,可以把所有传输的数据进行加密,也能够防止DNS欺骗和IP欺骗。还有一个额外的好处就是传输的数据是经过压缩的,所以可以加快传输的速度。目前已经成为Linux系统的标准配置。

SSH只是一种协议,存在多种实现,既有商业实现,也有开源实现。

显然我们是想要更加简单易用的方式编写test.c程序,并且可以通过gcc命令编译我们的源程序。下面将分享一种傻瓜式的操作方法,我们使用Visual Studio Code来连接远程的Linux主机。

下面以Windows用户为例(作者本人也是虚拟机选手)


  1. 安装VMware

  2. 下载好Centos 7 镜像文件或者 Ubuntu 20以上版本(当然根据自身情况选择版本)

  3. 在VMware里新建虚拟机,使用Centos或者Ubuntu都可以(这里我们使用Centos为例)

注意(以下几点务必设置准确无误):

  • 虚拟机网络适配器选择NAT
    在这里插入图片描述

  • 进入系统后打开远程连接(其实在安装好Centos后系统会默认打开远程连接)

在这里插入图片描述


🌟 配置VSCode中的SSH文件

在拓展商店里搜索Remote-SSH插件,并安装

在这里插入图片描述

安装好后在左侧窗口会显示远程资源管理器,点击进入,在上方的命令窗口输入>Remote-SSH

在这里插入图片描述

选择连接主机,ssh root@ip地址得到一个要连接的目标主机,接下来命令窗口将自动提示配置SSH文件

在这里插入图片描述

到这里不需要其他任何操作,进入config配置文件:

Host 主机名(无所谓,只是标识这份创建的主机)
    HostName 服务器的IP地址
    User root  你的Linux用户名称(注意这里务必准去无误,且必填)
    Port 22  连接的端口号(这里不需要更改,默认就行,当然如果考虑到安全可以根据需求设定)

下面进入Centos系统,打开终端

  1. 安装openssh-server服务(注意这一步可以忽略,因为现在一般来讲系统是默认安装好的)

systemctl start sshd.service #启动ssh服务

systemctl restart sshd.service #重启ssh服务

systemctl enable sshd.service #开机ssh自启

  1. 得到Linux主机的IP地址

    在终端中输入命令:ifconfig

    第一栏里找到下图所在位置

在这里插入图片描述

inet即为当前主机的IP地址,记下来并写到VSCode里的HostName后面

在这里插入图片描述

在VMWare的Centos右击编辑配置SSH,将里面的端口设置为默认的22,用户名根据自己创建虚拟机
的情况设定,这是要与VSCode里User选项填写一致。

在这里插入图片描述

🌟 建立连接

找到右侧新建连接,接下来在新窗口里底部终端将会提示输入密码(这里密码不是Centos的锁屏密

码,是带有字母数字符号的用户密码,这是在安装Centos完成后强制需要你设定的)

在这里插入图片描述
到这里就说明连接成功了,那么左下角也将会显示你连接到的主机名称。之后回到资源管理器,就已
经提示连接到了远程服务器,打开文件夹就是在你虚拟机里的Centos系统的文件夹,一般选择把整个
根目录都打开,便于后续程序编写执行。


📝 创建文件

在右侧加号+ 新建一个终端
在这里插入图片描述

在VSCode里创建一个test.c文件并保存

在这里插入图片描述
如果我们直接将test.c文件编译一步到位,那么在命令行输入如下指令:

gcc test.c

结果会生成一个a.out文件,这是一个二进制文件,使用vim来打开看:vim a.out,结果如下:
在这里插入图片描述


📝从源程序到可执行程序

!!!对于整个过程详解如下:
在这里插入图片描述

当我们在VS里看到LNK报错时,一般都是链接阶段出现错误。

  1. 预处理 选项 gcc -E test.c -o test.i
    预处理完成之后就停下来,预处理之后产生的结果都放在test.i文件中。(预处理完成后其本质还是C代码)

在这里插入图片描述

  1. 编译 选项 gcc -S test.c
    编译完成之后就停下来,结果保存在test.s中。(形成汇编代码)
	.file	"test.c"
	.section	.rodata
.LC0:
	.string	"hello world "
	.text
	.globl	main
	.type	main, @function
main:
.LFB0:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	movl	$.LC0, %edi
	call	puts
	movl	$0, %eax
	popq	%rbp
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE0:
	.size	main, .-main
	.ident	"GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-44)"
	.section	.note.GNU-stack,"",@progbits

  1. 汇编 gcc -c test.c
    汇编完成之后就停下来,结果保存在test.o中。
    (读取查看elf格式的文件)
readelf test.o -s

在这里插入图片描述


📝 运行环境

最终的可执行文件保存在磁盘上,可以以某种方式启动该文件并执行。

程序执行的过程:

  1. 程序必须载入内存中。在有操作系统的环境中:一般这个由操作系统完成。在独立的环境中,程序的载入必须由手工安排,也可能是通过可执行代码置入只读内存来完成。

  2. 程序的执行便开始。接着便调用main函数。

  3. 开始执行程序代码。这个时候程序将使用一个运行时堆栈(stack),存储函数的局部变量和返回
    地址。程序同时也可以使用静态(static)内存,存储于静态内存中的变量在程序的整个执行过程
    一直保留他们的值。

  4. 终止程序。正常终止main函数;也有可能是意外终止。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值