Linux學習記錄--程序編譯與函數庫

wKiom1NYYV-gaAqKAARqGLVZk-Q465.bmp

程序編譯與函數庫

前面提到過對於機器來說只能識別0,1,我們如果讓機器運行必須輸入機器能夠識別的語言,可是機器語言不利於人們使用可理解,因此科學家就開發出人類能看的懂的程序語言,然後再創造出“編譯器”將程序語言轉換爲機器語言。

C語言就是我們能夠看懂的機器語言,gcc就是Linux下編譯器。我們通常C語言寫的程序通過gcc編譯後,就能成爲機器能夠識別的語言


gcc程序編譯

如果LINUX 系統中爲安裝GCC編譯器,可以使用下面命令安裝

[root@bogon ~]# yum install gcc


gcc常用語法

語法:

gcc  –c  file.c

僅將源代碼編譯成目標文件。並不會進行鏈接以及生成可執行文件


gcc –o 執行文件名 源代碼文件

直接生成指定名稱的執行文件。但不會生成目標文件


gcc –o 執行文件名 目標文件

通過目標文件生成可執行文件


gcc [其他編譯操作]  –L庫文件路徑

查找庫文件的路徑默認是/usr/lib 與/ib


gcc  [其他編譯操作] –I包含文件路徑

查找包含文件的路徑默認是/usr/include


gcc  [其他編譯操作] –Wall

更加嚴謹的編譯方式,會輸出很多警告信息


gcc  -O  [其他編譯操作]

編譯時依據操作環境優化執行速度


gcc  [其他編譯操作] –l庫文件名稱

編譯時引入其他的庫文件,其中庫文件lib與擴展名不需要寫。如引入libm.so文件,可寫成-lm


單一程序編譯


1.       編寫C語言程序l

[root@bogon code]# vim hello.c
#include <stdio.h>
int main(void)
{
   printf("hello world!");
}


2.       編譯

[root@bogon code]# gcc hello.c 
[root@bogon code]# ll hello.c a.out 
-rwxr-xr-x 1 root root 4947 04-05 16:07 a.out
-rw-r--r-- 1 root root   66 04-05 16:07 hello.c


說明:默認gcc編譯器編譯出來的執行文件a.out, 可以使用-o來制定編譯後生產的執行文件名稱

[root@bogon code]# gcc -o hello hello.c 
[root@bogon code]# ll hello
-rwxr-xr-x 1 root root 4947 04-05 16:11 hello


3.      執行

[root@bogon code]# ./a.out 
hello world!

[root@bogon code]# ./hello 
hello world!


多文件程序編譯

假設我們有A.c ,B.c兩個程序文件,並且他們之間存在函數調用,那麼當其中有一個文件更改了。是不是需要將這兩個文件都重新編譯?當然不需要,這就需要引入目標文件

目標文件:編譯器編譯源代碼後生成的文件,目標文件從結構上講,它是已經編譯後的可執行文件格式,只是沒有經過鏈接的過程。

接着上面的說,當B.c文件更改時,我們執行重新編譯B文件生產目標文件。再講整體鏈接即可


1.       編寫C語言程序

File:A.c
#include <stdio.h>
#include “B.c”
int main ()
{
printf("這是第一個文件\n");
method();
}

File:B.c
#include <stdio.h>
void method(void)
{
 printf("這是第二個文件!\n";)
}

2.       編譯

root@bogon code]# gcc -c A.c B.c -I./
[root@bogon code]# ll 
-rw-r--r-- 1 root root   81 04-05 16:35 A.c
-rw-r--r-- 1 root root  912 04-05 16:35 A.o
-rw-r--r-- 1 root root   80 04-05 16:34 B.c
-rw-r--r-- 1 root root  860 04-05 16:35 B.o

3.    鏈接

[root@bogon code]# gcc -o result A.o B.o

4.       執行

[root@bogon code]# ./result 
這是第一個文件
這是第二個文件!

5.  更改B.c文件

#include <stdio.h>
void method(void)
{
 printf("這是更改後第二個文件!\n";)
}

6.       重新編譯鏈接執行

[root@bogon code]# gcc -c B.c =>只編譯了B這個文件
[root@bogon code]# gcc -o result A.o B.o
[root@bogon code]# ./result 
這是第一個文件
這是更改後第二個文件!


調用外部函數庫

1.       編寫C語言程序

#include<stdio.h>
#include<math.h>
 
int main ()
{
  float val=sin(3.14);
  printf("val值是:%f\n",val);
}

2.       編譯與執行

[root@bogon code]# gcc -o sinmath sinmath.c -lm
[root@bogon code]# ./sinmath 
val值是:0.001593


函數庫介紹

函數庫依照是否編譯到程序內部可分爲

靜態函數庫:通常以.a爲擴展名,編譯時會整合到程序文件中

動態函數庫:通常以.so爲擴展名,編譯時會不會整合到程序文件中,只是在程序文件中存在一個指向的位置

因此程序執行時是不需要靜態函數庫的,但是需要動態函數庫,使用動態函數庫的好處再在可以減少程序文件的大小


動態函數庫加載內存

我們知道內存的訪問速度是硬盤的好幾倍,如果先將動態函數庫加載到內存中,那麼在使用動態函數庫時就會,就會提高很多效率


語法:ldconfig[-f 需要緩存函數庫信息所在文件] [-C 已緩存函數庫信息所在文件]

            ldconfig –p 列出已緩存函數庫信息


需要緩存函數庫信息所在文件:在這個文件中記錄所有需要緩存的的函數庫默認值是

/etc/ ld.so.conf


舉例:查看下我的系統下緩存的函數庫

[root@bogon etc]# vim ld.so.conf
include ld.so.conf.d/*.conf

[root@bogon etc]# cd ld.so.conf.d/
[root@bogon ld.so.conf.d]# ll
-rw-r--r-- 1 root root  15 2013-01-23 mysql-i386.conf
-rw-r--r-- 1 root root  17 2013-01-09 openais-athlon.conf
-rw-r--r-- 1 root root  20 2012-08-20 qt-i386.conf
-rw-r--r-- 1 root root 276 02-22 19:23 vmware-tools-libraries.conf
-rw-r--r-- 1 root root  19 2013-08-07 xulrunner-32.conf
[root@bogon ld.so.conf.d]# vim mysql-i386.conf 
[root@bogon ld.so.conf.d]# ll /usr/lib/mysql
lrwxrwxrwx 1 root root      26 02-18 20:03 libmysqlclient_r.so.15 -> libmysqlclient_r.so.15.0.0
-rwxr-xr-x 1 root root 1460684 2013-01-23 libmysqlclient_r.so.15.0.0
lrwxrwxrwx 1 root root      24 02-18 20:03 libmysqlclient.so.15 -> libmysqlclient.so.15.0.0
-rwxr-xr-x 1 root root 1452764 2013-01-23 libmysqlclient.so.15.0.0
-rwxr-xr-x 1 root root   13220 2013-01-23 mysqlbug
-rwxr-xr-x 1 root root    6215 2013-01-23 mysql_config


已緩存函數庫信息所在文件:這個文件中記錄了已經緩存的函數庫,默認文件爲

/etc/ld.so.cache ,通過-p查詢到的信息就是從這個文件讀取而來


舉例:查看所有已緩存的函數庫

[root@bogon ld.so.conf.d]# ldconfig -p|more
947 libs found in cache `/etc/ld.so.cache'
        libz.so.1 (libc6) => /lib/libz.so.1
        libz.so.1 (libc6) => /usr/lib/libz.so.1
        libx11globalcomm.so.1 (libc6) => /usr/lib/libx11globalcomm.so.1
   ……..
查看程序所包含的動態函數庫

語法:ldd –v文件名

-v:列出所有函數庫信息


舉例:

[root@bogon ld.so.conf.d]# ldd  /usr/bin/passwd
        linux-gate.so.1 =>  (0x00ddc000)
        libuser.so.1 => /usr/lib/libuser.so.1 (0x007c5000)
        libcrypt.so.1 => /lib/libcrypt.so.1 (0x05c74000)
       ……


make編譯

如果一個程序中有很多文件,那麼還像上面那樣講每個文件列出來在進行編譯就會很麻煩。因此這種時候就需要使用make工具了


Make編譯好處

簡化編譯時所需的指令

若在編譯完成後,修改了某個源文件,只會針對修改的文件編譯


Make使用方法

Make是有個二進制文件,其會查找當前目錄下的Makefile文件,根據其裏面定義的內容執行操作。 Makefile裏面包含了若干目標與操作


其基本關於規則如下

目標:

<tab>操作

REST2HTML=html.py --compact-lists --date --generator

all: user_manual.html dev_manual.html

user_manual.html: user_manual.rst
        $(REST2HTML) user_manual.rst user_manual.html

dev_manual.html: dev_manual.rst
        $(REST2HTML) dev_manual.rst dev_manual.html

clean:
        rm *.html


以上內容分爲三個目標all,user_manual.html,clean,其下面分別對應的是其操作

我們可以通過make 後面參數爲目標進行執行。如:make clean


Tarball的安裝

由於Unix like具有很多種。因此一個軟件安裝包不可能適用所有所本,因此有時我們需要根據軟件提供者提供的源碼自行編譯,以滿足在自己的操作系統上運行


大部分軟件開發包編譯與安裝的流程大致是這樣的

1.      講壓縮文件解壓縮

2.      解壓縮後執行裏面的configure文件,其作用就是建立makefile文件

3.      Make clean:清理一些上次操作的殘留

4.      Make :默認操作進行編譯的行爲

5.      Make install:安裝


說明:安裝前如果有安裝文檔最好先查閱

3-4步驟 不一定都存在。可查看makefile內容判斷具體包括哪些目標


舉例:

[root@bogon shared]# tar -zxvf ntp-4.2.4p7.tar.gz -C /tmp
…..
[root@bogon ntp-4.2.4p7]# ./configure --prefix=/usr/loacl/ntp
=> --prefix=/usr/loacl/ntp爲指定安裝目錄
[root@bogon ntp-4.2.4p7]# ll Makefile
-rw-r--r-- 1 root 6011 23950 04-05 21:40 Makefile
=>生成了Makefile文件
root@bogon ntp-4.2.4p7]# ll Makefile
root@bogon ntp-4.2.4p7]# make clean
root@bogon ntp-4.2.4p7]# make 
root@bogon ntp-4.2.4p7]# make install





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章