您的位置:首页 > 运维架构 > Linux

linux下mysql问题总结

2014-04-27 17:11 225 查看
首先安装mysqlserver mysqlclient

创建密码mysqladmin -u root password NEWPASSWORD

修改密码mysqladmin
-u root -p'oldpassword' password newpass


怎样查看端口被占用情况

netstat -anp|grep portnum

首页
(Home)

致访客
(Welcome)

关于我
(About Me)

分类
(Categories)

页面
(Pages)

把伟大书写成平凡,才会让梦想照进现实!


Linux静态库与共享库的创建使用

作者:旸仔发表于:2013-5-23分类:Unix/Linux编程

库文件是一类已编译的包含了若干函数的文件。利用库 (函数库),我们可以提高开发效率和代码复用率、使整个程序更加模块化、方便更新和修改。库又分为静态库 (static_library)、共享库 (shared_library)。在 Linux 操作系统中,静态库通常以.a为后缀,共享库以.so为后缀;而在 Windows 操作系统中,静态库是以.lib为后缀的文件,共享库被称为动态库,是以.dll为后缀的文件。

静态函数库:在主程序编译时,其中所有的函数代码就复制(被包含)到主程序可执行文件中了,主程序开始运行时连同主程序一起加载到内存;时间效率上比使用共享函数库高,但占用更多的硬盘和内存空间;当主程序可执行文件移植到其它计算机上运行时,不再需要依赖此静态库。

共享函数库:则是在主程序编译时,仅复制(包含进)所需要的函数符号表,而非全部函数代码;当主程序可执行文件移植到其它计算机上运行时,需要依赖此共享库;可以在主程序开始运行时一同加载进内存,也可以通过动态调用 (dynamically load) 的方法在主程序运行中需要时才调用加载进内存。

在 Linux 系统中,静态库与共享库的命名都必须以
lib
开头(某些非常底层的函数库例外)。有关函数库的命名规范及调用详细规则,我们在本文最后一章节说明,下面分别先介绍这两种函数库的特点、创建方法及一般调用使用方法。


一、静态函数库

静态函数库实际上是一个由若干的普通目标文件组成的集合,通常以
.a
作为文件后缀。可以用
ar
命令来产生静态函数库文件(ar
是 archiver 的缩写)。现在静态库使用得越来越少了,原因是使用共享库与之相比较有很多优势,不过在一些情况下我们仍然会使用静态库:一是有时用来保持与以前程序的兼容,而是它描述起来比较简单。

下面用一个示例程序,演示静态库的创建及使用。这个示例的源代码在后面介绍共享库时还会用到。
/* code : test.h */
#include <stdio.h>
#include <stdlib.h>
void testa();
void testb();
void testc();

/* code : testa.c */
#include "test.h"
void testa() {
printf("this is in testa n");
}

/* code : testb.c */
#include "test.h"
void testb() {
printf("this is in testb n");
}

/* code : testc.c */
#include "test.h"
void testc() {
printf("this is in testc n");
}

/* code : test.c */
#include "test.h"
int main() {
testa();
testb();
testc();
exit(0);
}


创建好以上5个源代码文件后,接下来我们通过以下命令编译、生成静态库、链接调用:
$ gcc -c testa.c testb.c testc.c     #将这三个文件编译成目标文件
$ ar -rc libtest.a testa.o testb.o testc.o     #将若干个目标文件生成一个静态库文件libtest.a
$ gcc test.c -L. -ltest -o test     #编译主程序,链接调用静态库(-L.参数表示指定静态库所在目录为当前目录,-ltest参数表示静态库文件名为libtest.a)
$ ./test
this is in testa
this is in testb
this is in testc


当我们将此可执行文件移植到别台计算机上运行时,一样可以执行成功。我们还可以通过
ldd
命令查看这个可执行文件的运行依赖关系:
$ ldd ./test
linux-gate.so.1 =>  (0x00e73000)
libc.so.6 => /lib/libc.so.6 (0x00295000)
/lib/ld-linux.so.2 (0x0026f000)


从中,我们看到,调用静态库编译成的可执行文件在运行时不在需要依赖原来的静态库了。


二、共享函数库


2.1、共享库的生成与一般调用方式

共享库文件通常以
.so
作为文件后缀。为了与调用静态库做比较,我们继续使用上面的示例代码:test.h、testa.c、testb.c、testc.c、test.c,执行以下命令编译、生成共享库、调用使用:
$ gcc testa.c testb.c testc.c -fPIC -shared -o libtest.so     #将这三个文件编译生成一个共享库文件libtest.so
#上面这一条命令也可以分为两步执行(等价):
$ gcc -c testa.c testb.c testc.c
$ gcc testa.o testb.o testc.o -fPIC -shared -o libtest.so

$ gcc test.c -L. -ltest -o test     #编译主程序,链接调用共享库(-L.参数表示指定共享库所在目录为当前目录,-ltest参数表示共享库文件名为libtest.so
#注:当指定目录下名为libtest的静态库和共享库同时存在时,默认优先使用共享库
$ ./test
this is in testa
this is in testb
this is in testc


我们在编译的本机上运行 ldd 命令,查看其运行依赖关系:
$ ldd test
linux-gate.so.1 =>  (0x004dd000)
libtest.so (0x004fb000)
libc.so.6 => /lib/libc.so.6 (0x001fe000)
/lib/ld-linux.so.2 (0x0055b000)


看到,主程序可执行文件依赖于共享库 libtest.so。我们仅将此可执行文件移植到别台计算机(却不移植其依赖的共享库)运行,运行报错缺少共享函数库。我们再将其共享函数库移植到到另外这台计算机的 /usr/lib/ 目录下,再运行即可成功:
$ ./test
./test: error while loading shared libraries: libtest.so: cannot open shared object file: No such file or directory
$ ldd test
linux-gate.so.1 =>  (0x003d1000)
libtest.so => not found
libc.so.6 => /lib/libc.so.6 (0x003d2000)
/lib/ld-linux.so.2 (0x0026f000)

$ sudo cp libtest.so /usr/lib/
$ ./test
this is in testa
this is in testb
this is in testc


2.2、共享库的动态调用方式

上面介绍的函数库调用方式,是在程序开始运行的时候就加载到内存中了;另外一种动态调用函数库的方式,则可以在程序运行的任何时候将函数加载进内存。动态加载函数库的方式特别适用于在程序中加载一些模块或 plugin 扩展模块的情况,因为它可以由程序选择性地,在某个需要加载函数库中函数的时候才动态地加载。例如,我们周知的 Pluggable Authentication Modules (PAM) 系统模块,就是用动态加载函数库来使得管理员可以配置和重新配置身份验证信息。

动态调用的函数库,与其它函数库在本质上没有任何区别。在 Linux/Solaris/Apple 系统中:

dlopen()
函数用来打开一个函数库以备之后使用。

dlsym()
函数在一个已经打开的函数库里面查找特定的函数符号来使用这个函数库。

dlclose()
函数关闭一个已经打开的函数库。

dlerror()
函数来获取最后一次 打开/使用/关闭
操作出现错误的错误信息。

它们的函数定义如下:(具体使用参见pubs.opengroup.org/onlinepubs/7908799/xsh/dlfcn.h.html)
void *dlopen(const char *filepath, int mode);

void *dlsym(void *handle, const char *name);

int dlclose(void *handle);

char *dlerror(void);


请看下面的例子:我们仍然使用之前示例中的 test.h、testa.c、testb.c、testc.c,将 test.c 修改如下:
/* code : test.c */
#include <dlfcn.h>
#include "test.h"
int main() {
void *handle;
char *error;
char (*res)();

handle = dlopen("libtest.so", RTLD_LAZY);
if(!handle) {
fputs(dlerror(), stderr);
exit(1);
}
res = dlsym(handle, "testa");
if((error = dlerror()) != NULL) {
fputs(error, stderr);
exit(1);
}
(*res)();
dlclose(handle);
exit(0);
}


使用下列命令编译、查看执行结果:(需现将之前编译生成的 libtest.so 复制到 /usr/lib/ 中)
$ gcc -o test test.c -ldl     #-ldl参数表示需要调用系统函数库 libdl.so.2
$ ./test
this is in testa

$ ldd ./test
linux-gate.so.1 =>  (0x00aa7000)
libdl.so.2 => /lib/libdl.so.2 (0x0042e000)
libc.so.6 => /lib/libc.so.6 (0x00295000)
/lib/ld-linux.so.2 (0x0026f000)


我们看到,当使用动态调用的方式加载函数库时,编译主程序时需要加入
-ldl
参数。所动态调用的
libtest.so 函数库是在程序内部需要时,通过 dlopen() 函数打开,而不是在程序运行开始就载入。


三、库的命名规范与调用路径查找规则


3.1、库文件的命名规范

共享库文件可以有两种名字 so-name、real-name:

so-name 的命名格式:
lib***.so.***
,即以
lib 开头,然后是库名称,接着是 .so 后缀,最后加上主版本号(可选)。real-name 的命名方式则相对自由,不过也是以 lib 开头,以 .so 为后缀,除了包含库名称,还应包含完整的发行版本号(主版本号、副版本号)。

so-name 是提供其它程序调用时使用的,通常 so-name 是一个符号链接文件,指向 real-name 的实际函数库文件。这样做的好处是,我们可以不断更新函数库的版本,real-name 改变了,但 so-name 不会随之改变,调用它的程序也就无须作修改。

以一个系统库 libc 为例,在 /lib/ 目录下,存在 libc.so.6 和 libc-2.12.so(每台计算机上的完整版本号可能不同)这两个文件,libc.so.6 是 libc 的 so-name,它是一个符号链接,指向的 libc-2.12.so 是 libc 的 real-name。


3.2、库调用路径查找规则

文件系统层次化标准
FHS (Filesystem Hierarchy Standard) 规定:一个 Linux 发行版系统中,大部分的函数库文件应该安装到 /usr/lib/ 目录下,系统启动的时候要加载的库则放到 /lib/ 目录下,而那些不是系统本身一部分的库则放到 /usr/local/lib/ 或其它目录下。

上文中我们提到,gcc 命令的 -L 参数用来指定调用库所在的目录位置,dlopen() 函数中的第一个参数也可以指定调用库所在的目录位置。那么,如果我们不指定查找库的路径,系统默认会去哪里查找呢?

首先,系统会根据
LD_LIBRARY_PATH
这个环境变量中的目录去查找;如果没有找到,接着,系统会根据
/etc/ld.so.cache 这个缓存表中的信息查找;如果还找不到,最后,系统会查找标准路径 (
/lib/
/usr/lib/
),如果仍找不到相应库文件,则宣布“查找失败”,提示如下错误信息。

cannot open shared object file: No such file or directory

/lib/ld-linux.so.2
是一个动态链接/加载器
(dynamic linker/loader)。ld-linux.so.2 管理着两个文件
/etc/ld.so.conf
/etc/ld.so.cache
,前者是一个可修改的配置文件,后者是一个高速缓存表。ld.so.cache
包含着 ld.so.conf 中所有目录下可供链接的共享库的索引,由
ldconfig
命令自动生成。因此,当我们将一个新的共享库添加到非标准路径以外的目录中时,需要运行以下命令更新
ld.so.cache 缓存表才能使库文件可用:
#假设新添加的库文件放在/usr/local/lib/,则在ld.so.conf文件中加入此路径
$ sudo echo /usr/local/lib/ >> /etc/ld.so.conf
$ sudo ldconfig


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: