操作系统基本概念[1]

1:程序的运行
程序设计语言----------->编译器,链接器---------->机器语言----------->操作系统加载到内存中(文件系统,内存管理)---------->操作系统任务管理与任务调度------------>操作系统输入输出------------------->结果
看到程序运行的结构图,不由得想到C语言编译过程
C语言过程如下:
.c.h文件-——>预处理——>.i文件——>编译器——>.s文件——>汇编器——>.o文件——>链接器对.so.a文件链接——>执行文件。
以linux gcc为例:(system :Ubuntu 14.04, gcc version:4.8.2 )
如程序代码mynum.c
#include <stdio.h>


#define mynum 123456789


int main(void)
{
printf("%d\n",mynum);
return 0;
}
经过gcc -E mynum.c -o mynum.i可得如下内容


# 2 "mynum.c" 2


int main(void)
{
printf("%d\n",123456789);
return 0;
}实现了预处理


在此基础上进行编译,gcc -S mynum.i -o mynum.s,得到汇编文件如下
 
.file "mynum.c"
.section .rodata
.LC0:
.string "%d\n"
.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 $123456789, %esi
movl $.LC0, %edi
movl $0, %eax
call printf
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"
.section .note.GNU-stack,"",@progbits
再对其生成目标文件 gcc -c mynum.s -o mynum.o,此时利用vim打开或者用cat显示mynum.o为乱码
gcc mynum.o -o mynum 即生成执行文件 此时文件格式为elf  如果使用交叉编译,生成的执行文件格式一般为二进制文件
链接过程在哪呢?利用命令readelf -d mynum 我们可知我们动态链接库位libc.so.6,其实gcc 默认使用的就是童泰链接
2:程序的内存布局
===================================一下内容根据国嵌Linux应用程序地址布局
小端模式下  
代码段 数据段 BSS段 堆 栈 堆先上增长,栈向下增长
我们可以通过编写代码查看数据是如何在内存分配的
其中memory.c代码如下
#include <stdio.h>
#include <stdlib.h>




int global_init_a = 1;
int global_uinit_a;
static int static_global_init_a = 1;
static int static_global_uinit_a;
const int const_global_a = 1;




int global_init_b = 1;
int global_uinit_b;
static int static_global_init_b = 1;
static int static_global_uinit_b;
const int const_global_b = 1;




int main(void)
{
        int local_init_a = 1;
        int local_uinit_a;
        static int static_local_init_a = 1;
        static int static_local_uinit_a;
        const int const_local_a = 1;




        int local_init_b = 1;
        int local_uinit_b;
        static int static_local_init_b = 1;
        static int static_local_uinit_b;
        const int const_local_b = 1;




        int* malloc_p_a;
        malloc_p_a = malloc(sizeof(int));




        printf("&global_init_a = %p,                  global_init_a = %d\n",&global_init_a,global_init_a);
        printf("&global_uinit_a = %p,                 global_uinit_a = %d\n",&global_uinit_a,global_uinit_a);
        printf("&static_global_init_a = %p,           static_global_init_a = %d\n",&static_global_init_a,static_global_init_a);
        printf("&static_global_uinit_a = %p,          static_global_uinit_a = %d\n",&static_global_uinit_a,static_global_uinit_a);
        printf("&const_global_a = %p,                 const_global_a = %d\n",&const_global_a,const_global_a);




        printf("&local_init_a = %p,                   local_init_a = %d\n",&local_init_a,local_init_a);
        printf("&local_uinit_a = %p,                  local_uinit_a = %d\n",&local_uinit_a,local_uinit_a);
        printf("&static_local_init_a = %p,            static_local_init_a = %d\n",&static_local_init_a,static_local_init_a);
        printf("&static_local_uinit_a = %p,           static_local_uinit_a = %d\n",&static_local_uinit_a,static_local_uinit_a);
        printf("&const_local_a = %p,                  const_local_a = %d\n",&const_local_a,const_local_a);




        while(1);
        return 0;
}
在linux下利用 cat /proc/memory进程号/maps查看代码段 数据段 BSS段 堆 栈的地址范围,再由memory各种类型打印的地址对应存储区域
08048000-08049000 r-xp 00000000 08:01 1052508    /home/liuyanhit/memory//代码段
08049000-0804a000 r--p 00000000 08:01 1052508    /home/liuyanhit/memory
0804a000-0804b000 rw-p 00001000 08:01 1052508    /home/liuyanhit/memory//数据段
08a7f000-08aa0000 rw-p 00000000 00:00 0          [heap]//堆
b7519000-b751a000 rw-p 00000000 00:00 0 
b751a000-b76c3000 r-xp 00000000 08:01 394206     /lib/i386-linux-gnu/libc-2.19.so
b76c3000-b76c5000 r--p 001a9000 08:01 394206     /lib/i386-linux-gnu/libc-2.19.so
b76c5000-b76c6000 rw-p 001ab000 08:01 394206     /lib/i386-linux-gnu/libc-2.19.so
b76c6000-b76c9000 rw-p 00000000 00:00 0 
b76dd000-b76e0000 rw-p 00000000 00:00 0 
b76e0000-b76e1000 r-xp 00000000 00:00 0          [vdso]
b76e1000-b7701000 r-xp 00000000 08:01 394182     /lib/i386-linux-gnu/ld-2.19.so
b7701000-b7702000 r--p 0001f000 08:01 394182     /lib/i386-linux-gnu/ld-2.19.so
b7702000-b7703000 rw-p 00020000 08:01 394182     /lib/i386-linux-gnu/ld-2.19.so
bfadc000-bfafd000 rw-p 00000000 00:00 0          [stack]//栈


&global_init_a = 0x804a024,                  global_init_a = 1//数据段
&global_uinit_a = 0x804a03c,                 global_uinit_a = 0//数据段
&static_global_init_a = 0x804a028,           static_global_init_a = 1//数据段
&static_global_uinit_a = 0x804a034,          static_global_uinit_a = 0//数据段
&const_global_a = 0x8048630,                 const_global_a = 1//代码段
&local_init_a = 0xbfafbdf0,                   local_init_a = 1//栈
&local_uinit_a = 0xbfafbdf4,                  local_uinit_a = -1217388544//栈
&static_local_init_a = 0x804a02c,            static_local_init_a = 1//数据段
&static_local_uinit_a = 0x804a038,           static_local_uinit_a = 0//数据段
&const_local_a = 0xbfafbdf8,                  const_local_a = 1//栈
最后发现
1.代码段:代码,全局常量(const)、字符串常量
2.数据段:全局变量(初始化以及未初始化的)、静态变量(全局的和局部的、初始化的以及未初始化的)
3.堆:动态分配的区域
4.栈:局部变量(初始化以及未初始化的,但不包含静态变量)、局部只读变量(const)






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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值