【代码1】应用眼中的操作系统;系统调用

这是 bilibili-[完结] 2020 南京大学 “操作系统:设计与实现” (蒋炎岩) 的课程笔记

本节内容概要:
- 一个最小的不依赖任何库函数的程序
	- 经过编译、链接,被操作系统加载
	- 调用操作系统API(系统调用)
- 粗浅地讲解了应用程序使用何种API实现
	- 编译器、图形界面程序等

什么是程序?

可执行文件(程序的二进制代码和数据)和其他数据文件

Linux支持多重可执行文件格式,ELF二进制文件是其中最常用的

file 命令查看文件信息

❯ vim a.c
❯ gcc -c a.c
❯ ls
a.c  a.o
❯ file a.c
a.c: C source, ASCII text
❯ file a.o
a.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
❯ gcc a.o
❯ file a.out
a.out: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=e4a5d3ec4e9319f61211fa13d0e1c32a7db7374d, for GNU/Linux 3.2.0, not stripped

运行中的程序成为进(正在运行的)程(程序)

  • 操作系统中会有很多进程对象 ps命令查看进程
  • 在运行时,进程会
    • 在CPU上执行,进行计算
    • 使用操作系统的API访问操作系统中的其他对象

ELF二进制文件

可执行文件也是普通的文件

  • 操作系统的一个对象

  • 一个存储在文件系统上的字节序列

    • 和文本文件没有本质区别

    • 操作系统提供API打开、读取、改写(都需要相应的权限)

    • 因此我们可以用xxd、 vim 、 cat 等命令查看可执行文件

      • 在vim中打开,二进制部分显示异常,但可以看到字符串常量(vim /bin/ls)
      • 使用xxd(命令分析工具)可以看到文件以 “\x7f” “ELF”开头
      ❯ xxd /bin/ls | less
      00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000  .ELF............
      00000010: 0300 3e00 0100 0000 1068 0000 0000 0000  ..>......h......
      00000020: 4000 0000 0000 0000 1834 0200 0000 0000  @........4......
      ...
      

解析ELF文件

readelf 是专门解析ELF可执行文件工具;我们主要关注:

  • header(元数据)
    • 文件内容分布
    • 指令集体系结构
    • 入口地址
  • ELF的program headers 决定了ELF如何被加载
❯ readelf -h /bin/ls
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Shared object file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x6810 # 第一条指令的位置
  Start of program headers:          64 (bytes into file)
  Start of section headers:          144408 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         13
  Size of section headers:           64 (bytes)
  Number of section headers:         31
  Section header string table index: 30

/usr/include/elf.h 提供了必要的定义

应用程序如何调用操作系统?

失败的尝试#1

假设我们要写一个最小的程序,只输出一句话

#include<stdio.h>
int main(){
   
        printf("hello world!\n");
}
❯ gcc -c hello.c
❯ ld hello.o
ld: warning: cannot find entry symbol _start; defaulting to 0000000000401000
ld: hello.o: in function `main':
hello.c:(.text+0x10): undefined reference to `puts'
# 我们已经引入了相关的库了,为什么还报错?而且为什么是 puts 不是 printf ?

为什么是puts?

  • gcc 在 -00 选项下依然会进行一定程度的编译优化
  • 这是导致一些编译器bug 的源头

undefined reference to `puts’

  • puts是库函数
  • 把库函数也链接进来就不是我们要写的最小的程序了
  • 放弃这个写法

cannot find entry symbol _start

  • _start是连接器默认的入口
  • 可以用 -e 指定 比如 -e main
失败的尝试#2

我们连这一句话也不输出了

int main(){
   
}

这样总行了吧?

❯ vim hello.c
❯ gcc -c hello.c
❯ objdump -d hello.o

hello.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <main>:
   0:	f3 0f 1e fa          	endbr64 
   4:	55                   	push   %rbp
   5:	48 89 e5             	mov    %rsp,%rbp
   8:	b8 00 00 00 00       	mov    $0x0,%eax
   d:	5d                   	pop    %rbp
   e:	c3                   	retq   
❯ ld -e main hello.o
❯ ./a.out
[1]
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值