linux命令解释程序实验,实验二 命令解释程序的使用
實(shí)驗(yàn)二 命令解釋程序的使用
一、實(shí)驗(yàn)?zāi)康?/p>
掌握UNIX或LINUX環(huán)境下命令解釋程序的使用
能對(duì)編寫(xiě)簡(jiǎn)單的C程序,進(jìn)行編譯運(yùn)行和調(diào)試。
二、實(shí)驗(yàn)內(nèi)容
輸入LINUX相關(guān)命令后記錄系統(tǒng)輸出
簡(jiǎn)單的C程序,進(jìn)行編譯運(yùn)行和調(diào)試
三、實(shí)驗(yàn)步驟
1、命令操作
1) 瀏覽目錄和文件的各種屬性 ls –l、
2) 顯示文件內(nèi)容 cat、more、
3) 改變文件和目錄的權(quán)限chmod、
4) 顯示當(dāng)前目錄 pwd、
5) 文字統(tǒng)計(jì) wc、
6) 查看時(shí)間命令 date 、time、
7) 幫助命令 help、
8) 查看與刪除進(jìn)程命令ps, kill、
9) 查看在線用戶 who
2、GNU gcc
GCC 是GNU提供的C 和C++ 編譯器。實(shí)際上,GCC 能夠編譯三種語(yǔ)言:C、C++ 和Object C(C 語(yǔ)言的一種面向?qū)ο髷U(kuò)展)。利用gcc命令可同時(shí)編譯并連接C 和C++ 源程序。如果你有兩個(gè)或少數(shù)幾個(gè)C 源文件,也可以方便地利用GCC 編譯、連接并生成可執(zhí)行文件。
* gcc 命令的基本用法如下:
gcc [options] [filenames]
* gcc的主要選項(xiàng):
-ansi 只支持ANSI 標(biāo)準(zhǔn)的C語(yǔ)法。這一選項(xiàng)將禁止GNU C的某些特色,例如asm 或typeof 關(guān)鍵詞。 -c 只編譯并生成目標(biāo)文件。 -DMACRO 以字符串“1”定義MACRO 宏。 -DMACRO=DEFN 以字符串“DEFN”定義MACRO 宏。 -E 只運(yùn)行C 預(yù)編譯器。 -g 生成調(diào)試信息。GNU 調(diào)試器可利用該信息。 -IDIRECTORY 指定額外的頭文件搜索路徑DIRECTORY。 -LDIRECTORY 指定額外的函數(shù)庫(kù)搜索路徑DIRECTORY。 -lLIBRARY 連接時(shí)搜索指定的函數(shù)庫(kù)LIBRARY。 -m486 針對(duì)486 進(jìn)行代碼優(yōu)化。 -o FILE 生成指定的輸出文件。用在生成可執(zhí)行文件時(shí)。 -O0 不進(jìn)行優(yōu)化處理。 -O 或-O1 優(yōu)化生成代碼。 -O2 進(jìn)一步優(yōu)化。 -O3 比-O2 更進(jìn)一步優(yōu)化,包括inline 函數(shù)。 -shared 生成共享目標(biāo)文件。通常用在建立共享庫(kù)時(shí)。 -static 禁止使用共享連接。 -UMACRO 取消對(duì)MACRO 宏的定義。 -w 不生成任何警告信息。 -Wall 生成所有警告信息。
<1> 輸入gcc test.c
<2> 輸入ls查看,目錄下應(yīng)該有個(gè)a.out文件
<3> 輸入./a.out,運(yùn)行程序,屏幕上顯示
The string is hello world
The string printed backward is
<4> 如果想給程序重命名,使用編譯選項(xiàng)-o重新編譯。輸入gcc –o test test.c
<5> 輸入ls查看,目錄下應(yīng)該有個(gè)test文件
<3> 輸入 ./test,運(yùn)行程序
這個(gè)程序執(zhí)行時(shí)顯示如下結(jié)果:
The string is hello world
The string printed backward is
輸出的第一行是正確的,但第二行打印出的東西并不是我們所期望的。我們所設(shè)想的輸出應(yīng)該是: The string printed backward is dlrow olleh。由于某些原因,my_print2 函數(shù)沒(méi)有正常工作。下面讓我們用gdb 看看問(wèn)題究竟出在哪兒。
3、GNU gdb
gdb 是一個(gè)用來(lái)調(diào)試C 和C++ 程序的強(qiáng)力調(diào)試器。以下是gdb 所提供的一些功能:它使你能監(jiān)視你程序中變量的值;它使你能設(shè)置斷點(diǎn)以使程序在指定的代碼行上停止執(zhí)行;它使你能一行行的執(zhí)行你的代碼。 在命令行上鍵入gdb并按回車(chē)鍵就可以運(yùn)行g(shù)db 了。
**gdb 的常用命令:
File 裝入想要調(diào)試的可執(zhí)行文件。
List 列出產(chǎn)生執(zhí)行文件的源代碼的一部分。
Run 執(zhí)行當(dāng)前被調(diào)試的程序。
Break 在代碼里設(shè)置斷點(diǎn),這將使程序執(zhí)行到這里時(shí)被掛起。
Next 執(zhí)行一行源代碼但不進(jìn)入函數(shù)內(nèi)部。
Step 執(zhí)行一行源代碼而且進(jìn)入函數(shù)內(nèi)部。
Watch 使你能監(jiān)視一個(gè)變量的值而不管它何時(shí)被改變。
Print 使你能查看變量值。
Kill 終止正在調(diào)試的程序。
Quit 終止gdb。**
<1>加入調(diào)試編譯選項(xiàng)-ggdb,重新編譯。輸入gcc -ggdb -o test test.c
<2>輸入命令gdb進(jìn)入調(diào)試環(huán)境。
<3>在gdb 命令行提示符下鍵入file test,裝入程序。屏幕顯示:
Reading symbols from test...done.
<4>輸入命令run,運(yùn)行程序。屏幕顯示:
Starting program: /home/zjh/test
The string is hello world
The string printed backward is
Program exited with code 040.
<5>輸入命令list,顯示程序代碼
1 #include
2
3 void my_print(char *);
4 void my_print2(char *);
5
6 main()
7 {
8 char my_string[] = "hello world";
9 my_print(my_string);
10 my_print2(my_string);
再輸入命令list,顯示后續(xù)的程序代碼。
<6>輸入break 26,屏幕顯示
Breakpoint 1 at 0x80485a0: file test.c, line 26.
<7>輸入run,屏幕顯示
Starting program: /home/zjh/test
The string is hello world
Breakpoint 1, my_print2 (string=0xbffffa40 "hello world") at test.c:26
26 string2[size - i] = string[i];
<8> watch string2[size-i],屏幕顯示
Watchpoint 2: string2[size - i]
<9>輸入next,程序運(yùn)行了第26行,屏幕顯示
Watchpoint 2: string2[size - i]
Old value = 0 '\000'
New value = 104 'h'
my_print2 (string=0xbffffa40 "hello world") at test.c:24
24 for (i = 0; i < size; i++)
<10> 在gdb 提示符下按回車(chē)鍵將重復(fù)上一個(gè)命令。
<11> 通過(guò)跟蹤可以發(fā)現(xiàn),當(dāng)i=10 時(shí),表達(dá)式string2[size - i] 的值等于‘d‘,size-i的值等于1,最后一個(gè)字符已經(jīng)拷到新串里了。如果你再把循環(huán)執(zhí)行下去,你會(huì)看到已經(jīng)沒(méi)有值分配給string2[0] 了,而它是新串的第一個(gè)字符,因?yàn)閙alloc函數(shù)在分配內(nèi)存時(shí)把它們初始化為空(null)字符。所以string2 的第一個(gè)字符是空字符。這解釋了為什么在打印string2 時(shí)沒(méi)有任何輸出了。
<12> 現(xiàn)在找出了問(wèn)題出在第26行,改正程序,重新編譯運(yùn)行。正確結(jié)果如下:
The string is hello world
The string printed backward is dlrow olleh
修改后test.c的完整代碼如下:
4、GNU make
在大型的開(kāi)發(fā)項(xiàng)目中,通常有幾十到上百個(gè)的源文件,如果每次均手工鍵入gcc 命令進(jìn)行編譯的話,則會(huì)非常不方便。因此,人們通常利用make 工具來(lái)自動(dòng)完成編譯工作。這些工作包括:如果僅修改了某幾個(gè)源文件,則只重新編譯這幾個(gè)源文件;如果某個(gè)頭文件被修改了,則重新編譯所有包含該頭文件的源文件。利用這種自動(dòng)編譯可大大簡(jiǎn)化開(kāi)發(fā)工作,避免不必要的重新編譯。實(shí)際上,make工具通過(guò)一個(gè)稱為makefile 的文件來(lái)完成并自動(dòng)維護(hù)編譯工作。makefile需要按照某種語(yǔ)法進(jìn)行編寫(xiě),其中說(shuō)明了如何編譯各個(gè)源文件并連接生成可執(zhí)行文件,并定義了源文件之間的依賴關(guān)系。當(dāng)修改了其中某個(gè)源文件時(shí),如果其他源文件依賴于該文件,則也要重新編譯所有依賴該文件的源文件。
makefile文件是許多編譯器,包括Windows NT下的編譯器維護(hù)編譯信息的常用方法,只是在集成開(kāi)發(fā)環(huán)境中,用戶通過(guò)友好的界面修改makefile 文件而已。默認(rèn)情況下,GNU make 工具在當(dāng)前工作目錄中按如下順序搜索makefile:
* GNUmakefile
* makefile
* Makefile
在UNIX 系統(tǒng)中,習(xí)慣使用Makefile 作為makfile 文件。如果要使用其他文件作為makefile,則可利用類似下面的make 命令選項(xiàng)指定makefile 文件:
$ make -f Makefile.debug
makefile 中一般包含如下內(nèi)容:
1. 需要由make 工具創(chuàng)建的項(xiàng)目,通常是目標(biāo)文件和可執(zhí)行文件。通常使用“目標(biāo)(target)”一詞來(lái)表示要?jiǎng)?chuàng)建的項(xiàng)目。
2. 要?jiǎng)?chuàng)建的項(xiàng)目依賴于哪些文件。
3. 創(chuàng)建每個(gè)項(xiàng)目時(shí)需要運(yùn)行的命令。
例如,假設(shè)你現(xiàn)在有一個(gè)C++ 源文件test.C,該源文件包含有自定義的頭文件test.h,
則目標(biāo)文件test.o 明確依賴于兩個(gè)源文件:test.C 和test.h。另外,你可能只希望利用g++
命令來(lái)生成test.o 目標(biāo)文件。這時(shí),就可以利用如下的makefile 來(lái)定義test.o 的創(chuàng)建規(guī)則:
# This makefile just is a example.
# The following lines indicate how test.o depends
# test.C and test.h, and how to create test.o
test.o: test.C test.h
g++ -c -g test.C
從上面的例子注意到,第一個(gè)字符為# 的行為注釋行。第一個(gè)非注釋行指定test.o 為目標(biāo),并且依賴于test.C 和test.h 文件。隨后的行指定了如何從目標(biāo)所依賴的文件建立目標(biāo)。當(dāng)test.C 或test.h 文件在編譯之后又被修改,則make 工具可自動(dòng)重新編譯test.o,如果在前后兩次編譯之間,test.C 和test.h 均沒(méi)有被修改,而且test.o 還存在的話,就沒(méi)有必要重新編譯。這種依賴關(guān)系在多源文件的程序編譯中尤其重要。通過(guò)這種依賴關(guān)系的定義,make 工具可避免許多不必要的編譯工作。當(dāng)然,利用Shell 腳本也可以達(dá)到自動(dòng)編譯的效果,但是,Shell 腳本將全部編譯任何源文件,包括哪些不必要重新編譯的源文件,而make 工具則可根據(jù)目標(biāo)上一次編譯的時(shí)間和目標(biāo)所依賴的源文件的更新時(shí)間而自動(dòng)判斷應(yīng)當(dāng)編譯哪個(gè)源文件。一個(gè)makefile 文件中可定義多個(gè)目標(biāo),利用make target 命令可指定要編譯的目標(biāo),如果不指定目標(biāo),則使用第一個(gè)目標(biāo)。通常,makefile 中定義有clean 目標(biāo),可用來(lái)清除編譯過(guò)程中的中間文件,例如:
clean:
rm -f *.o
運(yùn)行make clean 時(shí),將執(zhí)行rm -f *.o 命令,最終刪除所有編譯過(guò)程中產(chǎn)生的所有中間文件。
makefile 變量:
GNU 的make 工具除提供有建立目標(biāo)的基本功能之外,還有許多便于表達(dá)依賴性關(guān)系以及建立目標(biāo)的命令的特色。其中之一就是變量或宏的定義能力。如果你要以相同的編譯選項(xiàng)同時(shí)編譯十幾個(gè)C 源文件,而為每個(gè)目標(biāo)的編譯指定冗長(zhǎng)的編譯選項(xiàng)的話,將是非常乏味的。但利用簡(jiǎn)單的 變量定義 ,可避免這種乏味的工作:
# Define macros for name of compiler
CC = gcc
# Define a macr o for the CC flags
CCFLAGS = -D_DEBUG -g -m486
# A rule for building a object file
test.o: test.c test.h
$(CC) -c $(CCFLAGS) test.c
在上面的例子中,CC 和CCFLAGS 就是make 的變量。GNU make 通常稱之為變量,而其他UNIX 的make 工具稱之為宏,實(shí)際是同一個(gè)東西。在makefile 中引用變量的值時(shí),只需變量名之前添加$ 符號(hào),如上面的$(CC)和$(CCFLAGS)。
任務(wù):假設(shè)你有兩個(gè)源文件main.c 和factorial.c 兩個(gè)源文件,現(xiàn)在要編譯生成一個(gè)計(jì)算階乘的程序。
// factorial.c
int factorial(int n) {
if (n <= 1)
return 1;
else
return factorial(n - 1)*n;
}
// main.c
int factorial(int n);
int main(int argc, char **argy){
int n;
if(argc < 2){
printf("Usage:%s n\n", argy[0]);
return -1;
}
else {
n = atoi(argy[1]);
printf("Factorial of %d is %d.\n", n, factorial(n));
}
return 0;
}
請(qǐng)編寫(xiě)出編譯程序factorial 的makefile,并編譯。
* Makefile文件的內(nèi)容如下:
* 編譯執(zhí)行
四、總結(jié)
問(wèn)題:在使用watch string[size – i]命令設(shè)置觀察點(diǎn)時(shí),fedora上使用info watchpoints時(shí)雖然也顯示也設(shè)置了觀察點(diǎn),但是當(dāng)值改變時(shí),gdb卻沒(méi)顯示出來(lái)。
方法:換另一個(gè)環(huán)境運(yùn)行調(diào)試,比如centos7.3等等
總結(jié)
以上是生活随笔為你收集整理的linux命令解释程序实验,实验二 命令解释程序的使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: mysql 图片base64_关于图片的
- 下一篇: 网络命令使用