Linux操作系統(tǒng)-第6講C語言編程_第1頁
Linux操作系統(tǒng)-第6講C語言編程_第2頁
Linux操作系統(tǒng)-第6講C語言編程_第3頁
Linux操作系統(tǒng)-第6講C語言編程_第4頁
Linux操作系統(tǒng)-第6講C語言編程_第5頁
已閱讀5頁,還剩37頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、第6講 C語言編程 gcc、gdb的使用與Linux進程創(chuàng)建Linux的程序文件名后綴后綴后綴文件類型文件類型.cC語言源代碼文件.c或.cc或.cxx C+源代碼文件.s匯編語言源代碼文件.h頭文件.i已預(yù)處理過的C語言源代碼文件.ii已預(yù)處理過的C+語言源代碼文件.S已預(yù)處理過的匯編語言源代碼文件.o編譯后的目標文件.so目標文件構(gòu)成的動態(tài)庫文件.a目標文件構(gòu)成的靜態(tài)庫文件GCC編譯器 GCC是GNU C Comiler的縮寫,是GNU推出的 完全免費、功能強大,支持多種語言(C,C+,F(xiàn)ORTRAN,PASCAL,ADA)的編譯器。 支持多種硬件平臺,執(zhí)行效率快多種硬件平臺,執(zhí)行效率快,

2、比一般的編譯器的執(zhí)行效率高20%30% 。 查看gcc版本:gcc -vGCC編譯過程 預(yù)處理預(yù)處理:調(diào)用linux的CPP預(yù)編譯程序,生成.i的臨時文件。 將#include 文件拷貝到要編譯的源文件中。 用實際值替代#define文本。 在調(diào)用宏的地方進行宏替換。命令#gcc E o test.i test.c或#cpp test.ctest.i 匯編匯編:調(diào)用linux的as匯編編譯程序,生成.s的匯編文件。命令#gcc S test.c 編譯編譯:調(diào)用linux的cc1編譯程序,生成.o的目標文件。命令#gcc c test.c 鏈接鏈接:調(diào)用linux的ld鏈接程序,生成最后的可執(zhí)行

3、文件。命令#gcc o test test.c 執(zhí)行執(zhí)行#./testGcc的基本選項 Gcc options filenames Options有如下常用選項: -S:對源程序進行預(yù)處理和編譯,不進行匯編和鏈接,自動生成匯編文件。 -c:執(zhí)行預(yù)處理、編譯、匯編而不鏈接,生成.o為后綴的目標文件。通常用于編譯沒有主程序的子程序文件。 -o output_filename:指定輸出文件名為output_filename,不指定時缺省文件名為a.out -g:產(chǎn)生調(diào)試信息。 -x:指定待編譯程序的語言。如gcc xc+ test.cpp -O0:不優(yōu)化。 -O1:第一級優(yōu)化。允許與-g共用,編譯鏈

4、接過程稍慢。 -O2:第二級優(yōu)化。特別對于大型程序,可以大幅度提高運行速度。 -O3:第三級優(yōu)化。與O2的區(qū)別在于它允許把函數(shù)直接插入到調(diào)用的代碼處 。Gcc函數(shù)庫 Gcc options 選項: -lm 指定函數(shù)庫 -L 指定函數(shù)庫的搜尋目錄 -I指定include 所在目錄。 Gcc函數(shù)庫 共享函數(shù)庫的格式fun.so.x.x.x,其中x.x.x指版本號,共享函數(shù)庫通常會有符號鏈接指向靜態(tài)函數(shù)庫或相關(guān)so的文件。 命令ldd用于查出程序所用的共享函數(shù)庫。 例1: ldd test 例2: ldd sin分別編譯main()和其他函數(shù)程序維護工具make Linux 系統(tǒng)的許多軟件都是使用m

5、ake程序和 makefile來維護而實現(xiàn)自動編譯的, make程序自動確定需要重新編譯的文件,只對他們進行重新編譯,然后鏈接生成可執(zhí)行文件。 make程序是在程序調(diào)試、改進過程中必不可少的工具。 make程序可以自動對已修改的源程序進行編譯,而對未改變的部分則跳過編譯步驟,從而大大提高效率,是源程序的編譯、鏈接、管理更加規(guī)范和有條理。 make程序需要兩方面的信息:一是可執(zhí)行文件和各個程序模塊之間的關(guān)系,二是文件的修改日期。 可執(zhí)行文件和各個程序模塊之間的關(guān)系通常記錄在makefile或Makefile中。makefile語法target(目標名):dependency(依賴模塊)comma

6、nd(命令行) 依賴關(guān)系一行放不下時,續(xù)行用“”標記。 命令行command之前不可有空格,只是加制表符tab 命令行command行中的命令若不想顯示在屏幕上則在其前加 例如makefile文件為test : testmain.o testfun.ogcc -o test testmain.o testfun.otestmain.o : testmain.cgcc -c testmain.ctestfun.o: testfun.cgcc -c testfun.cclean:rm f test*.o寫makefile. 注意:命令前用鍵GDB調(diào)試器 GDB是GNU自帶的調(diào)試工具,GDB支持C,

7、C+,Modula-2等。 編譯程序時加調(diào)試開關(guān) #gcc g -o test test.c 進入調(diào)試狀態(tài)# gdb test GDB常用命令命令名命令名參數(shù)參數(shù)說明說明break行號、函數(shù)名、地址設(shè)置斷點。clear行號、函數(shù)名、地址去掉指定位置的斷點,未指定位置則去掉當(dāng)前斷點。run命令 參數(shù)開始運行被調(diào)試程序。continue繼續(xù)程序運行,直到下一個斷點或程序結(jié)束list-、行號、函數(shù)名、地址顯示指定行的源代碼,-表示前10行,否則回10行。next數(shù)值單步運行,不進入函數(shù)體。step數(shù)值單步運行,進入函數(shù)體。disp表達式顯示表達式的值。print表達式臨時顯示表達式的值,下次運行時表

8、達式的值不顯示。call函數(shù)程序執(zhí)行中調(diào)用指定函數(shù)。finish繼續(xù)程序運行,直到下一個斷點或返回調(diào)用者。file文件名打開要調(diào)試的文件。quit退出GDB。GDB其他使用技巧 在GDB下執(zhí)行shell命令( gdb)shell commandline 重復(fù)上次命令的執(zhí)行直接回車 指令級的調(diào)試 stepi/nexti(指令級單步執(zhí)行) disp/x $寄存器(顯示寄存器的值) 出錯后的調(diào)試。程序發(fā)生錯誤時,會在當(dāng)前目錄下產(chǎn)生一個名為core的內(nèi)存映像文件。 #gdb a.out core 獲得幫助 Shell狀態(tài)下,運行info gdb 或 man gdb GDB狀態(tài)下,運行(gdb)help

9、或(gdb)help GDB命令名Linux中的進程 進程這個概念是伴隨著Unix的產(chǎn)生而出現(xiàn)的,Unix之父Dennis Ritchie當(dāng)初用來發(fā)表Unix的論文的時候就提出了用進程的觀點來看待整個操作系統(tǒng),隨著操作系統(tǒng)理論的發(fā)展,進程作為程序執(zhí)行的實體和資源分配的單位的觀念也在變化。線程的出現(xiàn),改變了進程的傳統(tǒng)概念。但是在linux中,進程仍然保留著傳統(tǒng)的意義,它包括四個要素: 程序段。 系統(tǒng)堆??臻g。 task_struct結(jié)構(gòu)(PCB)。 專有內(nèi)存空間。Linux中的線程單進程單線程單進程多線程多進程每個進程一個線程多進程每個進程多個線程linux的線程模型是一種一對一模型,也就是每個

10、線程實際上在核心是一個單獨的進程,核心的調(diào)度程序負責(zé)線程的調(diào)度。進程控制塊和堆棧 作為描述進程信息,操作系統(tǒng)感知進程存在的進程控制塊(PCB),在linux中是由結(jié)構(gòu)task_struct來實現(xiàn)的。t a s k _ s t r u c t 的 定 義 在include/linux/sched.h中給出。 當(dāng)產(chǎn)生一個的進程時,在內(nèi)核空間中會分配一個8K的空間來記錄新進程的信息,其中包括task_struct結(jié)構(gòu)和為進程分配的內(nèi)核堆棧,當(dāng)進程由于系統(tǒng)調(diào)用轉(zhuǎn)到內(nèi)核時,就要切換到該進程的內(nèi)核堆棧了。 task_struct結(jié)構(gòu)可以被系統(tǒng)中的許多模塊訪問,如調(diào)度程序、資源分配程序、中斷處 理 程 序

11、等 。 由 于task_struct結(jié)構(gòu)經(jīng)常被訪問,它常駐內(nèi)存。 task_struct系統(tǒng)空間堆棧(大約7KB)兩個連續(xù)物理頁面(8KB)linux進程的創(chuàng)建與執(zhí)行 linux進程創(chuàng)建創(chuàng)建用以下系統(tǒng)調(diào)用完成: 系統(tǒng)調(diào)用fork():父進程的所有資源通過數(shù)據(jù)結(jié)構(gòu)復(fù)制全部給子進程。 fork()用于創(chuàng)建進程。用于創(chuàng)建進程。 后增設(shè)的系統(tǒng)調(diào)用vfork(): 除了task_struct和系統(tǒng)空間堆棧以外的資源全部都通過數(shù)據(jù)結(jié)構(gòu)指針的復(fù)制“遺傳”。所以vfork創(chuàng)建的是線程,而創(chuàng)建的是線程,而不是進程。不是進程。 系統(tǒng)調(diào)用clone():進程的資源有選擇地復(fù)制給子進程,而沒有復(fù)制的數(shù)據(jù)結(jié)構(gòu)(資源如內(nèi)

12、存空間)通過指針的復(fù)制讓子進程共享。 用clone既可以既可以創(chuàng)建創(chuàng)建一個進程,也可以創(chuàng)建一個進程,也可以創(chuàng)建一個線程。一個線程。創(chuàng)建子進程后父進程的選擇 創(chuàng)建子進程后,父進程可以有以下幾種選擇: 父進程不受影響,繼續(xù)執(zhí)行,也稱“異步”方式。 父進程停下來,等待子進程完成后,再繼續(xù)執(zhí)行,也稱“同步”方式。用系統(tǒng)調(diào)用wait()和 waitpid()實現(xiàn)。 wait()是等待所有子進程完成; waitpid()等待特定子進程完成。 父進程創(chuàng)建了子進程后,馬上結(jié)束自己。用系統(tǒng)調(diào)用exit()實現(xiàn)。進程的撤消 用戶程序中好像沒有調(diào)用exit()就結(jié)束了,實際上當(dāng)用戶程序編譯時,編譯器在程序的結(jié)尾處加

13、上一個exit()系統(tǒng)調(diào)用的,所以當(dāng)進程完成任務(wù)時,就會調(diào)用exit()來結(jié)束自己。用戶程序也可以主動地調(diào)用exit()來顯式的結(jié)束。 fork() #include #include pid_t fork(void); fork()函數(shù)是一個單調(diào)用雙返回函數(shù)。調(diào)用后,子進程是父進程的一個復(fù)制,父子進程都從fork()語句的一條語句開始執(zhí)行。 調(diào)用正確完成時, 給父進程返回的是被創(chuàng)建子進程的進程標識符(給父進程返回的是被創(chuàng)建子進程的進程標識符(0)。)。 給子進程返回的是給子進程返回的是0。 調(diào)用失敗時給父進程返回調(diào)用失敗時給父進程返回-1。fork()使用舉例/fork .#include

14、#include #include int glob = 3;int main(void) pid_t pid; int loc = 3; printf(Before fork :glob=%d,loc=%dn,glob,loc); pid = fork(); if (pid 0) printf(fork errorn); exit(0); else if (pid = 0) glob = glob + 1; loc= loc - 1;/sleep(1); printf(Now child process changes glob=%d and loc=%dn,glob,loc); else

15、printf(parent process doesnt changes the glob=%d and loc=%d n,glob,loc); printf(End pid=%d,:glob=%d,loc=%dn,pid,glob,loc); exit(0);fork()運行結(jié)果分析 fork()可能產(chǎn)生兩種運行結(jié)果: 一種為:子進程先運行,父進程后運行 另一種為:父進程先運行,子進程后運行vfork()使用舉例/vfork .#include #include #include int glob = 3;int main(void) pid_t pid; int loc = 3; prin

16、tf(Before vfork :glob=%d,loc=%dn,glob,loc); pid = vfork(); if (pid 0) printf(vfork errorn); exit(0); else if (pid = 0) glob = glob + 1; loc= loc - 1;sleep(1); printf(child process changes glob=%d and loc=%dn,glob,loc); exit(0); else printf(parent process doesnt changes the glob=%d and loc=%d n,glob,

17、loc); printf(End:glob=%d,loc=%dn,glob,loc); exit(0);vfork()運行結(jié)果分析 vfork()可能產(chǎn)生兩種運行方式,但變量最后結(jié)果是一樣的(因為是指針復(fù)制):clone()#include #include int clone(int(*fn)(void*),void *child_stack, int flags,void *arg); 與fork()不同的是,clone()函數(shù)創(chuàng)建的線程或進程,另立門戶。 當(dāng)線程被創(chuàng)建后,執(zhí)行fn(arg) 指定的函數(shù)。 fn是指向執(zhí)行函數(shù)的指針,arg是傳遞給含數(shù)的參數(shù)。當(dāng) fn(arg) 執(zhí)行終止時,

18、線程撤消。 fn返回的是整型值,即線程的退出碼。線程也可以調(diào)用exit()終止自己。child_stack說明線程使用的堆棧,它是指向堆棧的指針。 當(dāng)線程終止時,用flags的低字節(jié)給父進程返回信號, 調(diào)用正確完成時,與fork()一樣,給父進程返回的是被創(chuàng)建線程的標識符。 調(diào)用失敗時給父進程返回-1。 clone()函數(shù)是Linux專用的。clone()使用舉例#include #include int myfun() printf(Now in thread!n); exit(0);int main() int fd; void *child_stack; int flag; typede

19、f int (*fn)(void *); void *arg; int p20; child_stack = p; fd = clone(fn)myfun,child_stack,flag, arg); if (fd 0) printf(Thread created!fd=%dn,fd); else printf(Thread create Failn); sleep(1); exit(0);clone()運行結(jié)果分析 clone()是Linux專用的,不能在其他類unix系統(tǒng)上使用。用clone傳遞參數(shù)#include #include int myfun(int *argfun) int

20、x,y; printf(Now in threadn); x = *argfun; argfun = argfun + 1; y = *argfun; if (xy) printf(max=%dn,x); else printf(max=%dn,y); /exit(0);int main() int fd; void *child_stack; int flag; typedef int (*fn)(void *); void *arg; int p20; int a2; a0 = 6; a1 = 5; child_stack = p; arg = a; fd = clone(fn)myfun

21、(arg),child_stack,flag, arg); if (fd 0) printf(Thread created!fd=%dn,fd); else printf(Thread create Failn); exit(0);父子進程同步wait #include #include pid_t wait(int *status);/等待所有子進程完成 pid_t waitpid(pid_t pid, int *status, int options);/等待特定子進程完成。wait使用舉例/forkwait#include #include #include int main(void)

22、 pid_t pid; pid = fork(); if (pid 0) printf(fork errorn); exit(0); else if (pid = 0) printf(Now child processn); sleep(1); exit(0); wait(); printf(End parent now!n ); exit(0);將wait()可以改為waitpid(pid),效果相同運行結(jié)果分析 運行結(jié)果只有一個,子進程先執(zhí)行,子進程結(jié)束后父進程再執(zhí)行。kill( )函數(shù) kill()函數(shù)用于刪除執(zhí)行中的程序或者任務(wù)。 調(diào)用格式:調(diào)用格式: kill(int PID,int

23、 IID); 其中:PID是要被殺死的進程號,IID為向?qū)⒈粴⑺赖倪M程發(fā)送的中斷號。 signal()函數(shù)signal())函數(shù) signal()函數(shù)是允許調(diào)用進程控制軟中斷信號的處理。 調(diào)用格式:調(diào)用格式: #include int sig; void func(); signal(sig,func); sig的值是下列之一:SIGHUP 掛起 1 SIGINT 鍵盤按delete鍵或break鍵 2 SIGQUIT 鍵盤按quit鍵 3 SIGILL 非法指令 4 SIGTRAP 跟蹤中斷 5 SIGIOT IOT指令 6 SIGBUS 總線錯 7 SIGFPE 浮點運算溢出 8 SIGK

24、LL 要求終止進程 9 SIGUSR1 用戶定義信號#1 10 SIGSEGV 段違法 11 SIGUSR2 用戶定義信號#2 12 SIGPIPE 向無讀者管道上寫 13 SIGALRM 定時器告警,時間到 14 SIGTERM kill發(fā)出的軟件結(jié)束信號 15 SIGCHLD 子進程死 17 SIGPWR 電源故障 30function的解釋如下Function:在該進程中的一個函數(shù)地址,在核心返回用戶態(tài)時,它以軟件中斷信號的序號作為參數(shù)調(diào)用該函數(shù),對除了信號SIGILL、SIGTRAP和SIGPWR以外的信號,核心自動地重新設(shè)置軟中斷信號處理程序的值為SIG_DFL,一個進程不能捕獲SI

25、GKILL信號。實現(xiàn)軟中斷通信的程序 使用系統(tǒng)調(diào)用fork()創(chuàng)建兩個子進程,再用系統(tǒng)調(diào)用signal()讓父進程捕捉鍵盤上來的中斷信號(即按Del鍵),當(dāng)父進程接受到這兩個軟中斷的其中某一個后,父進程用系統(tǒng)調(diào)用kill()向兩個子進程分別發(fā)送整數(shù)值為16和17軟中斷信號,子進程獲得對應(yīng)軟中斷信號后,分別輸出下列信息后終止: Child process 1 is killed by parent ! Child process 2 is killed by parent ! 父進程調(diào)用wait()函數(shù)等待兩個子進程終止后,輸出以下信息后終止: Parent process is killed! 軟中斷流程圖 開開始始初初始始化化軟軟中中斷斷信信號號集集創(chuàng)創(chuàng)建建子子進進程程1 1子子進進程程1 1創(chuàng)創(chuàng)建建成成功功?否否是是是是否否子子進進程程1 1等等待待軟軟中中斷斷信信號號1 16 6發(fā)發(fā)生生否否等等待待軟軟中中斷斷發(fā)發(fā)生生是是是是過過了了5 5秒秒?否否產(chǎn)產(chǎn)生生軟軟中中斷斷S SI IG GA AL LR RM M是是調(diào)調(diào)用用k ki il ll l( ( ) )向向兩兩子子進進程程發(fā)發(fā)中中斷斷信信號號等等待待子子進進程程1 1終終止止結(jié)結(jié)束束子子進進程程2 2等等待待軟軟中中斷斷信信號號1 17

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論