2012-01-15 19:34:38 iteye_900 阅读数 26
  • C语言嵌入式Linux编程第8期:C语言的模块化编程

    本期课程,王老师对C语言在大型项目中经常遇到的一些问题、模棱两可的概念、知识死角、各种坑,从原理上进行分析、从技术实现上进行讲解。这些东西,在其它地方很少看到,很多知识点是老师花费了一个月的时间去研究、分析、验证得出的结论,干货满满。对于新手来收,这些可以直接作为经验,应用在以后的开发实战中;对于1~3年的公司工程师来说,学完本期课程,相信您也会有不少的收获。

    1091 人正在学习 去看看 王利涛
linux C库函数(一)
2010年01月26日
  C库函数的文件操作实际上是独立于具体的操作系统平台的,不管是DOS、Windows、Linux、Vxworks中都是这些函数。1.文件打开函数fopen():原型是
  FILE *fopen(const char *path,const char *mode);
  path --表示文件名和路径名,可以是绝对路径,也可以是相对路径。
  比如:fp=fopen("/tmp/file","r+");
  fp=fopen("./../file","w+");
  mode--打开方式.由r(read),w(write),a(append),t(text),b(banary),+六个字符组成
  函数的返回值为文件的流操作指针。
  对于UNIX系统,t和b没有区分,用那个都一样,也可以不写其他的有6中组合
  “r”=只读,文件必须存在;
  “w”=只写,若文件不存在则创建之,已存在则清空内容再写;
  "a"=只能追加数据,文件不存在就创建之;
  "r+"=允许读和写,文件必须存在;
  "w+"=读和写,文件不存在则创建,存在就清空再写;
  "a+"=读和追加数据,文件不存在就创建;
  打开如果出错,fopen 将返回一个空指针值 NULL,注意要加打开是否成功判断。
  if((fp=fopen("../file","r"))==NULL)
  {
  perror("failed to open ../file");
  exit(1);
  }
  fopen里的所谓当前目录是指:进程工作时的目录
  2.文件关闭函数fclose()
  文件使用完,最好是要关闭,原型是
  int fclose(FILE *fp);
  fclose与fopen配对调用。
  3.出错处理函数perror()
  C标准库和UNIX C库的很多系统函数在错误返回时将错误原因记录在一个全局变量errno中,一般用函数perror()将errno解释成字符串输出。原型:
  void perror(const char *s);
  每次调用系统函数错误返回后,要马上检查错误原因,perror()只处理最近一次错误产生的errno.
  4.字符读写函数fgetc()/fputc() 原型:
  int fgetc(FILE *stream);
  int fputc(int c,FILE *stream);
  在fgetc函数中,文件必须是可读的。fgetc返回的是一个字符(char型)。每读一个字符,自动向后移动一个字节。但申明的是int,这是指该字符的ASCII码。
  fputc输入的也是字符c的ASCII码。
  5.字符串读写函数fgets()/fputs() 原型:[b][b]
  char *fgets(char *s,int size,FILE *stream);
  int fputs(const char*s,FILE *stream);
  fgets中, s是缓冲区首地址,size是缓冲区长度,fgets从stream中一次最多读取以'\n'结尾的一行到s中。并且在末尾自动添加一个'\0';
  fputs中,s是以'\0'结尾的字符串,fputs将该字符串写入文件stream,但并不写入结尾的'\0'.fputs不需要以'\n'结尾。
  /***************************************
  2 *复制文本文件file1的内容到file2
  3 * 2009.3.25 yunbo03
  4 **************************************/
  5 #include [b]//[/b][b]头文件在[/b][b]linux[/b][b]系统[/b][b] /usr/include/[/b][b]下[/b]
  6 #include
  7 #include
  8
  9 int main(void)
  10 {
  11 FILE *fp1,*fp2;
  12 char ss[512];
  13
  14 if((fp1=fopen("file1","r"))==NULL){
  15 perror("fail to open file1");
  16 exit(1);
  17 }
  18
  19 if((fp2=fopen("file2","a+"))==NULL){
  20 perror("fail to open file2");
  21 exit(1);
  22 }
  23
  24 for(;fgets(ss,10,fp1)!=NULL;)
  25 fputs(ss,fp2);
  26
  27 fclose(fp1);
  28 fclose(fp2);
  29
  30 return 0;
  31 }
  [b] [/b]
[/b][/b]
2011-09-09 14:41:27 fan_hai_ping 阅读数 4760
  • C语言嵌入式Linux编程第8期:C语言的模块化编程

    本期课程,王老师对C语言在大型项目中经常遇到的一些问题、模棱两可的概念、知识死角、各种坑,从原理上进行分析、从技术实现上进行讲解。这些东西,在其它地方很少看到,很多知识点是老师花费了一个月的时间去研究、分析、验证得出的结论,干货满满。对于新手来收,这些可以直接作为经验,应用在以后的开发实战中;对于1~3年的公司工程师来说,学完本期课程,相信您也会有不少的收获。

    1091 人正在学习 去看看 王利涛
 最近在做的项目中使用到动态库的动态加载技术,Windows和Linux都提供了相应的函数来打开动态库、获取函数指针和关闭动态库

,在打开动态库函数(dlopen或LoadLibrary)中指定动态库的文件名后,在程序运行时是以什么次序来搜索动态库呢?

 

Linux下搜索路径的次序:

1)  ELF可执行文件中动态段中DT_RPATH所指定的路径,不常用但是比较使用的方法;

2)  编译目标代码时指定的动态库搜索路径(-WI,-rpath=./);

3)  环境变量LD_LIBRARY_PATH指定的动态库搜索路径;

4)  配置文件/etc/ld.so.conf(或ld.so.cache)中指定的动态库搜索路径;

5)  默认的动态库搜索路径/lib;

6)  默认的动态库搜索路径/usr/lib。

在上述1-3中指定的动态库搜索路径都可以指定多个搜索目录,其先后顺序是按指定路径的先后顺序搜索的。如果动态库之间存在依赖关系,那么先加载那些被依赖的动态库。

 

Windows下搜索路径次序

1)  可执行文件所在的目录(当前目录);

2)  Windows的系统目录(该目录可以通过GetSystemDirectory函数获得);

3)  16位的系统目录(Windows目录下的system子目录);

4)  Windows目录(该目录可以通过GetWindowsDirectory函数获得);

5)  进程当前所在的工作目录;

6)  PATH环境变量中所列出的目录。

注:工作目录位于Windows目录之后,这一改变开始于Windows XP SP2之后。

2006-03-18 16:05:00 thinkerABC 阅读数 7260
  • C语言嵌入式Linux编程第8期:C语言的模块化编程

    本期课程,王老师对C语言在大型项目中经常遇到的一些问题、模棱两可的概念、知识死角、各种坑,从原理上进行分析、从技术实现上进行讲解。这些东西,在其它地方很少看到,很多知识点是老师花费了一个月的时间去研究、分析、验证得出的结论,干货满满。对于新手来收,这些可以直接作为经验,应用在以后的开发实战中;对于1~3年的公司工程师来说,学完本期课程,相信您也会有不少的收获。

    1091 人正在学习 去看看 王利涛

众所周知,Linux动态库的默认搜索路径是/lib和/usr/lib。动态库被创建后,一般都复制到这两个目录中。当程序执行时需要某动态库,并且该动态库还未加载到内存中,则系统会自动到这两个默认搜索路径中去查找相应的动态库文件,然后加载该文件到内存中,这样程序就可以使用该动态库中的函数,以及该动态库的其它资源了。在Linux 中,动态库的搜索路径除了默认的搜索路径外,还可以通过以下三种方法来指定。

方法一:在配置文件/etc/ld.so.conf中指定动态库搜索路径。

可以通过编辑配置文件/etc/ld.so.conf来指定动态库的搜索路径,该文件中每行为一个动态库搜索路径。每次编辑完该文件后,都必须运行命令ldconfig使修改后的配置生效。我们通过例1来说明该方法。

例1:

我们通过以下命令用源程序pos_conf.c(见程序1)来创建动态库 libpos.so,详细创建过程请参考文[1]。

# gcc -c pos_conf.c
         # gcc -shared -fPCI -o libpos.so pos_conf.o
         #

 #include <stdio.h>
          void pos()
          {
                 printf("/root/test/conf/lib/n");
          }
           程序1: pos_conf.c

接着通过以下命令编译main.c(见程序2)生成目标程序pos。

 # gcc -o pos main.c -L. -lpos
          #

 void pos();
         int main()
         {
              pos();
              return 0;
         }
         程序2: main.c

然后把库文件移动到目录/root/test/conf/lib中。

 # mkdir -p /root/test/conf/lib
          # mv libpos.so /root/test/conf/lib
          #

最后编辑配置文件/etc/ld.so.conf,在该文件中追加一行"/root/test/conf/lib"。

运行程序pos试试。

 # ./pos
          ./pos: error while loading shared libraries: libpos.so: cannot open shared object file: No such file or directory
          #

出错了,系统未找到动态库libpos.so。找找原因,原来在编辑完配置文件/etc/ld.so.conf后,没有运行命令ldconfig,所以刚才的修改还未生效。我们运行ldconfig后再试试。

 # ldconfig
          # ./pos
           /root/test/conf/lib 
          #

程序pos运行成功,并且打印出正确结果。

方法二:通过环境变量LD_LIBRARY_PATH指定动态库搜索路径。

通过设定环境变量LD_LIBRARY_PATH也可以指定动态库搜索路径。当通过该环境变量指定多个动态库搜索路径时,路径之间用冒号":"分隔。下面通过例2来说明本方法。

例2:

我们通过以下命令用源程序pos_env.c(见程序3)来创建动态库libpos.so。

 # gcc -c pos_env.c
          # gcc -shared -fPCI -o libpos.so pos_env.o
          #

#include <stdio.h>
         void pos()
         {
               printf("/root/test/env/lib/n");
         }
         程序3: pos_env.c

测试用的可执行文件pos可以使用例1中的得到的目标程序pos,不需要再次编译。因为pos_conf.c中的函数pos和pos_env.c中的函数pos 函数原型一致,且动态库名相同,这就好比修改动态库pos后重新创建该库一样。这也是使用动态库的优点之一。

然后把动态库libpos.so移动到目录/root/test/conf/lib中。

 # mkdir -p /root/test/env/lib
          # mv libpos.so /root/test/env/lib
          #

我们可以使用export来设置该环境变量,在设置该环境变量后所有的命令中,该环境变量都有效。

例如:

 # export LD_LIBRARY_PATH=/root/test/env/lib
          #

但本文为了举例方便,使用另一种设置环境变量的方法,既在命令前加环境变量设置,该环境变量只对该命令有效,当该命令执行完成后,该环境变量就无效了。如下述命令:

# LD_LIBRARY_PATH=/root/test/env/lib ./pos
         /root/test/env/lib
         #

程序pos运行成功,并且打印的结果是"/root/test/env/lib",正是程序pos_env.c中的函数pos的运行结果。因此程序pos搜索到的动态库是/root/test/env/lib/libpos.so。

方法三:在编译目标代码时指定该程序的动态库搜索路径。

还可以在编译目标代码时指定程序的动态库搜索路径。这是通过gcc 的参数"-Wl,-rpath,"指定(如例3所示)。当指定多个动态库搜索路径时,路径之间用冒号":"分隔。

例3:

我们通过以下命令用源程序pos.c(见程序4)来创建动态库libpos.so。

 # gcc -c pos.c
          # gcc -shared -fPCI -o libpos.so pos.o
          #

#include <stdio.h>
         void pos()
         {
               printf(".//n");
         }
         程序4: pos.c

因为我们需要在编译目标代码时指定可执行文件的动态库搜索路径,所以需要用gcc命令重新编译源程序main.c(见程序2)来生成可执行文件pos。

# gcc -o pos main.c -L. -lpos -Wl,-rpath,./
         #

再运行程序pos试试。

 # ./pos
          ./
          #

 

程序pos运行成功,输出的结果正是pos.c中的函数pos的运行结果。因此程序pos搜索到的动态库是./libpos.so。

以上介绍了三种指定动态库搜索路径的方法,加上默认的动态库搜索路径/lib和/usr/lib,共五种动态库的搜索路径,那么它们搜索的先后顺序是什么呢?

在介绍上述三种方法时,分别创建了动态库./libpos.so、 /root/test/env/lib/libpos.so和/root/test/conf/lib/libpos.so。我们再用源程序pos_lib.c(见程序5)来创建动态库/lib/libpos.so,用源程序pos_usrlib.c(见程序6)来创建动态库/usr/lib/libpos.so。

 #include <stdio.h>
          void pos()
          {
                  printf("/lib/n");
          }
           程序5: pos_lib.c

#include <stdio.h>
         void pos()
         {
                printf("/usr/lib/n");
         }
         程序6: pos_usrlib.c

这样我们得到五个动态库libpos.so,这些动态库的名字相同,且都包含相同函数原型的公用函数pos。但存储的位置不同和公用函数pos 打印的结果不同。每个动态库中的公用函数pos都输出该动态库所存放的位置。这样我们可以通过执行例3中的可执行文件pos得到的结果不同获知其搜索到了哪个动态库,从而获得第1个动态库搜索顺序,然后删除该动态库,再执行程序pos,获得第2个动态库搜索路径,再删除第2个被搜索到的动态库,如此往复,将可得到Linux搜索动态库的先后顺序。程序pos执行的输出结果和搜索到的动态库的对应关系如表1所示:

程序pos输出结果 使用的动态库 对应的动态库搜索路径指定方式
./ ./libpos.so 编译目标代码时指定的动态库搜索路径
/root/test/env/lib /root/test/env/lib/libpos.so 环境变量LD_LIBRARY_PATH指定的动态库搜索路径
/root/test/conf/lib /root/test/conf/lib/libpos.so 配置文件/etc/ld.so.conf中指定的动态库搜索路径
/lib /lib/libpos.so 默认的动态库搜索路径/lib
/usr/lib /usr/lib/libpos.so 默认的动态库搜索路径/usr/lib
表1: 程序pos输出结果和动态库的对应关系

创建各个动态库,并放置在相应的目录中。测试环境就准备好了。执行程序pos,并在该命令行中设置环境变量LD_LIBRARY_PATH。

 # LD_LIBRARY_PATH=/root/test/env/lib ./pos
          ./
          #

根据程序pos的输出结果可知,最先搜索的是编译目标代码时指定的动态库搜索路径。然后我们把动态库./libpos.so删除了,再运行上述命令试试。

# rm libpos.so
         rm: remove regular file `libpos.so'? y
         # LD_LIBRARY_PATH=/root/test/env/lib ./pos
         /root/test/env/lib
         #

根据程序pos的输出结果可知,第2个动态库搜索的路径是环境变量LD_LIBRARY_PATH指定的。我们再把/root/test/env/lib/libpos.so删除,运行上述命令。

# rm /root/test/env/lib/libpos.so
         rm: remove regular file `/root/test/env/lib/libpos.so'? y
         # LD_LIBRARY_PATH=/root/test/env/lib ./pos
         /root/test/conf/lib
         #

第3个动态库的搜索路径是配置文件/etc/ld.so.conf指定的路径。删除动态库/root/test/conf/lib/libpos.so后再运行上述命令。

# rm /root/test/conf/lib/libpos.so
         rm: remove regular file `/root/test/conf/lib/libpos.so'? y
         # LD_LIBRARY_PATH=/root/test/env/lib ./pos
         /lib
         #

第4个动态库的搜索路径是默认搜索路径/lib。我们再删除动态库/lib/libpos.so,运行上述命令。

# rm /lib/libpos.so
         rm: remove regular file `/lib/libpos.so'? y
         # LD_LIBRARY_PATH=/root/test/env/lib ./pos
         /usr/lib
         #

最后的动态库搜索路径是默认搜索路径/usr/lib。

综合以上结果可知,动态库的搜索路径搜索的先后顺序是:

1.编译目标代码时指定的动态库搜索路径;

2.环境变量LD_LIBRARY_PATH指定的动态库搜索路径;

3.配置文件/etc/ld.so.conf中指定的动态库搜索路径;

4.默认的动态库搜索路径/lib;

5.默认的动态库搜索路径/usr/lib。

在上述1、2、3指定动态库搜索路径时,都可指定多个动态库搜索路径,其搜索的先后顺序是按指定路径的先后顺序搜索的。对此本文不再举例说明,有兴趣的读者可以参照本文的方法验证。

参考文献:

[1] 在Linux中创建静态库和动态库, http://blog.csdn.net/thinkerABC/archive/2006/03/11/621817.aspx , 2006.03.11

2017-09-16 20:25:16 kai165416 阅读数 385
  • C语言嵌入式Linux编程第8期:C语言的模块化编程

    本期课程,王老师对C语言在大型项目中经常遇到的一些问题、模棱两可的概念、知识死角、各种坑,从原理上进行分析、从技术实现上进行讲解。这些东西,在其它地方很少看到,很多知识点是老师花费了一个月的时间去研究、分析、验证得出的结论,干货满满。对于新手来收,这些可以直接作为经验,应用在以后的开发实战中;对于1~3年的公司工程师来说,学完本期课程,相信您也会有不少的收获。

    1091 人正在学习 去看看 王利涛

在Linux下安装mkl之后,编译需要指定库函数和头文件的路径

icc -I/opt/intel/mkl/include dgemm_example.c -lmkl_rt -L/opt/intel/mklb/intel64 -L/opt/intelb/intel64
其中,
-I/opt/intel/mkl/include 指定头文件的路径
dgemm_example.c 指定编译的文件
-lmkl_rt 指定链接的库
-L/opt/intel/mklb/intel64 指定库的路径 
-L/opt/intelb/intel64

生成可执行文件之后,运行的时候还需要动态库,所以需要改环境变量

在 /etc/ld.so.conf.d 下创建名为 intel-mkl.conf 的文件,内容为
/opt/intel/mkl/lib/intel64
/opt/intel/lib/intel64
然后执行
ldconfig -v

参考1
参考2

2019-12-05 23:11:46 qq_43684922 阅读数 85
  • C语言嵌入式Linux编程第8期:C语言的模块化编程

    本期课程,王老师对C语言在大型项目中经常遇到的一些问题、模棱两可的概念、知识死角、各种坑,从原理上进行分析、从技术实现上进行讲解。这些东西,在其它地方很少看到,很多知识点是老师花费了一个月的时间去研究、分析、验证得出的结论,干货满满。对于新手来收,这些可以直接作为经验,应用在以后的开发实战中;对于1~3年的公司工程师来说,学完本期课程,相信您也会有不少的收获。

    1091 人正在学习 去看看 王利涛

内容: 记录linux搜索动态库时的可能路径

一.搜索规则

Linux动态库的默认搜索路径是/lib和/usr/lib。动态库被创建后,一般都复制到这两个目录中,这样才能
被找到。当程序执行时需要某动态库,并且该动态库还未加载到内存中,则系统会自动到这两个默认搜索路径
中去查找相应的动态库文件,然后加载该文件到内存中,这样程序就可以使用该动态库中的函数,以及该动态
库的其它定义内容。

注意:并不会在像搜索头文件时,#include "XX" 一样,搜索你的当前目录是否有动态库

二.指定搜索路径的方法

方法一:在配置文件/etc/ld.so.conf中指定动态库搜索路径。

通过编辑配置文件/etc/ld.so.conf来指定动态库的搜索路径,该文件中每行为一个动态库搜索路径。每次
编辑完该文件后,都必须运行命令ldconfig使修改后的配置生效
比如:在配置文件追加你的路径:/root/XX/YY/lib

方法二:通过环境变量LD_LIBRARY_PATH指定动态库搜索路径。

通过设定环境变量LD_LIBRARY_PATH也可以指定动态库搜索路径。当通过该环境变量指定多个动态库搜索路
径时,路径之间用冒号":"分隔。

1.使用export来设置该环境变量,在设置该环境变量后所有的命令中,该环境变量都有效。

export LD_LIBRARY_PATH=/root/test/env/lib
    
2.在命令前加环境变量设置,该环境变量只对该命令有效,当该命令执行完成后,该环境变量就无效了:

LD_LIBRARY_PATH=/root/test/env/lib ./pos  /root/test/env/lib

方法三:在编译目标代码时指定该程序的动态库搜索路径。

还可以在编译目标代码时指定程序的动态库搜索路径。这是通过gcc 的参数"-Wl,-rpath,"指定。当指定多
动态库搜索路径时,路径之间用冒号":"分隔。


三.搜索路径的先后顺序

动态库的搜索路径搜索的先后顺序是:

1.编译目标代码时指定的动态库搜索路径;

2.环境变量LD_LIBRARY_PATH指定的动态库搜索路径;

3.配置文件/etc/ld.so.conf中指定的动态库搜索路径;

4.默认的动态库搜索路径/lib;

5.默认的动态库搜索路径/usr/lib。

大四学生一枚,如果文章有错误的地方,欢迎在下方提出,每条评论我都会去认真看并回复,同时感谢指正的前辈。有喜欢C/C++,linux的同学欢迎私信一起讨论学习。

Linux 函数库设计

阅读数 362

没有更多推荐了,返回首页