前几天看了《程序员的自我修养——链接、装载与库》中的第二章“编译和链接”,主要根据其中的内容简单总结一下C程序编译的过程吧。
我现在一般都是用gcc,所以自然以GCC编译hellworld为例,简单总结如下。
hello.c源代码如下:
#include
<
stdio.h
>
main() { printf(“Hello, world.\n”);
return
; }
通常我们使用gcc来生成可执行程序,命令为:gcc hello.c,默认生成可执行文件a.out
其实编译(包括链接)的命令:gcc hello.c 可分解为如下4个大的步骤:
预处理(Preprocessing)
编译(Compilation)
汇编(Assembly)
链接(Linking)
1. 预处理(Preproceessing)预处理的过程主要处理包括以下过程:将所有的#define删除,并且展开所有的宏定义处理所有的条件预编译指令,比如#if #ifdef #elif #else #endif等处理#include 预编译指令,将被包含的文件插入到该预编译指令的位置。删除所有注释 “//”和”/* */”.添加行号和文件标识,以便编译时产生调试用的行号及编译错误警告行号。保留所有的#pragma编译器指令,因为编译器需要使用它们通常使用以下命令来进行预处理:gcc -E hello.c -o hello.i参数-E表示只进行预处理 或者也可以使用以下指令完成预处理过程cpp hello.c > hello.i /* cpp – The C Preprocessor */直接cat hello.i 你就可以看到预处理后的代码2. 编译(Compilation)编译过程就是把预处理完的文件进行一系列的词法分析,语法分析,语义分析及优化后生成相应的汇编代码。$gcc –S hello.i –o hello.s或者$ /usr/lib/gcc/i486-linux-gnu/4.4/cc1 hello.c注:现在版本的GCC把预处理和编译两个步骤合成一个步骤,用cc1工具来完成。gcc其实是后台程序的一些包装,根据不同参数去调用其他的实际处理程序,比如:预编译编译程序cc1、汇编器as、连接器ld可以看到编译后的汇编代码(hello.s)如下:
.file
"
hello.c
"
.section .rodata.LC0:.
string
"
Hello, world.
"
.text.globl main.type main, @functionmain:pushl
ebpmovl
esp,
ebpandl $
,
espsubl $
,
espmovl $.LC0, (
esp)call putsmovl $
,
eaxleaveret.size main, .
main.ident
"
GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3
"
.section .note.GNU
stack,
""
,@progbits
汇编器是将汇编代码转变成机器可以执行的命令,每一个汇编语句几乎都对应一条机器指令。汇编相对于编译过程比较简单,根据汇编指令和机器指令的对照表一一翻译即可。
$ gcc –c hello.c –o hello.o
$ as hello.s –o hello.co
由于hello.o的内容为机器码,不能以普通文本形式的查看(vi 打开看到的是乱码)。
4. 链接(Linking)
通过调用链接器ld来链接程序运行需要的一大堆目标文件,以及所依赖的其它库文件,最后生成可执行文件。
ld -static crt1.o crti.o crtbeginT.o hello.o -start-group -lgcc -lgcc_eh -lc-end-group crtend.o crtn.o (省略了文件的路径名)。
helloworld的大体编译和链接过程就是这样了,那么编译器和链接器到底做了什么呢?
编译过程可分为6步:扫描(词法分析)、语法分析、语义分析、源代码优化、代码生成、目标代码优化。
词法分析:扫描器(Scanner)将源代的字符序列分割成一系列的记号(Token)。lex工具可实现词法扫描。
语法分析:语法分析器将记号(Token)产生语法树(Syntax Tree)。yacc工具可实现语法分析(yacc: Yet Another Compiler Compiler)。
语义分析:静态语义(在编译器可以确定的语义)、动态语义(只能在运行期才能确定的语义)。
源代码优化:源代码优化器(Source Code Optimizer),将整个语法书转化为中间代码(Intermediate Code)(中间代码是与目标机器和运行环境无关的)。中间代码使得编译器被分为前端和后端。编译器前端负责产生机器无关的中间代码;编译器后端将中间代 码转化为目标机器代码。
目标代码生成:代码生成器(Code Generator).
目标代码优化:目标代码优化器(Target Code Optimizer)。
链接的主要内容是把各个模块之间相互引用的部分处理好,使得各个模块之间能够正确地衔接。
链接的主要过程包括:地址和空间分配(Address and Storage Allocation),符号决议(Symbol Resolution),重定位(Relocation)等。
链接分为静态链接和动态链接。
静态链接是指在编译阶段直接把静态库加入到可执行文件中去,这样可执行文件会比较大。
而动态链接则是指链接阶段仅仅只加入一些描述信息,而程序执行时再从系统中把相应动态库加载到内存中去。
静态链接的大致过程如下图所示:
编译服务端程序,报错信息如下:
[oracle@informix ora]$ buildserver -o test -f test.c -f${ORACLE_HOME}/lib/libclntsh.so -s TEST
test.c: In function `TEST':
test.c:294: structure has no member named `sqlerrm'
test.c:295: structure has no member named `sqlerrm'
test.c:346: structure has no member named `sqlerrm'
test.c:347: structure has no member named `sqlerrm'
CMDTUX_CAT:1832: ERROR: can't execute cc -m32 -I$TUXDIR/include -o test BS-2557.c -L${TUXDIR}/lib test.c /u01/oracle/lib/libclntsh.so -ltux -lbuft -lfml -lfml32 -lengine -ldl -lpthread
【解决方法】
经过查找。原来是这个原因:
重命名下列文件,因为下列TUXEDO文件名与ORACLE带的文件名有冲突,所以要改名。
(1)TUXEDO安装路径include目录下的下面文件
把sqlca.h 改名为 sqlca.h.bbb
把sqlcode.h 改名为 sqlcode.h.bbb
把sqlda.h 改名为 sqlda.h.bbb
(2)重命名TUXEDO安装路径lib目录下的下面文件
把libsql.a 改名为 libsql.a.bbb
把libsql.so 改名为 libsql.so.bbb
希望对大家有用!
【报错信息】tmboot报错如下: Booting admin processes ... exec BBL -A : process id=6993 ... Started. Booting server processes ... exec TMS_ORA -A : Failed. exec TMS_ORA -A : Failed. exec test -A : Failed. 1 process started. 【查看日志】 查找ULOG和xa_NULL*.trc发现日值这样描述: 084519.6668.0: xaogetmod: XAER_INVAL; Invalid xa_info string. ORACLE XA: Version 10.2.0.1.0. RM name = 'Oracle_XA'. 【分析原因】 显然是我的ubb中的OPENINFO这行配置有问题。 查看我ubb配置如下: OPENINFO="Oracle_XA:Oracle_XA+Acc=P/scott/tigger+SesTm=600+MaxCur=5+LogDir=.+DbgFl=" DbgFl不能等于空,要么指定数字,要么不写这个选项。 【解决问题】 修改ubb配置如下: OPENINFO="Oracle_XA:Oracle_XA+Acc=P/scott/tigger+SesTm=600+MaxCur=5+LogDir=.+DbgFl=15" 或者 OPENINFO="Oracle_XA:Oracle_XA+Acc=P/scott/tigger+SesTm=600+MaxCur=5+LogDir=."
posted @
2012-03-20 17:15 cpp 阅读(360) |
评论 (0) |
编辑
用sysdba帐户登陆,
SQL> conn / as sysdba
SQL> @$ORACLE_HOME/rdbms/admin/xaview.sql
DROP VIEW v$xatrans$
ERROR at line 1:
ORA-00942: table or view does not exist
DROP VIEW v$pending_xatrans$
ERROR at line 1:
ORA-00942: table or view does not exist
View created.
View created.
SQL> grant select on v$xatrans$ to public with grant option;
Grant succeeded.
SQL> grant select on v$pending_xatrans$ to public with grant option;
Grant succeeded.
SQL> grant select any table to public;
Grant succeeded.
二、TUXEDO的配置
1、修改$TUXDIR/udataobj/RM文件
把原来的以Oracle_XA:xaosw:开头的屏蔽掉、
添加Oracle_XA:xaosw:-L${ORACLE_HOME}/lib -lclntsh
2、创建TMS文件:TMS_ORA10g,TUXEDO通过TMS_ORA10g与ORACLE数据库采用XA协议进行通讯
buildtms -o $TUXDIR\bin\TMS_ORA10g -r Oracle_XA
这个地方要注意权限问题。
[tuxedo@brady udataobj]$ buildtms -o $TUXDIR/bin/TMS_ORA10g -r Oracle_XA
/usr/bin/ld: cannot find -lclntsh
collect2: ld returned 1 exit status
CMDTUX_CAT:1832: ERROR: can't execute cc -I$TUXDIR/include -o /home/tuxedo/beahome/tuxedo9.1/bin/TMS_ORA10g BS-124c.c -L${TUXDIR}/lib
/home/tuxedo/beahome/tuxedo9.1/lib/TMS.o -ltux -lbuft -L${ORACLE_HOME}/lib -lclntsh -lfml -lfml32 -lengine -ldl -lpthread /usr/lib/libcrypt.a
CMDTUX_CAT:530: ERROR: Cannot execute $TUXDIR/bin/buildserver -r Oracle_XA -o /home/tuxedo/beahome/tuxedo9.1/bin/TMS_ORA10g -S -s TMS -s..TMS:TMS -f
$TUXDIR/lib/TMS.o
我觉得写得没错,指定了库的路径,不应该出这个问题。
[tuxedo@brady udataobj]$ ll $ORACLE_HOME/lib/libclntsh.so
ls: /home/oracle/oracle/product/10.2.0/db_1/lib/libclntsh.so: Permission denied
这时我才意识到 我的tuxedo用户没有权限啊。
于是用root用户来进行操作。
[root@brady tuxedo9.1]# buildtms -o $TUXDIR/bin/TMS_ORA10g -r Oracle_XA
3、配置UBBCONFIG文件
下面是我的配置文件,粗体部分是需要关注的位置。
*RESOURCES
IPCKEY 56778
DOMAINID xaapp
MASTER xamh
MAXACCESSERS 10
MAXSERVERS 5
MAXSERVICES 10
MODEL SHM
LDBAL N
*MACHINES
"brady.domain" LMID=xamh
APPDIR="/home/tuxedo/beahome/appdir/xaapp"
TUXCONFIG="/home/tuxedo/beahome/appdir/xaapp/tuxconfig"
TUXDIR="/home/tuxedo/beahome/tuxedo9.1"
TLOGDEVICE = "/home/tuxedo/beahome/appdir/TLOG"
TLOGNAME=TLOG
TLOGSIZE=100
#如果这个地方不设置的话,会出现一下错误:
#[tuxedo@brady xaapp]$ tmloadcf -y ubbconfig
#CMDTUX_CAT:1352: ERROR: GROUP entry GROUP1 has TMS specified and LMID xamh does not have TLOGDEVICE
#CMDTUX_CAT:867: ERROR: tmloadcf: Above errors found during syntax checking
*GROUPS
GROUP1
LMID=xamh
GRPNO=1
OPENINFO="ORACLE_XA:Oracle_XA+Acc=P/scott/tiger+sqlNet=ORCL+SesTm=100+LogDir=..+MaxCur=5"
CLOSEINFO=""
TMSNAME="TMS_ORA10g"
#OPENINFO中P/scott/tiger+sqlNet=ORCL
#scott/tiger是用户名/密码,sqlNet=ORCL是本地命名的服务别名
#需要根据实际情况自定义
*SERVERS
DEFAULT:
CLOPT="-A"
axserv SRVGRP=GROUP1 SRVID=1
*SERVICES
TEST
4、重命名下列文件,因为下列文件名与ORACLE带的文件名有冲突,所以要改名。
(1)TUXEDO安装路径include目录下的下面文件
把sqlca.h 改名为 sqlca.h.bbb
把sqlcode.h 改名为 sqlcode.h.bbb
把sqlda.h 改名为 sqlda.h.bbb
(2)重命名TUXEDO安装路径lib目录下的下面文件
把libsql.lib 改名为 libsql.lib.bbb
三、你可以编写服务器端和客户端程序了
1、在编译服务器端程序的时候,用到proc命令而且还有一些oracle的库,所以要注意权限问题。
2、在启动服务器之前,要确保ORACLE服务器已经启动,且监听器也已经正常启动。
我的Oracle数据库的监听器一开始没有正常启动,出现如下错误:
[root@brady xaapp]# tmboot -y
Booting all admin and server processes in /home/tuxedo/beahome/appdir/xaapp/tuxconfig
INFO: BEA Tuxedo, Version 9.1, 32-bit, Patch Level (none)
INFO: Serial #: 454493271161-2655514326743, Expiration NONE, Maxusers 1000000
INFO: Licensed to: Customer
Booting admin processes ...
exec BBL -A :
process id=5539 ... Started.
Booting server processes ...
exec TMS_ORA10g -A :
Failed.
exec TMS_ORA10g -A :
Failed.
exec TMS_ORA10g -A :
Failed.
exec axserv -A :
Failed.
1 process started.
在ULOG文件中记录的错误是TPERMERR - resource manager error
我弄了差不多一个小时,没有弄好,上网搜也没有没有搜到什么原因。
然后我检查了下oracle。才发现监听器没有正常启动。
[oracle@brady xa]$ lsnrctl stop
[oracle@brady xa]$ lsnrctl start
再次 启动TUXEDO服务器时:
[root@brady xaapp]# tmboot -y
Booting all admin and server processes in /home/tuxedo/beahome/appdir/xaapp/tuxconfig
INFO: BEA Tuxedo, Version 9.1, 32-bit, Patch Level (none)
INFO: Serial #: 454493271161-2655514326743, Expiration NONE, Maxusers 1000000
INFO: Licensed to: Customer
Booting admin processes ...
exec BBL -A :
process id=5603 ... Started.
Booting server processes ...
exec TMS_ORA10g -A :
CMDTUX_CAT:819: INFO: Process id=5606 Assume started (pipe).
exec TMS_ORA10g -A :
CMDTUX_CAT:819: INFO: Process id=5610 Assume started (pipe).
exec TMS_ORA10g -A :
CMDTUX_CAT:819: INFO: Process id=5613 Assume started (pipe).
exec axserv -A :
CMDTUX_CAT:819: INFO: Process id=5616 Assume started (pipe).
5 processes started.
posted @
2012-03-20 15:20 cpp 阅读(976) |
评论 (0) |
编辑
Tuxedo Domains通讯
使用TUXEDO组件/DOMAINS时,需要对管理配置作一些改变。在以下例子中,会创建一个独立的测试应用环境(DOMAINID是TEST),它可以读取/请求另一个应用的交易(ProdCust)的数据。
服务GWTDOMAIN(GWT)负责响应域间通讯。GWADM和DMADM是处理管理交易和域服务的管理服务。这些服务必须配置在UBBCONFIG文件中。配置信息必须在远程和本地应用环境中定义。
服务GWTDOMAIN通过TCP/IP协议与其他域进行通讯。物理上远程的域的应用位置是透明的。
服务GWTDOMAIN是双向的:可以处理远程域发来的请求也可以向远程域发出请求。
除UBBCONFIG外,配置/DOMAINS还需要一些信息。这些信息在DMCONFIG文件中。DMCONFIG的文本文件通过BDMCONFIG编译成二进制文件。
第一步:UBBCONFIG应作相应改动
为/DOMAIN建立的新组应该和其他应用组隔离开。其一用于管理,其他是网关服务。
UBBCONFIG
*RESOURCES
IPCKEY 49152
MAXACCESSERS 2
MAXSERVERS 25
MASTER SITE1
MODEL SHM
*MACHINES
class2 LMID=SITE1
TUXDIR=”/usr/tuxedo”
APPDIR=”/usr/apps/atmapp”
TUXCONFIG=”/usr/apps/atmapp/atmapp.tux”
*GROUPS
LDMGRP LMID=SITE1 GRPNO=20
LGWGRP LMID=SITE1 GRPNO=30
#下一行用于‘prod’域
APP1 LMID=SITE1 GRPNO=10
*SERVERS
DMADM SRVGRP=LDMGRP SRVID=200
GWADM SRVGRP=LGWGRP SRVID=310
GWTDOMAIN SRVGRP=LGWGRP SRVID=320
#下一行用于‘prod’域
CUSTOMER CLOPT=”-A” SRVGRP=APP1(对应上面的group) SRVID=100
*SERVICES
#下一行用于‘prod’域
ProdCust
第二步:为域间请求创建DMCONFIG
下文的ASCII数据存在的文件一般称为DMCONFIG,由此生成的二进制格式文件称为BDMCONFIG。以下的DMCONFIG存在于“TEST“域,用来请求远程的”prod“域的”ProdCust“交易。
DMCONFIG on TEST DOMAIN
*DM_LOCAL_DOMAINS
test GWGRP=LGWGRP
TYPE=TDOMAIN
DOMAINID=”TEST”
DMTLOGDEV=”/usr/apps/atmapp/logs/DLOG”
*DM_REMOTE_DOMAINS
production TYPE=TDOMAIN
DOMAINID=”prod”
*DM_TDOMAIN
prod NWADDR=”//lcspn1:3070”
NWDEVICE=”/dev/xti/tcp”
TEST NWADDR=”//lcspn2:3070”
NWDEVICE=”/dev/xti/tcp”
*DM_REMOTE_SERVICES
ProdCust
*DM_LOCAL_SERVICES
第三步:创建DMCONFIG指定对域外提供的交易
下文的DMCONFIG位于域’prod’,该域将向其他域提供可调用交易:ProdCust。
域‘prod’上的DMCONFIG
#本地域信息
*DM_LOCAL_DOMAINS
#LMID
production GWGRP=LGWGRP
#域描述:TDOMAIN即TUXEDO DOMAINS
TYPE=TDOMAIN
#域的唯一标识符
DOMAINID=”prod”
#交易的日志
DMTLOGDEV=”/usr/apps/atmapp/logs/DLOG”
#远程域信息
*DM_REMOTE_DOMAINS
test TYPE=TDOMAIN
DOMAINID=”TEST”
*DM_TDOMAIN
#地址和设备名
prod NWADDR=”//lcspn1:3070”
NWDEVICE=”/dev/xti/tcp”
TEST NWADDR=”//lcspn2:3070”
NWDEVICE=”/dev/xti/tcp”
*DM_REMOTE_SERVICES
*DM_LOCAL_SERVICES
#远程域可以使用的交易
ProdCust
第四步:设定环境变量
/DOMAIN进程需要额外的环境变量去访问/DOMAINS配置信息
export BDMCONFIG=/usr/apps/atmapp/atmapp.bdm
第五步:编译ubbconfig
本过程是从两个域中相同的UBBCONFIG生成二进制文件TUXCONFIG。在本例中,UBBCONFIG的信息位于’ubbconfig’。
tmloadcf –y ubbconfig
第六步:编译dmconfig
本过程是创建二进制DOMAINS配置文件,BDMCONFIG,在两个域中相同;而两者都有的文件‘dmconfig’内容是不同的。
dmloadcf –y dmconfig
该贴由chong.zhang转至本版2014-9-18 16:55:54