redhat 6.5 gcc编译器初识之一

测试结论
1,gcc是编译器,分为4个阶段


2,4个阶段为
预处理阶段


编译阶段


汇编阶段


链接阶段


3,预处理阶段为 即把stdio.h头文件内容编译进来


4,编译阶段为GCC首先要检查代码的规范性,是否有语法错误,以确定代码实际要作的工作,在检查无误后,
GCC把代码编译成汇编代码


5,GCC第3个阶段即GCC的汇编阶段,即把上述GCC第2个阶段产生的.S文件转化成目标文件


6,GCC第4个阶段,即进入GCC的链接阶段。在这里涉及一个重要的概念:函数库
我们可以再次查看这个小程序即helloworld.c,在这个程序中并没有定义printf函数的实现,
且在其预编译包含进来的头文件stdio.h中也只有这个函数的声明,而没有这个函数的实现,那么到底在哪儿实现
printf函数的呢。答案是:操作系统会把这些函数实现都作到一个名为libc.so.6的库文件中去了,如果在没有特别指定时,
GCC会到操作系统默认的路径即/USR/LIB查找,也就是说会去链接到这个路径的LIBC.SO.6库函数中,这样最终就可以实现函数PRINTF的功能了


7,函数库一般分2处类型:
静态库和动态库


静态库是指在编译链接时,把库文件的代码会全部加入到可执行文件中,因此生成的文件会比较大,但在运行时也就不需要库文件了,其后缀一般为.a,




动态库,与静态库相反,在编译链接时,并没有把库文件的代码加入到可执行文件中,而是在程序执行时链接文件加载库,这样就可以节省系统的开销,
动态库一般后缀为.SO,如前述LIBC.SO.6就是动态库。


GCC在编译时默认采用动态库






测试明细
1,操作系统版本
[root@mygirl ~]# more /etc/redhat-release 
Red Hat Enterprise Linux Server release 6.5 (Santiago)
[root@mygirl ~]# 


2,编写一个helloworld.c源代码文件
[root@mygirl ~]# pwd
/root
[root@mygirl ~]# 


clude
int main() {
   printf("hello world!\n");
   return 0;
}
[root@mygirl ~]# 


3,进行gcc 4个阶段第一个阶段 预处理阶段,即把stdio.h头文件内容编译进来


[root@mygirl ~]# gcc -E helloworld.c -o helloworld.i
[root@mygirl ~]# 


[root@mygirl ~]# ll hel*
-rw-r--r--. 1 root root    76 Jun 30 06:20 helloworld.c
-rw-r--r--. 1 root root 16751 Jun 30 06:22 helloworld.i


4,查看GCC预处理阶段产生的文件,可见此文件内容极多
[root@mygirl ~]# more helloworld.i|more
# 1 "helloworld.c"
# 1 ""
# 1 ""
# 1 "helloworld.c"
# 1 "/usr/include/stdio.h" 1 3 4
# 28 "/usr/include/stdio.h" 3 4
# 1 "/usr/include/features.h" 1 3 4
# 361 "/usr/include/features.h" 3 4
# 1 "/usr/include/sys/cdefs.h" 1 3 4
# 365 "/usr/include/sys/cdefs.h" 3 4
# 1 "/usr/include/bits/wordsize.h" 1 3 4
# 366 "/usr/include/sys/cdefs.h" 2 3 4
# 362 "/usr/include/features.h" 2 3 4
# 385 "/usr/include/features.h" 3 4
# 1 "/usr/include/gnu/stubs.h" 1 3 4






# 1 "/usr/include/bits/wordsize.h" 1 3 4
# 5 "/usr/include/gnu/stubs.h" 2 3 4








# 1 "/usr/include/gnu/stubs-64.h" 1 3 4
# 10 "/usr/include/gnu/stubs.h" 2 3 4
# 386 "/usr/include/features.h" 2 3 4
# 29 "/usr/include/stdio.h" 2 3 4


5,经查stdio.h头文件是把其内容通过GCC预处理阶段添加到其预处理的产生的文件中
[root@mygirl ~]# locate stdio.h
/oracle/product/11.2.0/db_1/perl/lib/5.10.0/x86_64-linux-thread-multi/CORE/nostdio.h
/usr/include/stdio.h
/usr/include/bits/stdio.h


[root@mygirl ~]# more /usr/include/stdio.h|more
/* Define ISO C stdio on top of C++ iostreams.
   Copyright (C) 1991, 1994-2008, 2009, 2010 Free Software Foundation, Inc.
   This file is part of the GNU C Library.


   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.


   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.


   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   02111-1307 USA.  */


/*
 *      ISO C99 Standard: 7.19 Input/output    
 */


#ifndef _STDIO_H


#if !defined __need_FILE && !defined __need___FILE
# define _STDIO_H       1
# include




6,进行gcc第二阶段之编译阶段,这个阶段就是GCC首先要检查代码的规范性,是否有语法错误,以确定代码实际要作的工作,在检查无误后,
GCC把代码编译成汇编代码
[root@mygirl ~]# ll helloworld.*
-rw-r--r--. 1 root root    76 Jun 30 06:20 helloworld.c
-rw-r--r--. 1 root root 16751 Jun 30 06:22 helloworld.i


[root@mygirl ~]# gcc -S helloworld.i -o helloworld.s
[root@mygirl ~]# 


[root@mygirl ~]# ll helloworld.*
-rw-r--r--. 1 root root    76 Jun 30 06:20 helloworld.c
-rw-r--r--. 1 root root 16751 Jun 30 06:22 helloworld.i
-rw-r--r--. 1 root root   448 Jun 30 06:38 helloworld.s




[root@mygirl ~]# more helloworld.s
        .file   "helloworld.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
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE0:
        .size   main, .-main
        .ident  "GCC: (GNU) 4.4.7 20120313 (Red Hat 4.4.7-4)"
        .section        .note.GNU-stack,"",@progbits






7,进行GCC第3个阶段即GCC的汇编阶段,即把上述GCC第2个阶段产生的.S文件转化成目标文件
/root
[root@mygirl ~]# ll helloworld.*
-rw-r--r--. 1 root root    76 Jun 30 06:20 helloworld.c
-rw-r--r--. 1 root root 16751 Jun 30 06:22 helloworld.i
-rw-r--r--. 1 root root   448 Jun 30 06:38 helloworld.s
[root@mygirl ~]# 
[root@mygirl ~]# 


8,进行GCC第4个阶段,即进入GCC的链接阶段。在这里涉及一个重要的概念:函数库
我们可以再次查看这个小程序即helloworld.c,在这个程序中并没有定义printf函数的实现,
且在其预编译包含进来的头文件stdio.h中也只有这个函数的声明,而没有这个函数的实现,那么到底在哪儿实现
printf函数的呢。答案是:操作系统会把这些函数实现都作到一个名为libc.so.6的库文件中去了,如果在没有特别指定时,
GCC会到操作系统默认的路径即/USR/LIB查找,也就是说会去链接到这个路径的LIBC.SO.6库函数中,这样最终就可以实现函数PRINTF的功能了
[root@mygirl ~]# gcc -c helloworld.s -o helloworld.o
[root@mygirl ~]# 
[root@mygirl ~]# 
[root@mygirl ~]# ll helloworld.*
-rw-r--r--. 1 root root    76 Jun 30 06:20 helloworld.c
-rw-r--r--. 1 root root 16751 Jun 30 06:22 helloworld.i
-rw-r--r--. 1 root root  1504 Jun 30 06:46 helloworld.o
-rw-r--r--. 1 root root   448 Jun 30 06:38 helloworld.s


[root@mygirl ~]# strings  helloworld.o
hello world!
[root@mygirl ~]# 






9,
函数库一般分2处类型:
静态库和动态库


静态库是指在编译链接时,把库文件的代码会全部加入到可执行文件中,因此生成的文件会比较大,但在运行时也就不需要库文件了,其后缀一般为.a,




动态库,与静态库相反,在编译链接时,并没有把库文件的代码加入到可执行文件中,而是在程序执行时链接文件加载库,这样就可以节省系统的开销,
动态库一般后缀为.SO,如前述LIBC.SO.6就是动态库。


GCC在编译时默认采用动态库




[root@mygirl ~]# ll helloworld.*
-rw-r--r--. 1 root root    76 Jun 30 06:20 helloworld.c
-rw-r--r--. 1 root root 16751 Jun 30 06:22 helloworld.i
-rw-r--r--. 1 root root  1504 Jun 30 06:46 helloworld.o
-rw-r--r--. 1 root root   448 Jun 30 06:38 helloworld.s
[root@mygirl ~]# 
[root@mygirl ~]# gcc helloworld.o -o helloworld
[root@mygirl ~]# 
[root@mygirl ~]# 
[root@mygirl ~]# ll helloworld.*
-rw-r--r--. 1 root root    76 Jun 30 06:20 helloworld.c
-rw-r--r--. 1 root root 16751 Jun 30 06:22 helloworld.i
-rw-r--r--. 1 root root  1504 Jun 30 06:46 helloworld.o
-rw-r--r--. 1 root root   448 Jun 30 06:38 helloworld.s
[root@mygirl ~]# 


[root@mygirl ~]# ll helloworld
-rwxr-xr-x. 1 root root 6430 Jun 30 06:58 helloworld
[root@mygirl ~]# 


10,查看GCC第4个阶段即GCC的链接阶段产生不代扩展名的文件名
[root@mygirl ~]# strings  helloworld
/lib64/ld-linux-x86-64.so.2
__gmon_start__
libc.so.6
puts
__libc_start_main
GLIBC_2.2.5
fff.
fffff.
l$ L
t$(L
|$0H
hello world!
[root@mygirl ~]# 


11,执行GCC第4个阶段产生的执行文件
[root@mygirl ~]# ./helloworld 
hello world!
[root@mygirl ~]# 




12,查看动态库文件


[root@mygirl ~]# locate libc.so.6
/lib/libc.so.6
/lib/i686/nosegneg/libc.so.6
/lib64/libc.so.6
/oracle/product/11.2.0/db_1/lib/stubs/libc.so.6




[root@mygirl ~]# strings  /lib/libc.so.6 |grep -i --color printf
vswprintf
__obstack_vprintf_chk
vasprintf
printf_size
__vfprintf_chk
vfwprintf
__vsprintf_chk




[root@mygirl ~]# more /oracle/product/11.2.0/db_1/lib/sysliblist 
-ldl -lm -lpthread -lnsl -lirc -lipgo -lsvml

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/9240380/viewspace-2141450/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/9240380/viewspace-2141450/

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值