不同操作系统下的程序入口点分析
2011-08-22 10:05
459 查看
转自 http://hi.baidu.com/liu_bin0101/blog/item/03e3a9ec4e0fd5d72e2e21b9.html
程序入口与编译器没有什么关系, 关键是链接链接器(UNIX的用的ld和WINDOWS下用的LINK.EXE)
ld 用参数-e entry参数指定程序入口为entry
LINK.EXE 用/ENTRY:symbol指定程序入口为symbol
通常, ld/LINK.EXE 不是被直接运行的, 而是由编译器用适当的参数去调用的.
C/C++编译器的完成编译之后会用适当的参数去调用ld/LINK.EXE告诉链接器程序的入口.
WINDOWS下VC编译的程序程序入口点是WinMainCRTStartup(/SUBSYSTEM:WINDOWS, WIN32 GUI 程序)或mainCRTStartup(/SUBSYSTEM:CONSOLE 即WIN32控制台程序).
UNIX下cc/gcc设置的缺省程序入口是_start.
不论是WinMainCRTStartup, mainCRTStartup还是_start, 在链接器生成可执行程序之后, 入口点信息都保存在可执行文件中了.
WinMainCRTStartup, mainCRTStartup或_start函数都是由C标准库实现的, 这些里面通常做一些初始化工作, 包括一些需要用汇编语言才能完成的工作, 然后调用的main函数(WIN32 GUI 程序是WinMain).
这个过程可以用一个例子来说明, 下面是FreeBSD 6.2 的libc的crt1.c, 里面有_start函数的实现:
C/C++ code
C/C++ code
这个程序在FreeBSD 6.2 和Fedora Core 6上可以用下面的命令编译, 也可以运行.
gcc -c entry_start.c
ld -o entry_start -static -e _start entry_start.o -lc
但是在运行Loongson Debian Linux V4.0的龙芯福珑迷你(龙芯2E处理器)的机器上会core dump,
原因应该是没有初始化C运行环境而调用了C库函数引起的. 毕竟这不是写C程序的正规方法
程序入口与编译器没有什么关系, 关键是链接链接器(UNIX的用的ld和WINDOWS下用的LINK.EXE)
ld 用参数-e entry参数指定程序入口为entry
LINK.EXE 用/ENTRY:symbol指定程序入口为symbol
通常, ld/LINK.EXE 不是被直接运行的, 而是由编译器用适当的参数去调用的.
C/C++编译器的完成编译之后会用适当的参数去调用ld/LINK.EXE告诉链接器程序的入口.
WINDOWS下VC编译的程序程序入口点是WinMainCRTStartup(/SUBSYSTEM:WINDOWS, WIN32 GUI 程序)或mainCRTStartup(/SUBSYSTEM:CONSOLE 即WIN32控制台程序).
UNIX下cc/gcc设置的缺省程序入口是_start.
不论是WinMainCRTStartup, mainCRTStartup还是_start, 在链接器生成可执行程序之后, 入口点信息都保存在可执行文件中了.
WinMainCRTStartup, mainCRTStartup或_start函数都是由C标准库实现的, 这些里面通常做一些初始化工作, 包括一些需要用汇编语言才能完成的工作, 然后调用的main函数(WIN32 GUI 程序是WinMain).
这个过程可以用一个例子来说明, 下面是FreeBSD 6.2 的libc的crt1.c, 里面有_start函数的实现:
C/C++ code
/* LINTLIBRARY */ /*- * Copyright 1996-1998 John D. Polstra. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef lint #ifndef __GNUC__ #error "GCC is needed to compile this file" #endif #endif /* lint */ #include <stdlib.h> #include "libc_private.h" #include "crtbrand.c" extern int _DYNAMIC; #pragma weak _DYNAMIC typedef void (*fptr)(void); extern void _fini(void); extern void _init(void); extern int main(int, char **, char **); extern void _start(char *, ...); #ifdef GCRT extern void _mcleanup(void); extern void monstartup(void *, void *); extern int eprol; extern int etext; #endif char **environ; const char *__progname = ""; static __inline fptr get_rtld_cleanup(void) { fptr retval; #ifdef __GNUC__ __asm__("movl %%edx,%0" : "=rm"(retval)); #else retval = (fptr)0; /* XXXX Fix this for other compilers */ #endif return(retval); } /* The entry function. */ void _start(char *ap, ...) { fptr cleanup; int argc; char **argv; char **env; const char *s; #ifdef __GNUC__ __asm__("and $0xfffffff0,%esp"); #endif cleanup = get_rtld_cleanup(); argv = ≈ argc = *(long *)(void *)(argv - 1); env = argv + argc + 1; environ = env; if (argc > 0 && argv[0] != NULL) { __progname = argv[0]; for (s = __progname; *s != '\0'; s++) if (*s == '/') __progname = s + 1; } if (&_DYNAMIC != NULL) atexit(cleanup); else _init_tls(); #ifdef GCRT atexit(_mcleanup); #endif atexit(_fini); #ifdef GCRT monstartup(&eprol, &etext); #endif _init(); exit( main(argc, argv, env) ); } #ifdef GCRT __asm__(".text"); __asm__("eprol:"); __asm__(".previous"); #endif __asm__(".ident\t\"$FreeBSD: src/lib/csu/i386-elf/crt1.c,v 1.14 2005/05/19 07:36:07 dfr Exp $\""); 至于楼主想知道的"如何让没有main函数的C程序变成可执行文件?" 涉及到自己链接给链接程序传参数, 有一个例子可以试试.
C/C++ code
/*- * name: entry_start.c * auth: mymtom * date: 2008-02-18 */ #include <unistd.h> #include <string.h> void _start(void) { (void)write(1, __func__, strlen(__func__)); (void)write(1, "\n", 1); _exit(0); }
这个程序在FreeBSD 6.2 和Fedora Core 6上可以用下面的命令编译, 也可以运行.
gcc -c entry_start.c
ld -o entry_start -static -e _start entry_start.o -lc
但是在运行Loongson Debian Linux V4.0的龙芯福珑迷你(龙芯2E处理器)的机器上会core dump,
原因应该是没有初始化C运行环境而调用了C库函数引起的. 毕竟这不是写C程序的正规方法
相关文章推荐
- 不同操作系统下的程序入口点分析
- Linux下生产者消费者问题详细分析(操作系统期中考试论文---并发程序的同步和互斥)
- caffe caffe.cpp 程序入口分析
- linux启动分析---C程序入口函数start_kernel
- Linux操作系统分析-lab2-进程的创建与可执行程序的加载
- 前言 我们知道不同的操作系统有各自的文件系统,这些文件系统又存在很多差异,而Java 因为是跨平台的,所以它必须要统一处理这些不同平台文件系统之间的差异,才能往上提供统一的入口。 关于FileSy
- 第二人生的源码分析(3)程序入口点
- linux的64位操作系统对32位程序的兼容-全面分析
- PHPCMS V9 框架代码分析(入口程序)
- 第二人生的源码分析(3)程序入口点
- linux的64位操作系统对32位程序的兼容-全面分析
- Linux操作系统分析-(2)进程的创建与可执行程序的加载
- Linux内核分析课程--完成一个简单的时间片轮转多道程序内核代码,理解操作系统是如何工作的
- C++第三方程序包在不同操作系统下的使用
- 关于monkey测试通过不同入口Intent启动app引起的anr分析
- Linux操作系统分析-lab2-进程的创建与可执行程序的加载
- Mongodb源码分析--主程序入口main()
- Flume 1.7 源码分析(三)程序入口
- 关于不同的程序入口,main(), _tmain(),WinMain(),wmain()?
- Mongodb源码分析--主程序入口main()