system programming and API and ABI

系统编程、API及ABI

clip_image001

系统编程

Linux系统编程中有三大基石:系统调用、C库和C编译器

clip_image003 clip_image005  clip_image007

系统调用

       系统编程始于系统调用,系统调用syscalls是为了从操作系统获得服务或者资源而从用户空间向内核发起的函数调用。比如我们比较熟悉的readwrite函数。

       操作系统的主要功能是为应用程序的运行创建良好的环境,为了达到这个目的,内核提供一系列具备预定功能的多内核函数,通过一组称为系统调用(system call)的接口呈现给用户。系统调用把应用程序的请求传给内核,调用相应的的内核函数完成所需的处理,将处理结果返回给应用程序,如果没有系统调用和内核函数,用户将不能编写大型应用程序。

clip_image008

C

clip_image009

ClibcUnix应用程序的核心。就算你使用别的语言,c库也常常扮演着非常重要的角色,它常被高级的库封装,提供核心服务或者方便的系统调用。

glibclinux系统中最底层的api,几乎其它任何运行库都会依赖于glibcglibc除了封装linux操作系统所提供的系统服务外,它本身也提供了许多其它一些必要功能服务的实现。由于 glibc 囊括了几乎所有的 UNIX 通行的标准,可以想见其内容包罗万有。而就像其他的 UNIX 系统一样,其内含的档案群分散于系统的树状目录结构中,像一个支架一般撑起整个作业系统。在 GNU/Linux 系统中,其C函式库发展史点出了GNU/Linux 演进的几个重要里程碑,用 glibc 作为系统的C函式库,是GNU/Linux演进的一个重要里程碑。

C编译器

clip_image010

       Linux中,标准的C编辑器是GNU编辑器工具集gcc

       GCCGNU Compiler CollectionGNU编译器集合)是一套由GNU工程开发的支持多种编程语言的编译器。GCC是自由软件发展过程中的著名例子,由自由软件基金会以GPL协议发布。GCC是大多数类Unix操作系统(如LinuxBSDMac OS X等)的标准的编译器,GCC同样适用于微软的WindowsGCC支持多种计算机体系芯片,如x86ARM,并已移植到其他多种硬件平台。GCC原名为GNU C编译器(GNU C Compiler),因为它原本只能处理C语言。GCC很快地扩展,并支持处理C++。后来又扩展能够支持更多编程语言,如FortranPascalObjective-CJavaAdaGo等。

API以及ABI

在系统级别上,影响可移植性的因素主要包括两个互相独立的定义和描述集合,一个是应用程序接口API,另一个是应用程序二进制接口ABI。两个都定义和描述了软件不同模块间的接口。

API

clip_image012

APIApplication Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件的以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。

ABI

clip_image013

应用程序二进制接口(application binary interfaceABI 描述了应用程序和操作系统之间,一个应用和它的库之间,或者应用的组成部分之间的低接口 ABI不同于API API定义了源代码和库之间的接口,因此同样的代码可以在支持这个API的任何系统中编译 ,然而ABI允许编译好的目标代码在使用兼容ABI的系统中无需改动就能运行。 ABI掩盖了各种细节,例如:调用约定控制着函数的参数如何传送以及如何接受返回值;系统调用的编码和一个应用如何向操作系统进行系统调用;以及在一个完整的操作系统ABI中,对象文件的二进制格式、程序库等等。一个完整的ABI,像 Intel二进制兼容标准 (iBCS) ,允许支持它的操作系统上的程序不经修改在其他支持此ABI的操作体统上运行。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

the meaning of postfix(.a,.la,.o,.so) and realize by programming

linux.a,.la,.o,.so文件的意义和编程实现

后缀含义

Linux下文件的类型是不依赖于其后缀名的,但一般来讲:

l  .o,是目标文件,相当于windows中的.obj文件

l  .so 为共享库,shared object,用于动态连接的,dll差不多

l  .a为静态库,是好多个.o合在一起,用于静态连接

l  .lalibtool自动生成的一些共享库,vi编辑查看,主要记录了一些配置信息。可以用如下命令查看.la文件的格式 $file .la .la: ASCII English text,所以可以用vi来查看其内容。

创建.a库文件和.o库文件:

$ gcc -c a.c

$ ar -rc a.a a.o

ar: creating a.a

动态库的编译

假定有三个.c文件:a.cb.cc.c,我们将这几个文件编译成一个动态库:libtest.so

$ gcc a.c b.c c.c -fPIC -shared -o libtest.so

动态库的链接

在上面,我们已经成功生成了一个自己的动态链接库libtest.so,下面我们通过一个程序来调用这个库里的函数。程序的源文件为:test.c

l test.c与动态库libtest.so链接生成执行文件test

$ gcc test.c -L. -ltest -o test

l 测试是否动态连接,如果列出libtest.so,那么应该是连接正常了

$ ldd test

l 执行test,可以看到它是如何调用动态库中的函数的。

编译参数解析

最主要的是GCC命令行的一个选项:

-shared 该选项指定生成动态连接库(让连接器生成T类型的导出符号表,有时候也生成弱连接W类型的导出符号),不用该标志外部程序无法连接。相当于一个可执行文件

-fPIC表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的,所以动态库必须要有此选项

-L.:表示要连接的库在当前目录中

-ltest:编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.so来确定库的名称

LD_LIBRARY_PATH:这个环境变量指示动态连接器可以装载动态库的路径。

当然如果有root权限的话,可以修改/etc/ld.so.conf文件,然后调用 /sbin/ldconfig来达到同样的目的,不过如果没有root权限,那么只能采用输出LD_LIBRARY_PATH的方法了。

注意

调用动态库的时候有几个问题会经常碰到,有时,明明已经将库的头文件所在目录 通过 “-I” include进来了,库所在文件通过“-L”参数引导,并指定了“-l”的库名,但通过ldd命令察看时,就是死活找不到你指定链接的so文件,这时你要作的就是通过修改LD_LIBRARY_PATH或者/etc/ld.so.conf文件来指定动态库的目录。通常这样做就可以解决库无法链接的问题了。

makefile里面怎么正确的编译和连接生成.so库文件,然后又是在其他程序的makefile里面如何编译和连接才能调用这个库文件的函数:我们需要告诉动态链接器、加载器ld.so在哪里才能找到这个共享库,可以设置环境变量把库的路径添加到库目录/lib/usr/libLD_LIBRARY_PATH=$(pwd),这种方法采用命令行方法不太方便,一种替代方法

LD_LIBRARY_PATH可以在/etc/profile还是 ~/.profile还是 ./bash_profile里设置,或者.bashrc里,改完后运行source /etc/profile . /etc/profile更好的办法是

添入/etc/ld.so.conf, 然后执行 /sbin/ldconfig

 

how to learn c programming language

漫谈C语言及如何学习C语言

C语言学习方法

C语言学习顺序:阅读参考书,阅读代码,编写调试实际程序,上网参与讨论,研究高级话题。

1,参考书籍

The C Programming Language

clip_image001如果你只想买一本书学习C语言,只需要买这一本就够了。用三个词语来形容它就是:经典!经典!经典!这本薄薄的只有二百多页的小书涵盖了C语言的方方面面,前无古人而且后无来者,任何溢美之词都不足以形容它。

C程序设计语言(第2·新版)》这是K&R的中文译本,可以先从中文译本看起,然后再读一遍英文原版,既可以学习英文,又可以体会原文那种简约优美的风格。

C陷阱与缺陷》

http://book.douban.com/subject/2778632/

C专家编程》

http://book.douban.com/subject/2377310/

这两本书也是学习及使用C语言的朋友必备的两本书,比如《C专家编程》,专门用两三个章节详细介绍C语言中数组与指针的不同之处,这两本书在某种程度上算是对K&R略过的地方做了详细补充,强烈推荐。

C语言参考手册》

http://book.douban.com/subject/2132084/

C语言参考手册》可以看作是C语言编程的《新华字典》,全面而权威。里面还涵盖了C99的内容,紧跟时代潮流。

C和指针》

http://book.douban.com/subject/1229973/

指针的重要性如何,学过C语言(或者C++)的朋友都知道,这本书更是把指针拔高到了与C语言平起平坐的地位,其实也是从头开始介绍,作为教学参考书也是可以的。

C标准库》

http://book.douban.com/subject/3775842/

这本书是专门介绍C语言的标准库如何实现的,比如malloc算法,用标准的C语言该如何写?strlen这个函数应该如何实现?尽管书中不少代码与真实的C标准库相差很多(由于标准库需要考虑性能优化,很多函数有一些特定的trick),但是绝对值得参考。

《你必须知道的495C语言问题》

 http://book.douban.com/subject/3422332/

这本书其实就是C-FAQ的印刷版本,C-FAQ在各种编程语言的FAQ中可以称得上质量一流。如果你想应聘或者招聘C语言相关程序员,这本书一定要参考。

Linux C编程一站式学习》

http://book.douban.com/subject/4141733/

这本书是基于特定操作系统Linux来介绍C语言编程,可作为计算机相关专业的教科书或入门参考书,也是书单里面唯一一本国人原创的编程书籍,非常难得。书中几乎所有内容都在网上直接公开,针对读者的意见进行修改,这也是非常难得的一种开放态度。非常推荐大家买一本。

学习C语言,一定不能只读书,应该动手练习完成书里面的项目需求(比如编写一个目录浏览器)以及每章的练习题目。这就需要有可以实验的环境,下面针对不同操作系统简单做一下介绍。

2,开发环境

Windows系统下推荐大家使用Code::blocks这个软件。这个软件最大优点是自带了基于mingwGCC以及GDB,只要下载70M左右软件包,就可以完整支持C++C语言编程了。各种功能(比如调试功能)也很强大,版本更新也比较快。注意下载选择名字有mingw的文件,比如最新版本是codeblocks-10.05mingw-setup.exe(版本也许有所不同)。

主页:http://www.codeblocks.org/

clip_image002

另外推荐codelite,相比codeblock,这个更新的更频繁一些。也支持各种比较有用的插件、调试特性、WX等等。

clip_image003

主页 http://codelite.org/

如果需要做Windows操作系统的开发,可以下载Visual C++ 2010 Express

clip_image004

因为Code::Blocks不包含Windows编程头文件(实际是因为没有Windows SDK),无法编写Windows操作系统相关的界面应用程序或者服务类程序。而VC++Express自带了这些头文件以及编程库,虽然功能稍微简陋,但对于练习使用基本够用。

主页:http://www.microsoft.com/express/windows/

对于计算机专业的学生朋友,建议大家使用Linux操作系统,或者更详细一点是使用Xubuntu操作系统作为桌面,使用NetbeansGCC这个组合(当然也可以选择Code::Blocks)。在Xubuntu下可以通过apt-get install build-essential这个命令安装gcc相关程序,已经可以在Terminal下编译C语言程序了,但为了使用方便,大家可以选择NetbeansC++支持包,在Netbeans网站上就能下载。

clip_image005

主页:http://netbeans.org/features/cpp/index.html

如果使用苹果Mac系统,毫无疑问XCode就是编程的绝佳选择,XCode可以在苹果开发者网站上免费下载,在IPhone SDK中也包含了XCode

clip_image006

主页:http://developer.apple.com/technologies/tools/xcode.html

如果手头没有合适的编程环境,还需要实验一些简单的代码,可以用http://codepad.org/提供的服务,在线编写运行代码。

clip_image007

另外建议大家申请一个github.com的账号,在gist.github.com可以保存自己的练习代码,就不需要随身带着U盘了。

C语言编程电子书及教程:

http://publications.gbdirect.co.uk/c_book/ 这一本写的非常详细,你可以把它看成是类似谭浩强版的教科书。

http://www.knosof.co.uk/cbook/cbook.html 这一本云风曾经推荐过,相当深入的介绍了C99标准,深入细节时候需要读读。

http://www.duckware.com/bugfreec/index.html 这本书在网上流传一个中文版本,《编写优化、高效、无错地代码》,另外也有英文影印版《编程精粹》。

http://wangcong.org/blog/?page_id=196 作者王聪,也是相当hard geek,从两个样章看,包含了相当多的内容。

C语言深度解剖》这本可以在百度文库或google搜到,可以读读,有些参考性。

C标准和实现》作者姚新颜,他的《深度探索CC++》算是当年比较有深度的书籍,可惜已经绝版了。这本书也可以在百度文库搜到。这本书也比较值得读。

良葛格C语言学习笔记

 http://caterpillar.onlyfun.net/Gossip/CGossip/CGossip.html

CC++的兼容性问题

 http://en.wikipedia.org/wiki/Compatibility_of_C_and_C%2B%2B

另一个文档关于CC++标准兼容性问题:http://david.tribble.com/text/cdiffs.htm

C Elements of Stylehttp://www.oualline.com/books.free/style/index.html

Linux安全编程》http://www.dwheeler.com/secure-programs/

C Craft》电子版 http://crypto.stanford.edu/~blynn/c/

The function pointer tutorials》函数指针教程。http://www.newty.de/fpt/index.html

C语言编程及Unix系统调用,想用CUnix或者Linux编程的朋友可以参考。http://www.cs.cf.ac.uk/Dave/C/

优化CC++代码http://www.eventhelix.com/RealtimeMantra/Basics/OptimizingCAndCPPCode.htm

图文并茂介绍C语言的指针 http://boredzo.org/pointers/

另外一篇介绍C语言优化的文章

 http://www.prism.uvsq.fr/~cedb/local_copies/lee.html

一个C语言教学ppt

http://www.slideshare.net/petdance/just-enough-c-for-open-source-programmers

一些UnixC语言编程相关的文章

http://users.actcom.co.il/~choo/lupg/tutorials/index.html

Unix下如何建立静态、动态C语言函数库

http://users.actcom.co.il/~choo/lupg/tutorials/libraries/unix-c-libraries.html

如何使用GDB

 http://users.actcom.co.il/~choo/lupg/tutorials/debugging/debugging-with-gdb.html

一些C语言编程技巧

 http://users.bestweb.net/~ctips/

Advanced C programming,高级C语言编程,可以提高水平,非常有帮助http://www.mpi-inf.mpg.de/departments/rg1/teaching/advancedc-ws08/literature.html

C语言问答,这些题目也可用于面试 http://www.gowrikumar.com/c/

预备知识

处于TUI模式的GDB

       加上-tui选项可以在调用GDB是用TUI模式运行,或者当处于非TUI模式时在GDB中使用Ctrl+A+X组合键就可以在TUI模式和非TUI模式中跳转。

       GUI模式中,GDB窗口划分为两个子窗口:

l  用于输入GDB命令的窗口

l  用于查看源码的窗口

clip_image002

       通过使用上下方向键可以在TUI模式中移动到代码的其他部分。如果没有处于TUI模式中,就可以使用箭头键来浏览以前的GBD命令,从而修改或重复执行这些命令。

       TUI模式中,箭头键用于滚动源代码子窗口,可以使用Ctrl+PCtrl+N组合键来浏览以前的GDB命令。

CGDB

       CGDB是一个很友好的GDB界面,当然是相对于GDBTUI界面,CGDB也是GDB的前端,虽然CGDB类似于基于终端的TUI的概念,但其在色彩方面特别有吸引力,而且可以浏览源代码子窗口,并直接在子窗口中设置断点,并且CGDB处理屏幕刷新的能力似乎也比GDBTUI强。

       CGDB的基本命令与约定:

l  按下ESC键可以从基本命令转到源代码窗口,按下i键返回;

l  当光标在源代码窗口中时,可以使用箭头键或者类似vi的操作在源码中随意移动,jk/查找;

l  要执行的下一行用箭头标记;

l  为了在通过光标突出显示的当前代码行上设置断点,只要按下空格键即可;

l  断点行的行号用红色突出显示

clip_image004

调试实例

#include <stdio.h>

#include <stdlib.h>

//insertion sort, several erros

//

//Usage : insert_sort num1 num2 num3 …, where the numi are the numbers to

//be sorted

 

int x[10], //input array

        y[10],//wortspace array

        num_inputs,//length of input array

        num_y = 0;//current number of elements in y

 

void get_args(int ac, char **av)

{

    int i;

 

    num_inputs = ac – 1;

    for(i = 0; i < num_inputs; i++)

        x[i] = atoi(av[i+1]);

    }

 

void scoot_over(int jj)

{

    int k;

 

    for(k = num_y – 1; k > jj; k++)

        y[k] = y[k – 1];

    }

 

void insert(int new_y)

{

    int j;

 

    if(num_y == 0)

    {

        //y empty so far , easy case

        y[0] = new_y;

        return;

        }

        //need to insert just before the first y

        //element that new_y is less than

        for(j = 0; j < num_y; j++)

        {

            if(new_y < y[j])

            {

                //shift y[j],y[j+1],…rightward

                //before insert new_y

                scoot_over(j);

                y[j] = new_y;

                return;

                }

            }

    }

 

void process_data()

{

    for(num_y = 0; num_y < num_inputs; num_y ++)

        //insert new y in the proper place

        //among y[0]…y[num_y – 1]

        insert(x[num_y]);

    }

  

void print_results()

{

    int i;

    for(i = 0; i< num_inputs;i++)

        printf("%d\n",y[i]);

    }

 

 

 

int main(int argc, char **argv){

    get_args(argc,argv);

    process_data();

    print_results();

         return 0;

}

编译:gcc -g -Wall -o insert_sort ins.c

Attention:其中的-g选项可以让编译器将符号表(即对应程序的变量和代码行的内存地址列表)保存在生成的可执行文件。这是一个绝对必要的步骤,这样才能在调试会话过程中引用源代码中的变量名和行号。