
开发后端有很多的编程语言,目前比较流行的就是python ,c,cpp,java,js,php,rust,golang ..

在互联网公司,后端用用的服务器主要是Linux 操作系统为主,发行版本有很多,但都是Linux,架构都是X86的指令集。


java,rust,golang,php,python,c,c++等语言它们的可执行文件里的内容都是按照Linux os的ELF格式进行封装。
比如PHP的可执行程序【解释器】

比如JAVA的可执行文件【用于执行JAVA程序】

比如GOLANG的可执行文件【用于编译GO程序】


ELF文件是编译器,或是汇编器生成二进制文件【ELF】时,会按照ELF的要求及Intel X86指令要求生成文件,文件里存储的主要是程序指令+程序数据+其它数据,程序指令主要是用户编写的代码+系统提供的代码【或是库提供的封装函数】
go编程语言在Linux os 的运行
程序编写完以后,不论是作为解释器的输入,还是作为编译器的输入得到的可执行文件,总之都要装载到内存中由CPU取出ELF装载到内存的指令执行,说白了就是不管是什么程序,都要装载到内存中执行,那么在LINUX系统中主要是在终端启动,比如我们编写了一个GOLANG程序如下
//demo.go package main
import "fmt"
func main(){
var vx string="Le-studyg" // 在进程内存里找个地方,存储数据 同时通过vx变量绑定 fmt.Println("hello:"+vx) // 虽然用了fmt库,但程序工作时,调用了Linux os 的系统调用函数write
}
然后我们编译并在在Linux终端进程【控制进程】执行它
编译后得到的文件是ELF文件,ELF文件的程序指令即为X86-64指令集的指令。

然后我们启动程序执行并观察它调用了Linux 系统调用接口API

在Linux终端输入【控制进程会接收我们的输入并回显】: ./demo
同时我们能看到启动执行的过程,进程会调用execve系统调用函数帮我装载demo可执行文件,同时调用了write系统调用函数,此函数的功能就是向参数1【标准输出】写入数据"hello:Le-studyg\n"的内容,就是向屏幕输出一段数据。
int execve(const char *filename, char *const argv[],
char *const envp[]);//用于启动装载一个程序
ssize_t write(int fd, const void buf, size_t count);//用于向一个文件fd写入数据
那么我们的GO程序在Linux上从编译到启动执行,退出的过程就是这样的。

java程序在Linux os 上的运行
我们编写一段简单的java程序
//demo.java
public class demo {
public static void main(String[] args) {
System.out.println("Hello World");
}
}
同样的,我们也在Linux os 编译一下它,同时观察它调用了Linux os的系统调用函数


execve("/home/soft/jdk1.8.0_261/bin/java", ["java", "demo"], 0x55b6b83b23e0 /
32 vars */) = 0
//第一个参数是ELF 可执行文件,第二个参数是数组,数组的第二个值是demo.class
///home/soft/jdk1.8.0_261/bin/java 会打开demo.class 文件读取内容并解释执行它。
rust 编程语言在Linux os 的运行
fn main() {
println!("Hello World!");
}
编译后文件是ELF文件

启动示例程序

同样的也是execve,write系统调用函数。
php编程语言在Linux os 的运行
//demo.php
<?php$name="vx:Le-studyg";
echo $name;
同样的我们启动执行它。

execve("/home/soft/php/bin/php", ["/home/soft/php/bin/php", "demo.php"], 0x55b6b83b23e0 /* 32 vars */) = 0
write(1, "vx:Le-studyg", 12) = 12
///home/soft/php/bin/php 为ELF可执行文件,读取后面的参数脚本文件demo.php然后打开读取内容解释执行
Linux os 系统调用函数
上面我们演示了golang,java,rust,php编程语言【其它编程语言也是一样】,它们启动到运行都是调用了Linux 的系统函数execve,write,【其实linux 的系统调用函数很多】这些函数都是固定的【函数名,功能,参数数量】都是固定的。
像execve,write系统调用函数在linux0.1版本【1991年发布的操作系统】就已经提供了。


2011年的linux版本3也是一直存在的


我们再看一下阿里云服务器【百度云,腾讯云都一样】Linux的系统调用

系统调用的使用
主要是通过控制X86 CPU的几个寄存器和指令syscall,x86是int指令来实现对系统调用的使用。
这里我们看java和golang的系统调用【其它编程语言全都一样】
java运行的底层指令

golang运行的底层指令

rsp寄存器的值上【内存上的数据】
0xc000066cd0: 0x5a 0xcc 0x48 0x00 0x00 0x00 0x00 0x00
0xc000066cd8: 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0xc000066ce0: 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0xc000066ce8: 0x10 0x81 0x01 0x00 0xc0 0x00 0x00 0x00
0xc000018110: "hello:Le-studyg\n"
所有编程语言的核心总结

应用层的生态千变万化,而它们的背后本质就是X86,千举万变,其道一也。
时间宝贵,无法在此处一一详细的说了,如有兴趣可以评论交流讨论学习。