導航:首頁 > 源碼編譯 > glibc源碼在哪個目錄

glibc源碼在哪個目錄

發布時間:2022-12-25 23:00:10

㈠ 如何安裝 glibc-2.15.tar

編譯步驟:
下載glibc-2.15.tar.gz和補丁包glibc-ports-2.15.tar.gz
解壓
$mv glibc-ports-2.15 glibc-2.15/ports
$mkdir glibc-build-2.15 &&cd glibc-build-2.15
$ ../glibc-2.15/configure \
--prefix=/usr/local/glibc_mips \
CC=mipsel-linux-gcc \
--host=mipsel-linux \
--build=i686-pc-linux-gnu \
--enable-add-on=nptl \
libc_cv_forced_unwind=yes \
libc_cv_c_cleanup=yes \
libc_cv_mips_tls=yes \
libc_cv_gnu99_inline=yes
ok,沒問題
$make &&make install
大功告成

##########################################################################

下面是我編譯時的過程和遇到的問題及解決:
##########################################################################

$tar xvf glibc-2.16.0.tar.bz2
$cd glibc-2.16.0
$./configure --prefix=/usr/local/glibc //先不加其他選項,除了安裝路徑,一切默認,網上一般配置arm的選項如下 --prefix=$HOME/usr/arm --with-headers=$HOME/usr/arm/glibc/arm-linux-glibc/include --with-libs=$HOME/usr/arm/glibc/arm-linux-glibc/lib
報錯:
configure: error: you must configure in a separate build directory

很奇怪的問題,必須配置一個構建目錄,剛開始以為是安裝目錄為創建
$mkdir /usr/local/glibc
問題仍然存在,網路之
$mkdir ../glibc-build && cd ../glibc-build
$../glibc-2.16.0/configure --prefix=/usr/local/glibc
出現新的問題:
configure: WARNING:
*** These auxiliary programs are missing or incompatible versions: msgfmt
*** some features will be disabled.
*** Check the INSTALL file for required versions.
checking LD_LIBRARY_PATH variable... contains current directory
configure: error:
*** LD_LIBRARY_PATH shouldn't contain the current directory when
*** building glibc. Please change the environment variable
*** and run configure again.
第一個警告不用管它,第二個LD_LIBRARY_PATY也會有錯?我的這個路徑用了多少天了。仔細看提示,不應包含當前路徑。打開~/.bash_profile
$cat ~/.bash_profile
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib export LD_LIBRARY_PATH

這也沒當前路徑啊。還是網路吧。
一個兄弟的解釋是這樣「LD_LIBRARY_PATH不能以終結符作為開始和最後一個字元,不能有2個終結符連在一起,我的LD_LIBRARY_PATH為 :/usr/local/firefox:/usr/local/firefox,只要在前面加上一個路徑,不讓:出現在第一個字元就可以了 」
原來如此,第一個字元不能是":",修改~/.bash_profile
export LD_LIBRARY_PATH=/usr/local/lib export LD_LIBRARY_PATH

$../glibc-2.16.0/configure --prefix=/usr/local/glibc
ls一下,發現,當前目錄生成了Makefile等一堆東西
$make && make install
沒問題
下一步開始交叉編譯
$mkdir ../glibc-build-mips && cd ../glibc-build-mips
$ ../glibc-2.16.0/configure --prefix=/usr/local/glibc_mips CC=mipsel-linux-gcc --host=mips
出現新的問題:
configure: running configure fragment for add-on libidn
configure: running configure fragment for add-on nptl
*** The GNU C library is currently not available for this platform.
*** So far nobody cared to port it and if there is no volunteer it
*** might never happen. So, if you have interest to see glibc on
*** this platform visit
*** http://www.gnu.org/software/libc/porting.html
*** and join the group of porters
看起來像是需要path,下載glibc-ports-2.16.tar.gz,放在源碼包目錄,解壓
$ ../glibc-2.16.0/configure \
--prefix=/usr/local/glibc_mips \
CC=mipsel-linux-gcc \
CXX=mipsel-linux-g++ \
--host=mips \
--enable-add-ons=/home/hb/code/glibc/glibc-ports-2.16.0/sysdeps/mips
仍然報錯:
configure: error: fragment must set $libc_add_on_canonical
改為:
$ ../glibc-2.16.0/configure \
--prefix=/usr/local/glibc_mips \
CC=mipsel-linux-gcc \
CXX=mipsel-linux-g++ \
--host=mips \
--enable-add-ons
報錯:
configure: error: The mipsel is not supported.
這樣不行,谷歌半天,總算知道補丁怎麼用的了。把補丁目錄拷到glibc目錄下,改名為ports
$mv glibc-ports-2.16.0/ glibc-2.16.0/ports

$../glibc-2.16.0/configure \
--prefix=/usr/local/glibc_mips \
CC=mipsel-linux-gcc \
CXX=mipsel-linux-g++ \
--host=mipsel-linux \
--build=i686-pc-linux-gnu \
--enable-add-on
繼續報錯:
configure: error:
*** These critical programs are missing or too old: ld as
*** Check the INSTALL file for required versions.
這個問題可折騰死我了。弄了好半天,就是不行,最後google發現,原來是ld和as版本不對,不是太高就是太低。
configure中找到$AS --version
發現版本是這么匹配的2.1*.*
$mipsel-linux-ld
GNU ld (GNU Binutils) 2.18.50.20080908
原來是這樣,在configure版本號那一行修改,最後的括弧前面加入
|2.18.50.×
as那一行也同樣修改
然後
$make
開始編譯,看起來不錯
好半天後,編譯也報錯了

In file included from ../include/uchar.h:1,
from mbrtoc16.c:23:
../wcsmbs/uchar.h:47:5: error: #error "<uchar.h> requires ISO C11 mode"
In file included from ../include/uchar.h:1,
from mbrtoc16.c:23:
../wcsmbs/uchar.h:52: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'char16_t'
../wcsmbs/uchar.h:53: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'char32_t'
../wcsmbs/uchar.h:61: error: expected ')' before '*' token
../wcsmbs/uchar.h:66: error: expected declaration specifiers or '...' before 'char16_t'
../wcsmbs/uchar.h:73: error: expected ')' before '*' token
../wcsmbs/uchar.h:78: error: expected declaration specifiers or '...' before 'char32_t'
mbrtoc16.c:37: error: expected ')' before '*' token
make[2]: *** [/home/hb/code/glibc/glibc-build-mips/wcsmbs/mbrtoc16.o] 錯誤 1
make[2]:正在離開目錄 `/home/hb/code/glibc/glibc-2.16.0/wcsmbs'
make[1]: *** [wcsmbs/subdir_lib] 錯誤 2
make[1]:正在離開目錄 `/home/hb/code/glibc/glibc-2.16.0'
make: *** [all] 錯誤 2
看看這個頭文件咋回事
$ vim ../glibc-2.16.0/wcsmbs/uchar.h
#if defined __GNUC__ && !defined __USE_ISOCXX11
/* Define the 16-bit and 32-bit character types. Use the information
provided by the compiler. */
# if !defined __CHAR16_TYPE__ || !defined __CHAR32_TYPE__
# if defined __STDC_VERSION__ && __STDC_VERSION__ < 201000L
# error "<uchar.h> requires ISO C11 mode"
# else
# error "definitions of __CHAR16_TYPE__ and/or __CHAR32_TYPE__ missing"
# endif

# endif

明白了,原來是需要c11支持,mipsel-linux-gcc -v一下,我的支持c99.原來如此。暫時沒招了,我還做不到修改c11的支持,只剩兩個辦法,不用這個glibc版本或者重新編譯一個支持c11的交叉編譯器。編譯器需要做的比較多,暫時先換個低點的版本吧。
下載galibc-2.15版本
重復上面步驟,解壓tar包
解壓ports包
$mv glibc-ports-2.15 glibc-2.15/ports
$mkdir glibc-build-2.15 &&cd glibc-build-2.15
$ ../glibc-2.15/configure \
--prefix=/usr/local/glibc_mips \
CC=mipsel-linux-gcc \
--host=mipsel-linux \
--build=i686-pc-linux-gnu \
--enable-add-on=nptl \
libc_cv_forced_unwind=yes \
libc_cv_c_cleanup=yes \
libc_cv_mips_tls=yes \
libc_cv_gnu99_inline=yes
ok,沒問題
$make &&make install
庫已經編好了,但是不能直接使用,必須再用新的庫重編一遍編譯器才行。

上一篇

㈡ 在C語言里,關於庫函數中各種數學函數的代碼。

你說的就是庫函數的源碼,也就是glibc,源碼在ftp://ftp.gnu.org/gnu/glibc可以下到,比如下載ftp://ftp.gnu.org/gnu/glibc/glibc-2.9.tar.gz,打開後就可以看到你需要的各種庫的具體實現代碼,比如在string中的strcat.c中就有

char*strcat(dest,src)
char*dest;
constchar*src;
{
char*s1=dest;
constchar*s2=src;
reg_charc;
/*Findtheendofthestring.*/
do
c=*s1++;
while(c!='');
/*,sowecanincrement
itwhilememoryisread(winsonpipelinedcpus).*/
s1-=2;
do
{
c=*s2++;
*++s1=c;
}
while(c!='');
returndest;
}

㈢ 如何為嵌入式開發建立交叉編譯環境

下面我們將以建立針對arm的交叉編譯開發環境為例來解說整個過程,其他的體系結構與這個相類似,只要作一些對應的改動。我的開發環境是,宿主機 i386-redhat-7.2,目標機 arm。
這個過程如下
1. 下載源文件、補丁和建立編譯的目錄
2. 建立內核頭文件
3. 建立二進制工具(binutils)
4. 建立初始編譯器(bootstrap gcc)
5. 建立c庫(glibc)
6. 建立全套編譯器(full gcc)
下載源文件、補丁和建立編譯的目錄
1. 選定軟體版本號
選擇軟體版本號時,先看看glibc源代碼中的INSTALL文件。那裡列舉了該版本的glibc編譯時所需的binutils 和gcc的版本號。例如在 glibc-2.2.3/INSTALL 文件中推薦 gcc 用 2.95以上,binutils 用 2.10.1 以上版本。
我選的各個軟體的版本是:
linux-2.4.21+rmk2
binutils-2.10.1
gcc-2.95.3
glibc-2.2.3
glibc-linuxthreads-2.2.3
如果你選的glibc的版本號低於2.2,你還要下載一個叫glibc-crypt的文件,例如glibc-crypt-2.1.tar.gz。 Linux 內核你可以從www.kernel.org 或它的鏡像下載。
Binutils、gcc和glibc你可以從FSF的FTP站點ftp://ftp.gun.org/gnu/ 或它的鏡像去下載。 在編譯glibc時,要用到 Linux 內核中的 include 目錄的內核頭文件。如果你發現有變數沒有定義而導致編譯失敗,你就改變你的內核版本號。例如我開始用linux-2.4.25+vrs2,編譯glibc-2.2.3 時報 BUS_ISA 沒定義,後來發現在 2.4.23 開始它的名字被改為 CTL_BUS_ISA。如果你沒有完全的把握保證你改的內核改完全了,就不要動內核,而是把你的 Linux 內核的版本號降低或升高,來適應 glibc。
Gcc 的版本號,推薦用 gcc-2.95 以上的。太老的版本編譯可能會出問題。Gcc-2.95.3 是一個比較穩定的版本,也是內核開發人員推薦用的一個 gcc 版本。
如果你發現無法編譯過去,有可能是你選用的軟體中有的加入了一些新的特性而其他所選軟體不支持的原因,就相應降低該軟體的版本號。例如我開始用 gcc-3.3.2,發現編譯不過,報 as、ld 等版本太老,我就把 gcc 降為 2.95.3。 太新的版本大多沒經過大量的測試,建議不要選用。
回頁首
2. 建立工作目錄
首先,我們建立幾個用來工作的目錄:
在你的用戶目錄,我用的是用戶liang,因此用戶目錄為 /home/liang,先建立一個項目目錄embedded。
$pwd
/home/liang
$mkdir embedded
再在這個項目目錄 embedded 下建立三個目錄 build-tools、kernel 和 tools。
build-tools-用來存放你下載的 binutils、gcc 和 glibc 的源代碼和用來編譯這些源代碼的目錄。
kernel-用來存放你的內核源代碼和內核補丁。
tools-用來存放編譯好的交叉編譯工具和庫文件。
$cd embedded
$mkdir build-tools kernel tools
執行完後目錄結構如下:
$ls embedded
build-tools kernel tools
3. 輸出和環境變數
我們輸出如下的環境變數方便我們編譯。
$export PRJROOT=/home/liang/embedded
$export TARGET=arm-linux
$export PREFIX=$PRJROOT/tools
$export TARGET_PREFIX=$PREFIX/$TARGET
$export PATH=$PREFIX/bin:$PATH
如果你不慣用環境變數的,你可以直接用絕對或相對路徑。我如果不用環境變數,一般都用絕對路徑,相對路徑有時會失敗。環境變數也可以定義在.bashrc文件中,這樣當你logout或換了控制台時,就不用老是export這些變數了。
體系結構和你的TAEGET變數的對應如下表

你可以在通過glibc下的config.sub腳本來知道,你的TARGET變數是否被支持,例如:
$./config.sub arm-linux
arm-unknown-linux-gnu
在我的環境中,config.sub 在 glibc-2.2.3/scripts 目錄下。
網上還有一些 HOWTO 可以參考,ARM 體系結構的《The GNU Toolchain for ARM Target HOWTO》,PowerPC 體系結構的《Linux for PowerPC Embedded Systems HOWTO》等。對TARGET的選取可能有幫助。
4. 建立編譯目錄
為了把源碼和編譯時生成的文件分開,一般的編譯工作不在的源碼目錄中,要另建一個目錄來專門用於編譯。用以下的命令來建立編譯你下載的binutils、gcc和glibc的源代碼的目錄。
$cd $PRJROOT/build-tools
$mkdir build-binutils build-boot-gcc build-gcc build-glibc gcc-patch
build-binutils-編譯binutils的目錄
build-boot-gcc-編譯gcc 啟動部分的目錄
build-glibc-編譯glibc的目錄
build-gcc-編譯gcc 全部的目錄
gcc-patch-放gcc的補丁的目錄
gcc-2.95.3 的補丁有 gcc-2.95.3-2.patch、gcc-2.95.3-no-fixinc.patch 和gcc-2.95.3-returntype-fix.patch,可以從 http://www.linuxfromscratch.org/ 下載到這些補丁。
再將你下載的 binutils-2.10.1、gcc-2.95.3、glibc-2.2.3 和 glibc-linuxthreads-2.2.3 的源代碼放入 build-tools 目錄中
看一下你的 build-tools 目錄,有以下內容:
$ls
binutils-2.10.1.tar.bz2 build-gcc gcc-patch
build-binutls build-glibc glibc-2.2.3.tar.gz
build-boot-gcc gcc-2.95.3.tar.gz glibc-linuxthreads-2.2.3.tar.gz
回頁首
建立內核頭文件
把你從 www.kernel.org 下載的內核源代碼放入 $PRJROOT /kernel 目錄
進入你的 kernel 目錄:
$cd $PRJROOT /kernel
解開內核源代碼
$tar -xzvf linux-2.4.21.tar.gz

$tar -xjvf linux-2.4.21.tar.bz2
小於 2.4.19 的內核版本解開會生成一個 linux 目錄,沒帶版本號,就將其改名。
$mv linux linux-2.4.x
給 Linux 內核打上你的補丁
$cd linux-2.4.21
$patch -p1 < ../patch-2.4.21-rmk2
編譯內核生成頭文件
$make ARCH=arm CROSS_COMPILE=arm-linux- menuconfig
你也可以用 config 和 xconfig 來代替 menuconfig,但這樣用可能會沒有設置某些配置文件選項和沒有生成下面編譯所需的頭文件。推薦大家用 make menuconfig,這也是內核開發人員用的最多的配置方法。配置完退出並保存,檢查一下的內核目錄中的 include/linux/version.h 和 include/linux/autoconf.h 文件是不是生成了,這是編譯 glibc 是要用到的,version.h 和 autoconf.h 文件的存在,也說明了你生成了正確的頭文件。
還要建立幾個正確的鏈接
$cd include
$ln -s asm-arm asm
$cd asm
$ln -s arch-epxa arch
$ln -s proc-armv proc
接下來為你的交叉編譯環境建立你的內核頭文件的鏈接
$mkdir -p $TARGET_PREFIX/include
$ln -s $PRJROOT/kernel/linux-2.4.21/include/linux $TARGET_PREFIX/include/linux
$in -s $PRJROOT/kernel/linux-2.4.21/include/asm-arm $TARGET_PREFIX/include/asm
也可以把 Linux 內核頭文件拷貝過來用
$mkdir -p $TARGET_PREFIX/include
$cp -r $PRJROOT/kernel/linux-2.4.21/include/linux $TARGET_PREFIX/include
$cp -r $PRJROOT/kernel/linux-2.4.21/include/asm-arm $TARGET_PREFIX/include
回頁首
建立二進制工具(binutils)
binutils是一些二進制工具的集合,其中包含了我們常用到的as和ld。
首先,我們解壓我們下載的binutils源文件。
$cd $PRJROOT/build-tools
$tar -xvjf binutils-2.10.1.tar.bz2
然後進入build-binutils目錄配置和編譯binutils。
$cd build-binutils
$../binutils-2.10.1/configure --target=$TARGET --prefix=$PREFIX
--target 選項是指出我們生成的是 arm-linux 的工具,--prefix 是指出我們可執行文件安裝的位置。
會出現很多 check,最後產生 Makefile 文件。
有了 Makefile 後,我們來編譯並安裝 binutils,命令很簡單。
$make
$make install
看一下我們 $PREFIX/bin 下的生成的文件
$ls $PREFIX/bin
arm-linux-addr2line arm-linux-gasp arm-linux-objmp arm-linux-strings
arm-linux-ar arm-linux-ld arm-linux-ranlib arm-linux-strip
arm-linux-as arm-linux-nm arm-linux-readelf
arm-linux-c++filt arm-linux-obj arm-linux-size
我們來解釋一下上面生成的可執行文件都是用來干什麼的
add2line - 將你要找的地址轉成文件和行號,它要使用 debug 信息。
Ar-產生、修改和解開一個存檔文件
As-gnu 的匯編器
C++filt-C++ 和 java 中有一種重載函數,所用的重載函數最後會被編譯轉化成匯編的標號,c++filt 就是實現這種反向的轉化,根據標號得到函數名。
Gasp-gnu 匯編器預編譯器。
Ld-gnu 的連接器
Nm-列出目標文件的符號和對應的地址
Obj-將某種格式的目標文件轉化成另外格式的目標文件
Objmp-顯示目標文件的信息
Ranlib-為一個存檔文件產生一個索引,並將這個索引存入存檔文件中
Readelf-顯示 elf 格式的目標文件的信息
Size-顯示目標文件各個節的大小和目標文件的大小
Strings-列印出目標文件中可以列印的字元串,有個默認的長度,為4
Strip-剝掉目標文件的所有的符號信息
回頁首
建立初始編譯器(bootstrap gcc)
首先進入 build-tools 目錄,將下載 gcc 源代碼解壓
$cd $PRJROOT/build-tools
$tar -xvzf gcc-2.95.3.tar.gz
然後進入 gcc-2.95.3 目錄給 gcc 打上補丁
$cd gcc-2.95.3
$patch -p1< ../gcc-patch/gcc-2.95.3.-2.patch
$patch -p1< ../gcc-patch/gcc-2.95.3.-no-fixinc.patch
$patch -p1< ../gcc-patch/gcc-2.95.3-returntype-fix.patch
echo timestamp > gcc/cstamp-h.in
在我們編譯並安裝 gcc 前,我們先要改一個文件 $PRJROOT/gcc/config/arm/t-linux,把
TARGET_LIBGCC2-CFLAGS = -fomit-frame-pointer -fPIC
這一行改為
TARGET_LIBGCC2-CFLAGS = -fomit-frame-pointer -fPIC -Dinhibit_libc -D__gthr_posix_h
你如果沒定義 -Dinhibit,編譯時將會報如下的錯誤
../../gcc-2.95.3/gcc/libgcc2.c:41: stdlib.h: No such file or directory
../../gcc-2.95.3/gcc/libgcc2.c:42: unistd.h: No such file or directory
make[3]: *** [libgcc2.a] Error 1
make[2]: *** [stmp-multilib-sub] Error 2
make[1]: *** [stmp-multilib] Error 1
make: *** [all-gcc] Error 2
如果沒有定義 -D__gthr_posix_h,編譯時會報如下的錯誤
In file included from gthr-default.h:1,
from ../../gcc-2.95.3/gcc/gthr.h:98,
from ../../gcc-2.95.3/gcc/libgcc2.c:3034:
../../gcc-2.95.3/gcc/gthr-posix.h:37: pthread.h: No such file or directory
make[3]: *** [libgcc2.a] Error 1
make[2]: *** [stmp-multilib-sub] Error 2
make[1]: *** [stmp-multilib] Error 1
make: *** [all-gcc] Error 2
還有一種與-Dinhibit同等效果的方法,那就是在你配置configure時多加一個參數-with-newlib,這個選項不會迫使我們必須使用newlib。我們編譯了bootstrap-gcc後,仍然可以選擇任何c庫。
接著就是配置boostrap gcc, 後面要用bootstrap gcc 來編譯 glibc 庫。
$cd ..; cd build-boot-gcc
$../gcc-2.95.3/configure --target=$TARGET --prefix=$PREFIX \
>--without-headers --enable-languages=c --disable-threads
這條命令中的 -target、--prefix 和配置 binutils 的含義是相同的,--without-headers 就是指不需要頭文件,因為是交叉編譯工具,不需要本機上的頭文件。-enable-languages=c是指我們的 boot-gcc 只支持 c 語言。--disable-threads 是去掉 thread 功能,這個功能需要 glibc 的支持。
接著我們編譯並安裝 boot-gcc
$make all-gcc
$make install-gcc
我們來看看 $PREFIX/bin 裡面多了哪些東西
$ls $PREFIX/bin
你會發現多了 arm-linux-gcc 、arm-linux-unprotoize、cpp 和 gcov 幾個文件。
Gcc-gnu 的 C 語言編譯器
Unprotoize-將 ANSI C 的源碼轉化為 K&R C 的形式,去掉函數原型中的參數類型。
Cpp-gnu的 C 的預編譯器
Gcov-gcc 的輔助測試工具,可以用它來分析和優程序。
使用 gcc3.2 以及 gcc3.2 以上版本時,配置 boot-gcc 不能使用 --without-headers 選項,而需要使用 glibc 的頭文件。
回頁首
建立 c 庫(glibc)
首先解壓 glibc-2.2.3.tar.gz 和 glibc-linuxthreads-2.2.3.tar.gz 源代碼
$cd $PRJROOT/build-tools
$tar -xvzf glibc-2.2.3.tar.gz
$tar -xzvf glibc-linuxthreads-2.2.3.tar.gz --directory=glibc-2.2.3
然後進入 build-glibc 目錄配置 glibc
$cd build-glibc
$CC=arm-linux-gcc ../glibc-2.2.3/configure --host=$TARGET --prefix="/usr"
--enable-add-ons --with-headers=$TARGET_PREFIX/include
CC=arm-linux-gcc 是把 CC 變數設成你剛編譯完的boostrap gcc,用它來編譯你的glibc。--enable-add-ons是告訴glibc用 linuxthreads 包,在上面我們已經將它放入了 glibc 源碼目錄中,這個選項等價於 -enable-add-ons=linuxthreads。--with-headers 告訴 glibc 我們的linux 內核頭文件的目錄位置。
配置完後就可以編譯和安裝 glibc
$make
$make install_root=$TARGET_PREFIX prefix="" install
然後你還要修改 libc.so 文件

GROUP ( /lib/libc.so.6 /lib/libc_nonshared.a)
改為
GROUP ( libc.so.6 libc_nonshared.a)
這樣連接程序 ld 就會在 libc.so 所在的目錄查找它需要的庫,因為你的機子的/lib目錄可能已經裝了一個相同名字的庫,一個為編譯可以在你的宿主機上運行的程序的庫,而不是用於交叉編譯的。
回頁首
建立全套編譯器(full gcc)
在建立boot-gcc 的時候,我們只支持了C。到這里,我們就要建立全套編譯器,來支持C和C++。
$cd $PRJROOT/build-tools/build-gcc
$../gcc-2.95.3/configure --target=$TARGET --prefix=$PREFIX --enable-languages=c,c++
--enable-languages=c,c++ 告訴 full gcc 支持 c 和 c++ 語言。
然後編譯和安裝你的 full gcc
$make all
$make install
我們再來看看 $PREFIX/bin 裡面多了哪些東西
$ls $PREFIX/bin
你會發現多了 arm-linux-g++ 、arm-linux-protoize 和 arm-linux-c++ 幾個文件。
G++-gnu的 c++ 編譯器。
Protoize-與Unprotoize相反,將K&R C的源碼轉化為ANSI C的形式,函數原型中加入參數類型。
C++-gnu 的 c++ 編譯器。
到這里你的交叉編譯工具就算做完了,簡單驗證一下你的交叉編譯工具。
用它來編譯一個很簡單的程序 helloworld.c
#include <stdio.h>
int main(void)
{
printf("hello world\n");
return 0;
}
$arm-linux-gcc helloworld.c -o helloworld
$file helloworld
helloworld: ELF 32-bit LSB executable, ARM, version 1,
dynamically linked (uses shared libs), not stripped
上面的輸出說明你編譯了一個能在 arm 體系結構下運行的 helloworld,證明你的編譯工具做成功了。
轉載僅供參考,版權屬於原作者

㈣ glibc-2.4-31.54包在哪個目錄

要新建一個目錄,進入到該目錄,使用絕對路徑編譯安裝。
新建一個目錄,然後進入該目錄,用絕對路徑編譯。
mkdir \\/usr\\/local\\/glibc
cd \\/usr\\/local\\/glibc
\\/usr\\/local\\/src\\/glibc-2.7\\/configure
make && make install

㈤ 求Linux下的libdl庫源碼。

你可以從GNU網站下載glibc的源碼,libdl庫源於glibc源碼的dlfcn目錄,其中包含dlopen、dlsym等函數的實現。

㈥ linux glibc默認安裝在哪

GNU C庫(glibc)是標准C庫的GNU實現。glibc是GNU工具鏈的關鍵組件,用於和二進制工具和編譯器一起使用,為目標架構生成用戶空間應用程序。
當從源碼進行構建時,一些Linux程序可能需要鏈接到某個特定版本的glibc。在這種情況下,你可能想要檢查已安裝的glibc信息以查看是否滿足依賴關系。
這里介紹幾種簡單的方法,方便你檢查Linux上的glibc版本。
方法一
下面給出了命令行下檢查GNU C庫的簡單命令。
$ ldd --version
在本例中,glibc版本是2.19。
方法二
另一個方法是在命令行「輸入」glibc 庫的名稱(如,libc.so.6),就像命令一樣執行。
輸出結果會顯示更多關於glibc庫的詳細信息,包括glibc的版本以及使用的GNU編譯器,也提供了glibc擴展的信息。glibc變數的位置取決於Linux版本和處理器架構。
在基於Debian的64位系統上:
$ /lib/x86_64-linux-gnu/libc.so.6
在基於Debian的32位系統上:
$ /lib/i386-linux-gnu/libc.so.6
在基於Red Hat的64位系統上:
$ /lib64/libc.so.6
在基於Red Hat的32位系統上:
$ /lib/libc.so.6

㈦ 求助QT5.4 安裝在win8.1後無法編譯

關於QT安裝時出現錯誤請參照我的上一篇文章http://hi..com/whyme%CE%DE%CF%DE/blog/item/91103d1a71f4aed5e2fe0b65.html
現在說一下編譯運行出錯的解決辦法:
說明:redhat紅帽5.4有點太老了,所以運行最新的QT時,出現了各種問題,最主要的就是各種庫的問題:
(1)undefined reference to `FcFreeTypeQueryFace'的問題
需要更新fontconfig,我用的是fontconfig-2.6.0.tar.gz,2.5.0我試了,出現了很多錯誤,不知道為什麼2.6.0可以,
附下載地址http://115.com/file/be9m2r
解壓到/usr/src 進入後 ./autogen.sh 然後終端中提示make,你就make,最後make install。完成。./autogen.sh也可以輸入./configure --sysconfdir=/etc --prefix=/usr --mandir=/usr/share/man 具體可能是./configure後指明了安在你想要安得地方吧(我用的是./autogen.sh)
如果期間遇到錯誤不要不耐煩,按照提示網路一下會有解決的辦法的。
(2)undefined reference to 'FT_Library_SetLcdFilter'
這是由於freetype太舊的原因,也是一樣,需要更新:
附下載地址:http://115.com/file/anwcxdfk
安裝方法與(1)一樣。也有安裝(1)時可能有問題要先安裝(2) 這個自己嘗試吧,我是先(1)後(2)的。
還有就是我的系統是紅帽企業版5.4,不是的或者版本不一樣的,我不知道我的方法有沒有效果。
(3)接下來應該有的常式就可以編譯運行了,但是還有不能運行的,那是因為你的glibc太舊了,這個是c動態庫。必須注意的是,幾乎所有的應用程序都依賴於glibc的動態庫,重新編譯安裝glibc必須非常謹慎,一旦出錯可能導致系統無法繼續使用。所以強烈建議閱讀源碼目錄下的INSTALL。
附下載地址:http://115.com/file/e749sc6n
第一步是配置glibc,出於安全的考慮,glibc不允許在源碼目錄樹下編譯,必須新建一個目錄,然後在新建目錄下運行configure,我就在/usr/src下建了一個glibc文件夾mkdir glibc。然後在新建目錄里運行解壓縮文件中的config,在運行這個之前,先在終端運行需要加上優化開關export CFLAGS="-g -O2 -march=i686" ,然後運行../glibc/configure --prefix=/usr --disable-profile --enable-add-ons --with-headers=/usr/include --with-binutils=/usr/bin 這樣就不是默認安裝的路徑了安裝在/usr下,這會將glibc安裝為linux系統的標准庫。
執行make -j 。glibc的編譯相當耗時,可以給make加上-j選項並行編譯glibc。make -j
然後make install。
make時可能會有錯誤我就遇到了以下錯誤,我是這么解決的:
1、在編譯glibc的過程中可能出現錯誤:「../sysdeps/i386/fpu/s_frexp.S:66: Error: invalid identifier for ".ifdef"」,解決方法是:
1)、在glibc源碼目錄下找到文件:nptl/sysdeps/pthread/pt-initfini.c,找到第46行附近:asm ("\n#include "defs.h"");在其後添加代碼:
asm ("\n#if defined __i686 && defined __ASSEMBLER__");
asm ("\n#undef __i686");
asm ("\n#define __i686 __i686");
asm ("\n#endif");
2)、在glibc源碼目錄下找到文件:sysdeps/unix/sysv/linux/i386/sysdep.h,找到第30行附近:#include <tls.h>,在其後添加代碼:
#if defined __i686 && defined __ASSEMBLER__
#undef __i686
#define __i686 __i686
#endif
重新make
2、在編譯glibc的過程中可能出現錯誤:「./sysdeps/i386/i686/multiarch/strcmp.S:78: Error: Error: unrecognized symbol type "gnu_indirect_function"unrecognized symbol type "gnu_indirect_function"」,原因是沒有安裝新版的binutils,如果依照前面的步驟安裝了binutils-2.21應該不會出現該錯誤。(注第2個錯誤我沒遇到)
註:還有一個地方不知道是哪一步遇到錯誤了需要安裝libxml我在紅帽的系統鏡像中的server中找到了三個相關文件libxml2*.rpm安裝即可!!!!!!
至此,重啟reboot,打開QT運行常式,可能還有問題,我的就是還是有問題,解決辦法如下:
把QT的安裝目錄和QT中的bin都添加為環境變數,在/etc/profile下,具體怎麼填您應該知道吧,這里不提了。source /etc/profile一下
然後再點擊QT的左邊欄的項目在構建和運行的選項中,您可能哪裡沒有選擇,一定要讓你的項目有效和目錄正確,QT的版本正確!!!QT的gcc編譯目錄正確,gcc一般用的是QT文件中自帶的!!如果還不行,那就在你的在項目目錄項運行make clean!!如果還不對!!!vi Makefile 可能是這里有問題,如果不會改,就乾脆刪了rm Makefiel。然後再在QT中運行一下。

㈧ Linux 之mutex 源碼分析

 mutex相關的函數並不是linux kernel實現的,而是glibc實現的,源碼位於nptl目錄下。

http://ftp.gnu.org/pub/gnu/glibc/glibc-2.3.5.tar.gz

首先說數據結構:

typedef union

{

  struct

  {

    int __lock;

    unsigned int __count;

    int __owner;

    unsigned int __nusers;

    /* KIND must stay at this position in the structure to maintain

       binary compatibility.  */

    int __kind;

    int __spins;

  } __data;

  char __size[__SIZEOF_PTHREAD_MUTEX_T];

  long int __align;

} pthread_mutex_t;

 int __lock;  資源競爭引用計數

 int __kind; 鎖類型,init 函數中mutexattr 參數傳遞,該參數可以為NULL,一般為 PTHREAD_MUTEX_NORMAL

結構體其他元素暫時不了解,以後更新。

/*nptl/pthread_mutex_init.c*/

int

__pthread_mutex_init (mutex, mutexattr)

     pthread_mutex_t *mutex;

     const pthread_mutexattr_t *mutexattr;

{

  const struct pthread_mutexattr *imutexattr;

  assert (sizeof (pthread_mutex_t) <= __SIZEOF_PTHREAD_MUTEX_T);

  imutexattr = (const struct pthread_mutexattr *) mutexattr ?: &default_attr;

  /* Clear the whole variable.  */

  memset (mutex, '\0', __SIZEOF_PTHREAD_MUTEX_T);

  /* Copy the values from the attribute.  */

  mutex->__data.__kind = imutexattr->mutexkind & ~0x80000000;

  /* Default values: mutex not used yet.  */

  // mutex->__count = 0;        already done by memset

  // mutex->__owner = 0;        already done by memset

  // mutex->__nusers = 0;        already done by memset

  // mutex->__spins = 0;        already done by memset

  return 0;

}

init函數就比較簡單了,將mutex結構體清零,設置結構體中__kind屬性。

/*nptl/pthread_mutex_lock.c*/

int

__pthread_mutex_lock (mutex)

     pthread_mutex_t *mutex;

{

  assert (sizeof (mutex->__size) >= sizeof (mutex->__data));

  pid_t id = THREAD_GETMEM (THREAD_SELF, tid);

  switch (__builtin_expect (mutex->__data.__kind, PTHREAD_MUTEX_TIMED_NP))

    {

     …

    default:

      /* Correct code cannot set any other type.  */

    case PTHREAD_MUTEX_TIMED_NP:

    simple:

      /* Normal mutex.  */

      LLL_MUTEX_LOCK (mutex->__data.__lock);

      break;

  …

  }

  /* Record the ownership.  */

  assert (mutex->__data.__owner == 0);

  mutex->__data.__owner = id;

#ifndef NO_INCR

  ++mutex->__data.__nusers;

#endif

  return 0;

}

該函數主要是調用LLL_MUTEX_LOCK, 省略部分為根據mutex結構體__kind屬性不同值做些處理。

宏定義函數LLL_MUTEX_LOCK最終調用,將結構體mutex的__lock屬性作為參數傳遞進來

#define __lll_mutex_lock(futex)                                                \

  ((void) ({                                                                \

    int *__futex = (futex);                                                \

    if (atomic_compare_and_exchange_bool_acq (__futex, 1, 0) != 0)        \

      __lll_lock_wait (__futex);                                        \

  }))

atomic_compare_and_exchange_bool_acq (__futex, 1, 0)宏定義為:

#define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \

  ({ __typeof (mem) __gmemp = (mem);                                      \

     __typeof (*mem) __gnewval = (newval);                              \

      \

     *__gmemp == (oldval) ? (*__gmemp = __gnewval, 0) : 1; })

這個宏實現的功能是:

如果mem的值等於oldval,則把newval賦值給mem,放回0,否則不做任何處理,返回1.

由此可以看出,當mutex鎖限制的資源沒有競爭時,__lock 屬性被置為1,並返回0,不會調用__lll_lock_wait (__futex); 當存在競爭時,再次調用lock函數,該宏不做任何處理,返回1,調用__lll_lock_wait (__futex);

void

__lll_lock_wait (int *futex)

{

  do

    {

      int oldval = atomic_compare_and_exchange_val_acq (futex, 2, 1);

      if (oldval != 0)

lll_futex_wait (futex, 2);

    }

  while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0);

}

atomic_compare_and_exchange_val_acq (futex, 2, 1); 宏定義:

/* The only basic operation needed is compare and exchange.  */

#define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \

  ({ __typeof (mem) __gmemp = (mem);                                      \

     __typeof (*mem) __gret = *__gmemp;                                      \

     __typeof (*mem) __gnewval = (newval);                              \

      \

     if (__gret == (oldval))                                              \

       *__gmemp = __gnewval;                                              \

     __gret; })

這個宏實現的功能是,當mem等於oldval時,將mem置為newval,始終返回mem原始值。

此時,futex等於1,futex將被置為2,並且返回1. 進而調用

lll_futex_wait (futex, 2);

#define lll_futex_timed_wait(ftx, val, timespec)                        \

({                                                                        \

   DO_INLINE_SYSCALL(futex, 4, (long) (ftx), FUTEX_WAIT, (int) (val),        \

     (long) (timespec));                                \

   _r10 == -1 ? -_retval : _retval;                                        \

})

該宏對於不同的平台架構會用不同的實現,採用匯編語言實現系統調用。不過確定的是調用了Linux kernel的futex系統調用。

futex在linux kernel的實現位於:kernel/futex.c

SYSCALL_DEFINE6(futex, u32 __user *, uaddr, int, op, u32, val,

struct timespec __user *, utime, u32 __user *, uaddr2,

u32, val3)

{

struct timespec ts;

ktime_t t, *tp = NULL;

u32 val2 = 0;

int cmd = op & FUTEX_CMD_MASK;

if (utime && (cmd == FUTEX_WAIT || cmd == FUTEX_LOCK_PI ||

      cmd == FUTEX_WAIT_BITSET ||

      cmd == FUTEX_WAIT_REQUEUE_PI)) {

if (_from_user(&ts, utime, sizeof(ts)) != 0)

return -EFAULT;

if (!timespec_valid(&ts))

return -EINVAL;

t = timespec_to_ktime(ts);

if (cmd == FUTEX_WAIT)

t = ktime_add_safe(ktime_get(), t);

tp = &t;

}

/*

 * requeue parameter in 'utime' if cmd == FUTEX_*_REQUEUE_*.

 * number of waiters to wake in 'utime' if cmd == FUTEX_WAKE_OP.

 */

if (cmd == FUTEX_REQUEUE || cmd == FUTEX_CMP_REQUEUE ||

    cmd == FUTEX_CMP_REQUEUE_PI || cmd == FUTEX_WAKE_OP)

val2 = (u32) (unsigned long) utime;

return do_futex(uaddr, op, val, tp, uaddr2, val2, val3);

}

futex具有六個形參,pthread_mutex_lock最終只關注了前四個。futex函數對參數進行判斷和轉化之後,直接調用do_futex。

long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,

u32 __user *uaddr2, u32 val2, u32 val3)

{

int clockrt, ret = -ENOSYS;

int cmd = op & FUTEX_CMD_MASK;

int fshared = 0;

if (!(op & FUTEX_PRIVATE_FLAG))

fshared = 1;

clockrt = op & FUTEX_CLOCK_REALTIME;

if (clockrt && cmd != FUTEX_WAIT_BITSET && cmd != FUTEX_WAIT_REQUEUE_PI)

return -ENOSYS;

switch (cmd) {

case FUTEX_WAIT:

val3 = FUTEX_BITSET_MATCH_ANY;

case FUTEX_WAIT_BITSET:

ret = futex_wait(uaddr, fshared, val, timeout, val3, clockrt);

break;

         …

default:

ret = -ENOSYS;

}

return ret;

}

省略部分為對其他cmd的處理,pthread_mutex_lock函數最終傳入的cmd參數為FUTEX_WAIT,所以在此只關注此分之,分析futex_wait函數的實現。

static int futex_wait(u32 __user *uaddr, int fshared,

      u32 val, ktime_t *abs_time, u32 bitset, int clockrt)

{

struct hrtimer_sleeper timeout, *to = NULL;

struct restart_block *restart;

struct futex_hash_bucket *hb;

struct futex_q q;

int ret;

           … … //delete parameters check and convertion

retry:

/* Prepare to wait on uaddr. */

ret = futex_wait_setup(uaddr, val, fshared, &q, &hb);

if (ret)

goto out;

/* queue_me and wait for wakeup, timeout, or a signal. */

futex_wait_queue_me(hb, &q, to);

… … //other handlers

return ret;

}

futex_wait_setup 將線程放進休眠隊列中,

futex_wait_queue_me(hb, &q, to);將本線程休眠,等待喚醒。

喚醒後,__lll_lock_wait函數中的while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0); 語句將被執行,由於此時futex在pthread_mutex_unlock中置為0,所以atomic_compare_and_exchange_bool_acq (futex, 2, 0)語句將futex置為2,返回0. 退出循環,訪問用戶控制項的臨界資源。

/*nptl/pthread_mutex_unlock.c*/

int

internal_function attribute_hidden

__pthread_mutex_unlock_usercnt (mutex, decr)

     pthread_mutex_t *mutex;

     int decr;

{

  switch (__builtin_expect (mutex->__data.__kind, PTHREAD_MUTEX_TIMED_NP))

    {

   … …

    default:

      /* Correct code cannot set any other type.  */

    case PTHREAD_MUTEX_TIMED_NP:

    case PTHREAD_MUTEX_ADAPTIVE_NP:

      /* Normal mutex.  Nothing special to do.  */

      break;

    }

  /* Always reset the owner field.  */

  mutex->__data.__owner = 0;

  if (decr)

    /* One less user.  */

    --mutex->__data.__nusers;

  /* Unlock.  */

  lll_mutex_unlock (mutex->__data.__lock);

  return 0;

}

省略部分是針對不同的__kind屬性值做的一些處理,最終調用 lll_mutex_unlock。

該宏函數最終的定義為:

#define __lll_mutex_unlock(futex)                        \

  ((void) ({                                                \

    int *__futex = (futex);                                \

    int __val = atomic_exchange_rel (__futex, 0);        \

\

    if (__builtin_expect (__val > 1, 0))                \

      lll_futex_wake (__futex, 1);                        \

  }))

atomic_exchange_rel (__futex, 0);宏為:

#define atomic_exchange_rel(mem, value) \

  (__sync_synchronize (), __sync_lock_test_and_set (mem, value))

實現功能為:將mem設置為value,返回原始mem值。

__builtin_expect (__val > 1, 0) 是編譯器優化語句,告訴編譯器期望值,也就是大多數情況下__val > 1 ?是0,其邏輯判斷依然為if(__val > 1)為真的話執行 lll_futex_wake。

現在分析,在資源沒有被競爭的情況下,__futex 為1,那麼返回值__val則為1,那麼 lll_futex_wake (__futex, 1);        不會被執行,不產生系統調用。 當資源產生競爭的情況時,根據對pthread_mutex_lock 函數的分析,__futex為2, __val則為2,執行 lll_futex_wake (__futex, 1); 從而喚醒等在臨界資源的線程。

lll_futex_wake (__futex, 1); 最終會調動同一個系統調用,即futex, 只是傳遞的cmd參數為FUTEX_WAKE。

在linux kernel的futex實現中,調用

static int futex_wake(u32 __user *uaddr, int fshared, int nr_wake, u32 bitset)

{

struct futex_hash_bucket *hb;

struct futex_q *this, *next;

struct plist_head *head;

union futex_key key = FUTEX_KEY_INIT;

int ret;

if (!bitset)

return -EINVAL;

ret = get_futex_key(uaddr, fshared, &key);

if (unlikely(ret != 0))

goto out;

hb = hash_futex(&key);

spin_lock(&hb->lock);

head = &hb->chain;

plist_for_each_entry_safe(this, next, head, list) {

if (match_futex (&this->key, &key)) {

if (this->pi_state || this->rt_waiter) {

ret = -EINVAL;

break;

}

/* Check if one of the bits is set in both bitsets */

if (!(this->bitset & bitset))

continue;

wake_futex(this);

if (++ret >= nr_wake)

break;

}

}

spin_unlock(&hb->lock);

put_futex_key(fshared, &key);

out:

return ret;

}

該函數遍歷在該mutex上休眠的所有線程,調用wake_futex進行喚醒,

static void wake_futex(struct futex_q *q)

{

struct task_struct *p = q->task;

/*

 * We set q->lock_ptr = NULL _before_ we wake up the task. If

 * a non futex wake up happens on another CPU then the task

 * might exit and p would dereference a non existing task

 * struct. Prevent this by holding a reference on p across the

 * wake up.

 */

get_task_struct(p);

plist_del(&q->list, &q->list.plist);

/*

 * The waiting task can free the futex_q as soon as

 * q->lock_ptr = NULL is written, without taking any locks. A

 * memory barrier is required here to prevent the following

 * store to lock_ptr from getting ahead of the plist_del.

 */

smp_wmb();

q->lock_ptr = NULL;

wake_up_state(p, TASK_NORMAL);

put_task_struct(p);

}

wake_up_state(p, TASK_NORMAL);  的實現位於kernel/sched.c中,屬於linux進程調度的技術。

㈨ gcc編譯時默認使用的庫在哪個目錄(是標准C庫,還是glibc庫 )

看你包含的頭文件和使用的函數啊~兩者包含的函數不一樣~
你要是使用fopen/memcpy等等這樣標准C的函數,當然會在鏈接時使用到標准C庫(ANSI C),如果你使用了read/write這些glibc庫實現的函數,肯定就在鏈接時使用到glibc庫~

具體使用了什麼庫,要看你調用的函數了~可能不會僅僅只包含一個庫~

Linux下,庫的路徑一般是:/lib,/usr/lib,/usr/local/lib等,這些路徑一般會在/etc/ld.so.conf 中標記出來,如果需要添加特殊位置的庫,可以把庫的路徑添加到/etc/ld.so.conf中去,並且執行ldconfig來使得新路徑立即生效~

http://linux.die.net/man/8/ldconfig

㈩ 多線程庫的源碼在哪,為啥在glibc裡面沒有

Linux下的glic庫的源碼鏈接:
http://ftp.gnu.org/gnu/glibc/,你可以下載最新版本的glibc-2.24.tar.gz這個壓縮文件,在Windows系統下直接用WinRAR解壓即可,如果在Linux系統下用命令行解壓的話,命令如下:tar -xzvf glibc-2.24.tar.gz。

閱讀全文

與glibc源碼在哪個目錄相關的資料

熱點內容
c51單片機原 瀏覽:194
交行app在哪裡買東西 瀏覽:37
python高手之路pdf 瀏覽:82
iphone怎麼像安卓一樣返回 瀏覽:160
linuxtomcat埠佔用怎麼辦 瀏覽:720
表演pdf 瀏覽:921
微信如何更換伺服器 瀏覽:861
android使用html5 瀏覽:458
python可視化極坐標 瀏覽:384
程序員喜歡綠色 瀏覽:730
php編譯的主流軟體 瀏覽:364
操作系統伺服器版本下載地址 瀏覽:245
手機管家加密圖片打不開 瀏覽:839
基於單片機的智能散熱器控制器的設計 瀏覽:471
pdfadobereaderxi 瀏覽:488
本田雅閣壓縮機工作 瀏覽:680
河北編程排行榜 瀏覽:134
胸椎12輕度壓縮性骨折 瀏覽:104
演算法英文pdf 瀏覽:358
編譯原理第3版清華課後答案第二章 瀏覽:165