操作系統(tǒng)-Linux環(huán)境下C語(yǔ)言編程課件_第1頁(yè)
操作系統(tǒng)-Linux環(huán)境下C語(yǔ)言編程課件_第2頁(yè)
操作系統(tǒng)-Linux環(huán)境下C語(yǔ)言編程課件_第3頁(yè)
操作系統(tǒng)-Linux環(huán)境下C語(yǔ)言編程課件_第4頁(yè)
操作系統(tǒng)-Linux環(huán)境下C語(yǔ)言編程課件_第5頁(yè)
已閱讀5頁(yè),還剩157頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

Linux環(huán)境下C語(yǔ)言編程2007年10月Linux環(huán)境下C語(yǔ)言編程2007年10月1GCC簡(jiǎn)介GCC簡(jiǎn)介2C語(yǔ)言和LinuxLINUX中包含了很多軟件開發(fā)工具。它們中的很多是用于C和C++應(yīng)用程序開發(fā)的。C是一種能在UNIX的早期就被廣泛使用的通用編程語(yǔ)言。它最早是由Bell實(shí)驗(yàn)室的DennisRitchie為了UNIX的輔助開發(fā)而寫的,從此C就成為世界上使用最廣泛的計(jì)算機(jī)語(yǔ)言。C能在編程領(lǐng)域里得到如此廣泛支持的原因有:(1)它是一種非常通用的語(yǔ)言,并且它的語(yǔ)法和函數(shù)庫(kù)在不同的平臺(tái)上都是統(tǒng)一的,對(duì)開發(fā)者非常有吸引力;(2)用C寫的程序執(zhí)行速度很快;(3)C是所有版本UNIX上的系統(tǒng)語(yǔ)言;C語(yǔ)言和LinuxLINUX中包含了很多軟件開發(fā)工具。它們中3GNUC編譯器-gccLINUX上可用的C編譯器是GNUC編譯器,它建立在自由軟件基金會(huì)編程許可證的基礎(chǔ)上,因此可以自由發(fā)布。LINUX上的GNUC編譯器(gcc)是一個(gè)全功能的ANCIC兼容編譯器,而一般UNIX(如SCOUNIX)用的編譯器是CC。GNUC編譯器-gccLINUX上可用的C編譯器是GNU4文件后綴文件后綴5Gcc編譯文件gcc指令的一般格式為:gcc[選項(xiàng)]要編譯的文件[選項(xiàng)][目標(biāo)文件]其中,目標(biāo)文件可缺省,gcc默認(rèn)生成可執(zhí)行的文件為:編譯文件.out如:gcc–ohellohello.cGcc編譯文件gcc指令的一般格式為:6GCC編譯流程預(yù)處理(Preprocessing)編譯(Compiling)匯編(Assembling)連接(Linking)GCC編譯流程預(yù)處理(Preprocessing)7hello.c#include<stdio.h>intmain(){printf("Hello!Thisisourworld!\n");return0;}hello.c#include<stdio.h>8預(yù)處理階段

在該階段,編譯器將上述代碼中的stdio.h編譯進(jìn)來,并且用戶可以使用Gcc的選項(xiàng)“-E”進(jìn)行查看,該選項(xiàng)的作用是讓Gcc在預(yù)處理結(jié)束后停止編譯過程。編譯命令:

gcc–Ehello.c–ohello.igcc進(jìn)行了預(yù)處理,它把“stdio.h”的內(nèi)容插入到hello.i文件中。預(yù)處理階段

在該階段,編譯器將上述代碼中的stdio.h編譯9編譯階段在這個(gè)階段中,Gcc首先要檢查代碼的規(guī)范性、是否有語(yǔ)法錯(cuò)誤等,以確定代碼的實(shí)際要做的工作,在檢查無誤后,Gcc把代碼翻譯成匯編語(yǔ)言。用戶可以使用“-S”選項(xiàng)來進(jìn)行查看,該選項(xiàng)只進(jìn)行編譯而不進(jìn)行匯編,生成匯編代碼。編譯命令: gcc–Shello.i–ohello.s編譯階段在這個(gè)階段中,Gcc首先要檢查代碼的規(guī)范性、是否有10匯編階段匯編階段是把編譯階段生成的“.s”文件轉(zhuǎn)成目標(biāo)文件,在此可使用選項(xiàng)“-c”就可看到匯編代碼已轉(zhuǎn)化為“.o”的二進(jìn)制目標(biāo)代碼了。編譯命令:gcc–chello.s–ohello.o匯編階段匯編階段是把編譯階段生成的“.s”文件轉(zhuǎn)成目標(biāo)文件,11鏈接階段系統(tǒng)把”stdio.h”中的實(shí)現(xiàn)都在libc.so.6庫(kù)文件中,在沒有特別指定時(shí),gcc會(huì)到系統(tǒng)默認(rèn)的搜索路徑“/usr/lib”下進(jìn)行查找,也就是鏈接到libc.so.6庫(kù)函數(shù)中去,這樣就能實(shí)現(xiàn)函數(shù)“printf”了。編譯命令: gcchello.o–ohello鏈接階段系統(tǒng)把”stdio.h”中的實(shí)現(xiàn)都在libc.so.12運(yùn)行程序[root@localhost]#./hello Hello!Thisisourworld!運(yùn)行程序[root@localhost]#./hello13Gcc常用編譯選項(xiàng)Gcc常用編譯選項(xiàng)14Gdb調(diào)試器Gdb調(diào)試器是一款GNU開發(fā)組織并發(fā)布的UNIX/Linux下的程序調(diào)試工具。雖然,它沒有圖形化的友好界面,但是它強(qiáng)大的功能也足以與微軟的VC工具等媲美。能監(jiān)視程序中變量的值能設(shè)置斷點(diǎn)以使程序在指定的代碼行上停止執(zhí)行能一行行執(zhí)行代碼Gdb調(diào)試器Gdb調(diào)試器是一款GNU開發(fā)組織并發(fā)布的U15基本gdb命令命令 描述file 裝入想要調(diào)試的可執(zhí)行文件.kill 終止正在調(diào)試的程序.list 列出產(chǎn)生執(zhí)行文件的源代碼的一部分.next 執(zhí)行一行源代碼但不進(jìn)入函數(shù)內(nèi)部.step 執(zhí)行一行源代碼而且進(jìn)入函數(shù)內(nèi)部.run 執(zhí)行當(dāng)前被調(diào)試的程序quit 終止gdbwatch 使你能監(jiān)視一個(gè)變量的值而不管它何時(shí)被改變.print 顯示表達(dá)式的值break 在代碼里設(shè)置斷點(diǎn),這將使程序執(zhí)行到這里時(shí)被掛起.make 能不退出gdb就可以重新產(chǎn)生可執(zhí)行文件.shell 能不離開gdb就執(zhí)行UNIXshell命令.基本gdb命令命令 描述16一個(gè)調(diào)試的例子-gdbtest.c#include<stdio.h>intsum(intm);intmain(){inti,n=0;sum(50);for(i=1;i<=50;i++){n+=i;}printf("Thesumof1-50is%d\n",n);}intsum(intm){inti,n=0;for(i=1;i<=m;i++)n+=i;printf("Thesumof1-mis%d\n",n);}一個(gè)調(diào)試的例子-gdbtest.c#include<std17編譯程序使用Gcc對(duì)test.c進(jìn)行編譯,注意一定要加上選項(xiàng)“-g”,這樣編譯出的可執(zhí)行代碼中才包含調(diào)試信息,否則之后Gdb無法載入該可執(zhí)行文件。gcc-ggdbtest.c-ogdbtest編譯程序使用Gcc對(duì)test.c進(jìn)行編譯,注意一定要加上選項(xiàng)18用Gdb調(diào)試1開始調(diào)試:gdbgdbtest……(gdb)2查看文件命令:l列出帶有行號(hào)的代碼用Gdb調(diào)試1開始調(diào)試:19用Gdb調(diào)試(續(xù))3設(shè)置斷點(diǎn)設(shè)置斷點(diǎn)是調(diào)試程序中是一個(gè)非常重要的手段,它可以使程序到一定位置暫停它的運(yùn)行。因此,程序員在該位置處可以方便地查看變量的值、堆棧情況等,從而找出代碼的癥結(jié)所在。在Gdb中設(shè)置斷點(diǎn)非常簡(jiǎn)單,只需在“b”后加入對(duì)應(yīng)的行號(hào)即可。如:(Gdb)b6Breakpoint1at0x804846d:filegdbtest.c,line6.用Gdb調(diào)試(續(xù))3設(shè)置斷點(diǎn)20用Gdb調(diào)試(續(xù))查看斷點(diǎn)情況:鍵入“infob”來查看設(shè)置斷點(diǎn)情況:(Gdb)infobNumTypeDispEnbAddressWhat1breakpointkeepy0x0804846dinmainattest.c:64運(yùn)行代碼:Gdb默認(rèn)從首行開始運(yùn)行代碼,可鍵入“r”(run)即可(若想從程序中指定行開始運(yùn)行,可在r后面加上行號(hào))。(Gdb)rStartingprogram:/root/workplace/Gdb/testReadingsymbolsfromsharedobjectreadfromtargetmemory...done.LoadedsystemsuppliedDSOat0x5fb000Breakpoint1,main()attest.c:66sum(50);用Gdb調(diào)試(續(xù))查看斷點(diǎn)情況:鍵入“infob”來查看21用Gdb調(diào)試(續(xù))5查看變量值在Gdb中只需鍵入“p”+變量值即可,如下所示:(Gdb)pn$1=0(Gdb)pi$2=134518440用Gdb調(diào)試(續(xù))5查看變量值22用Gdb調(diào)試(續(xù))6單步運(yùn)行單步運(yùn)行可以使用命令“n”(next)或“s”(step),它們之間的區(qū)別在于:若有函數(shù)調(diào)用的時(shí)候,“s”會(huì)進(jìn)入該函數(shù)而“n”不會(huì)進(jìn)入該函數(shù)。(Gdb)nThesumof1-mis12757for(i=1;i<=50;i++)(Gdb)ssum(m=50)attest.c:1616inti,n=0;用Gdb調(diào)試(續(xù))6單步運(yùn)行23用Gdb調(diào)試(續(xù))7恢復(fù)程序運(yùn)行在查看完所需變量及堆棧情況后,就可以使用命令“c”(continue)恢復(fù)程序的正常運(yùn)行了。這時(shí),它會(huì)把剩余還未執(zhí)行的程序執(zhí)行完,并顯示剩余程序中的執(zhí)行結(jié)果。(Gdb)cContinuing.Thesumof1-50is:1275Programexitedwithcode031.用Gdb調(diào)試(續(xù))7恢復(fù)程序運(yùn)行24Linux多線程技術(shù)Linux多線程技術(shù)25POSIX線程庫(kù)Pthreads使用fork()創(chuàng)建進(jìn)程代價(jià)昂貴進(jìn)程間通信方式較復(fù)雜操作系統(tǒng)在實(shí)現(xiàn)進(jìn)程間的切換比線程切換更費(fèi)時(shí)

使用pthreads庫(kù)創(chuàng)建線程創(chuàng)建進(jìn)程比創(chuàng)建線程更快線程間的通信方式更容操作系統(tǒng)對(duì)線程的切換比對(duì)進(jìn)程的切換更容易和快速

POSIX線程庫(kù)Pthreads使用fork()創(chuàng)建進(jìn)26線程的創(chuàng)建#include<pthread.h>intpthread_create(pthread_t*thread,pthread_attr_t*attr,void*(*start_routine)(void*),void*arg );第一個(gè)參數(shù)為指向線程標(biāo)識(shí)符的指針。第二個(gè)參數(shù)用來設(shè)置線程屬性。第三個(gè)參數(shù)是線程運(yùn)行函數(shù)的起始地址。最后一個(gè)參數(shù)是運(yùn)行函數(shù)的參數(shù)。當(dāng)創(chuàng)建線程成功時(shí),函數(shù)返回0,若不為0則說明創(chuàng)建線程失敗,常見的錯(cuò)誤返回代碼為EAGAIN和EINVAL。前者表示系統(tǒng)限制創(chuàng)建新的線程,例如線程數(shù)目過多了;后者表示第二個(gè)參數(shù)代表的線程屬性值非法。線程的創(chuàng)建#include<pthread.h>27一個(gè)簡(jiǎn)單例子#include<stdio.h>

#include<pthread.h>

#include<string.h>

#include<sys/types.h>

#include<unistd.h>

pthread_tntid;

void*thr_fn(void*arg){

printids("newthread:");

return((void*)0);

}

intmain(){

interr;

err=pthread_create(&ntid,NULL,thr_fn,NULL);

if(err!=0){

printf("can'tcreatethread:%s\n",strerror(err));

return1;

}

sleep(1);

return0;

}一個(gè)簡(jiǎn)單例子#include<stdio.h>

#inclu28編譯多線程程序gcc-omypthread-lpthreadmypthread.c

編譯多線程程序gcc-omypthread-lpthr29線程的退出調(diào)用pthread_exit()結(jié)束線程執(zhí)行voidpthread_exit(void*retval);讓線程處理程序返回使用pthread_cancel()函數(shù)終止其他線程的執(zhí)行intpthread_cancel(pthread_tthread);向線程t發(fā)送取消請(qǐng)求,默認(rèn)情況下線程thread自己調(diào)用pthread_exit(PTHREAD_CANCELED),線程的退出調(diào)用pthread_exit()結(jié)束線程執(zhí)行30等待線程結(jié)束使用pthread_join()函數(shù)等待被創(chuàng)建的線程結(jié)束pthread_join()函數(shù)會(huì)掛起創(chuàng)建線程的線程的執(zhí)行直到等待到想要等待的子線程函數(shù)原型:intpthread_join(pthread_tth,void**thread_return);等待線程結(jié)束使用pthread_join()函數(shù)等待被31線程的分離主線程可以不斷地創(chuàng)建子線程子線程本身自己有自我回收內(nèi)存資源的能力函數(shù)原型:intpthread_detach(pthread_tth);pthread_detach()和pthread_join()一般情況下不能同時(shí)使用線程的分離主線程可以不斷地創(chuàng)建子線程32獲得當(dāng)前線程的標(biāo)志pthread_tpthread_self(void);本函數(shù)返回本線程的標(biāo)識(shí)符。在LinuxThreads中,每個(gè)線程都用一個(gè)pthread_descr結(jié)構(gòu)來描述,其中包含了線程狀態(tài)、線程ID等所有需要的數(shù)據(jù)結(jié)構(gòu),此函數(shù)的實(shí)現(xiàn)就是在線程棧幀中找到本線程的pthread_descr結(jié)構(gòu),然后返回其中的p_tid項(xiàng)。

獲得當(dāng)前線程的標(biāo)志pthread_tpthread_sel33一個(gè)例子#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<pthread.h>#defineTHREAD_NUMBER2intretval_hello1=2,retval_hello2=3;void*hello1(void*arg){ char*hello_str=(char*)arg;sleep(1);printf("%s\n",hello_str);pthread_exit(&retval_hello1);}一個(gè)例子#include<stdio.h>34void*hello2(void*arg){char*hello_str=(char*)arg;sleep(2);printf("%s\n",hello_str);pthread_exit(&retval_hello2);}intmain(intargc,char*argv[]){inti;intret_val;int*retval_hello[2];

pthread_tpt[THREAD_NUMBER];constchar*arg[THREAD_NUMBER];arg[0]="helloworldfromthread1";arg[1]="helloworldfromthread2";void*hello2(void*arg)35printf("Begintocreatethreads...\n");ret_val=pthread_create(&pt[0],NULL,hello1,(void*)arg[0]);if(ret_val!=0){printf("pthread_createerror!\n");exit(1);}ret_val=pthread_create(&pt[1],NULL,hello2,(void*)arg[1]);if(ret_val!=0){printf("pthread_createerror!\n");exit(1);}printf("Begintocreatethread36printf("Begintowaitforthreads...\n");for(i=0;i<THREAD_NUMBER;i++){ret_val=pthread_join(pt[i],(void**)&retval_hello[i]);if(ret_val!=0){printf("pthread_joinerror!\n"); exit(1);}else{printf("returnvalueis%d\n",*retval_hello[i]);}}printf("Now,themainthreadreturns.\n");return0;}printf("Begintowaitforthre37線程屬性的初始化和撤銷線程初始化: intpthread_attr_init(pthread_attr_t*attr)初始化線程屬性對(duì)象attr,并用默認(rèn)值填充線程撤銷: intpthread_attr_destroy(pthread_attr_t*attr)銷毀線程屬性對(duì)象attr。*修改線程屬性對(duì)象attr只有在線程創(chuàng)建前有效,在線程創(chuàng)建后修改對(duì)當(dāng)前線程不起作用。*返回0成功,否則失敗。線程屬性的初始化和撤銷線程初始化:38pthread_attr_t定義pthread_attr_t定義:

typedefstruct__pthread_attr_s

{

int__detachstate;

int__schedpolicy;

struct__sched_param__schedparam;

int__inheritsched;

int__scope;

size_t__guardsize;

int__stackaddr_set;

void*__stackaddr;

size_t__stacksize;

}pthread_attr_t;pthread_attr_t定義pthread_attr_t39線程的屬性屬性名意義

detachstate選擇被創(chuàng)建的線程是處于可加入的狀態(tài)還是分離狀態(tài)

schedpolicy為被創(chuàng)建的線程選擇調(diào)度策略。

schedparam為被創(chuàng)建的線程選擇調(diào)度參數(shù)。

inheritsched選擇對(duì)新創(chuàng)建的線程的調(diào)度策略和調(diào)度參數(shù)是否被schedpolicy和schedparam屬性決定或者是通過父線程繼承而得到的

scope為選擇被創(chuàng)建的線程調(diào)度競(jìng)爭(zhēng)范圍。線程的屬性屬性名意義detachstate選擇被創(chuàng)建的線程40線程的屬性(續(xù))detachstatePTHREAD_CREATE_JOINABLEPTHREAD_CREATE_DETACHED

默認(rèn):PTHREAD_CREATE_JOINABLE控制創(chuàng)建的線程是joinable態(tài)還是detached態(tài)schedpolicySCHED_OTHER(regular,non-realtimescheduling)SCHED_RR

(realtime,

round-robin)SCHED_FIFO(realtime,first-infirst-out)

默認(rèn):SCHED_OTHER優(yōu)先級(jí)類別Schedparam默認(rèn):0線程優(yōu)先級(jí)參數(shù)如果schedpolicy的值為SCHED_OTHER,schedpolicy此屬性無關(guān)緊要線程創(chuàng)建后可修改此屬性inheritschedPTHREAD_EXPLICIT_SCHEDPTHREAD_INHERIT_SCHED

默認(rèn):PTHREAD_EXPLICIT_SCHED說明此線程優(yōu)先級(jí)是否繼承于父線程還是通過上面兩個(gè)屬性確定scopePTHREAD_SCOPE_SYSTEMPTHREAD_SCOPE_PROCESS

默認(rèn):PTHREAD_SCOPE_SYSTEM設(shè)置線程綁定狀態(tài)部分Linux不支持PTHREAD_SCOPE_PROCESS,需要查看man線程的屬性(續(xù))detachstatePTHREAD_CRE41相關(guān)函數(shù)-分離狀態(tài)設(shè)置分離狀態(tài):pthread_attr_setdetachstateintpthread_attr_setdetachstate(pthread_attr_t*attr,intdetachstate);返回值:函數(shù)成功返回0;任何其他返回值都表示錯(cuò)誤設(shè)置分離狀態(tài)。參數(shù)detachstate的值為:PTHREAD_CREATE_DETACHED、PTHREAD_CREATE_JOINABLE。獲取分離狀態(tài):pthread_attr_getdetachstateintpthread_attr_getdetachstate(pthread_attr_t*attr,int*detachstate);返回值:函數(shù)成功返回0;任何其他返回值都表示錯(cuò)誤取線程分離狀態(tài):分離的或是非分離的。相關(guān)函數(shù)-分離狀態(tài)設(shè)置分離狀態(tài):pthread_attr_s42相關(guān)函數(shù)-調(diào)度策略設(shè)置調(diào)度策略:pthread_attr_setschedpolicyintpthread_attr_setschedpolicy(pthread_attr_t*tattr,intpolicy);返回值:函數(shù)成功返回0;任何其他返回值都表示錯(cuò)誤。POSIX標(biāo)準(zhǔn)定義的調(diào)度策略有:SCHED_FIFO(先入先出)、SCHED_RR(循環(huán))、SCHED_OTHER(由不同版本的POSIX線程庫(kù)定義的缺省調(diào)度策略)。獲取調(diào)度策略:pthread_attr_getschedpolicyintpthread_attr_getschedpolicy(pthread_attr_t*tattr,int*policy);返回值:函數(shù)成功返回0;任何其他返回值都表示錯(cuò)誤。相關(guān)函數(shù)-調(diào)度策略設(shè)置調(diào)度策略:pthread_attr_s43相關(guān)函數(shù)-調(diào)度參數(shù)設(shè)置調(diào)度參數(shù):pthread_attr_setschedparamintpthread_attr_setschedparam(pthread_attr_t*tattr,conststructsched_param*param);返回值:函數(shù)成功返回0;任何其他返回值都表示錯(cuò)誤。屬性對(duì)象的調(diào)度參數(shù)定義在param結(jié)構(gòu)中;在這個(gè)結(jié)構(gòu)中只定義了優(yōu)先級(jí)priority成員。新創(chuàng)建線程的優(yōu)先級(jí)由屬性對(duì)象中param結(jié)構(gòu)的priority參數(shù)指定。有兩種方式可以修改線程的優(yōu)先級(jí)。可以在創(chuàng)建子線程前設(shè)置屬性對(duì)象的優(yōu)先級(jí)參數(shù);也可以先修改父線程的優(yōu)先級(jí),然后創(chuàng)建子線程。sched_param結(jié)構(gòu)中有可能存放著其他一些調(diào)度信息。所以在修改線程屬性對(duì)象的調(diào)度參數(shù)前先取現(xiàn)有的調(diào)度參數(shù)是良好的習(xí)慣。一段合理的代碼應(yīng)該是這樣的:先取線程屬性對(duì)象中現(xiàn)有的調(diào)度參數(shù),對(duì)取出的調(diào)度參數(shù)進(jìn)行操作,再用修改過的調(diào)度參數(shù)重置線程屬性對(duì)象。

獲取調(diào)度參數(shù):pthread_attr_getschedparamintpthread_attr_getschedparam(pthread_attr_t*tattr,conststructsched_param*param);返回值:函數(shù)成功返回0;任何其他返回值都表示錯(cuò)誤。相關(guān)函數(shù)-調(diào)度參數(shù)設(shè)置調(diào)度參數(shù):pthread_attr_s44相關(guān)函數(shù)-域設(shè)置域:pthread_attr_setscopeintpthread_attr_setscope(pthread_attr_t*tattr,intscope);返回值:函數(shù)成功返回0;任何其他返回值都表示錯(cuò)誤。指定將來創(chuàng)建的線程是綁定(PTHREAD_SCOPE_SYSTEM)的還是非綁定的(PTHREAD_SCOPE_PROCESS)。在一個(gè)進(jìn)程中可以同時(shí)有這兩種不同類型的線程。

獲取域:pthread_attr_getscopeintpthread_attr_getscope(pthread_attr_t*tattr,int*scope);返回值:函數(shù)成功返回0;任何其他返回值都表示錯(cuò)誤。相關(guān)函數(shù)-域設(shè)置域:pthread_attr_setscop45例子:threadattr#include<stdio.h>#include<stdlib.h>#include<pthread.h>void*sum_val(void*arg){ intsum=0;inti;intcount=*(int*)arg;for(i=0;i<count;i++) sum=sum+i;printf("sumis%d\n",sum);pthread_exit(0);}例子:threadattr#include<stdio.h46例子:threadattr(續(xù))intmain(intargc,char*argv[]){

pthread_tpt;intcount=10;intret_val;pthread_attr_tattr;structsched_paramsp;sp._sched_priority=2;

ret_val=pthread_attr_init(&attr);if(ret_val!=0){printf("pthread_attr_initerror!\n");exit(1);}例子:threadattr(續(xù))intmain(inta47例子:threadattr(續(xù))ret_val=pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);if(ret_val!=0){printf("pthread_attr_setdetachstateerror!\n");exit(1);}ret_val=pthread_attr_setschedpolicy(&attr,SCHED_RR);if(ret_val!=0){printf("pthread_attr_setschedpolicyerror!\n");exit(1);}ret_val=pthread_attr_setschedparam(&attr,&sp);if(ret_val!=0){printf("pthread_attr_setschedparamerror!\n");exit(1);}例子:threadattr(續(xù))ret_val=pthr48例子:threadattr(續(xù))ret_val=pthread_attr_setinheritsched(&attr,PTHREAD_EXPLICIT_SCHED);if(ret_val!=0){printf("pthread_attr_setinheritschederror!\n");exit(1);}ret_val=pthread_attr_setscope(&attr,PTHREAD_SCOPE_SYSTEM);if(ret_val!=0){printf("pthread_attr_setscopeerror!\n");exit(1);}ret_val=pthread_create(&pt,NULL,sum_val,(void*)&count);if(ret_val!=0){printf("pthread_createerror!\n");exit(1);}pthread_attr_destroy(&attr);sleep(5);return0;}例子:threadattr(續(xù))ret_val=pthr49Linux下線程的同步和互斥Linux下線程的同步和互斥50mutexMutex:互斥設(shè)備(MUTualExclusiondevice)mutex有如下特性:原子性:對(duì)mutex的加鎖和解鎖操作是原子的單一性:擁有mutex的線程除非釋放mutex,否則其他線程不能擁有此mutex非忙等待:等待mutex的線程處于等待狀態(tài),直到要等待的mutex處于未加鎖狀態(tài),這時(shí)操作系統(tǒng)負(fù)責(zé)喚醒等待此mutex的線程mutexMutex:互斥設(shè)備(MUTualExclusi51Mutex類型在POSIX線程庫(kù)中,存在三中類型的mutex:快速(fast)mutex遞歸(recursive)mutex:獲得鎖的線程可以多次加鎖錯(cuò)誤檢測(cè)(errorchecking)mutex:鎖定時(shí)返回錯(cuò)誤Mutex類型在POSIX線程庫(kù)中,存在三中類型的mute52與mutex相關(guān)函數(shù)intpthread_mutex_init(pthread_mutex_t*mutex,constpthread_mutexattr_t*mutexattr);intpthread_mutex_lock(pthread_mutex_t*mutex);intpthread_mutex_trylock(pthread_mutex_t*mutex);intpthread_mutex_unlock(pthread_mutex_t*mutex);intpthread_mutex_destroy(pthread_mutex_t*mutex);與mutex相關(guān)函數(shù)intpthread_mutex_i53初始化互斥鎖intpthread_mutex_init(pthread_mutex_t*mp,constpthread_mutexattr_t*mattr);成功完成之后會(huì)返回零。其他任何返回值都表示出現(xiàn)了錯(cuò)誤。初始化互斥鎖intpthread_mutex_init(54例子#include<pthread.h>pthread_mutex_tmp=PTHREAD_MUTEX_INITIALIZER;pthread_mutexattr_tmattr;intret;/*initializeamutextoitsdefaultvalue*/ret=pthread_mutex_init(&mp,NULL);例子#include<pthread.h>55鎖定互斥鎖intpthread_mutex_lock(pthread_mutex_t*mutex);在成功完成之后會(huì)返回零。其他任何返回值都表示出現(xiàn)了錯(cuò)誤。當(dāng)返回時(shí),該互斥鎖已被鎖定。調(diào)用線程是該互斥鎖的屬主。互斥鎖類型為快速鎖:如果該互斥鎖已被另一個(gè)線程鎖定和擁有,則調(diào)用線程將阻塞,直到該互斥鎖變?yōu)榭捎脼橹??;コ怄i類型為錯(cuò)誤鎖:則會(huì)提供錯(cuò)誤檢查。如果某個(gè)線程嘗試重新鎖定的互斥鎖已經(jīng)由該線程鎖定,則將返回錯(cuò)誤。如果某個(gè)線程嘗試解除鎖定的互斥鎖不是由該線程鎖定或者未鎖定,則將返回錯(cuò)誤?;コ怄i類型為遞歸鎖:則該互斥鎖會(huì)保留鎖定計(jì)數(shù)這一概念。線程首次成功獲取互斥鎖時(shí),鎖定計(jì)數(shù)會(huì)設(shè)置為1。線程每重新鎖定該互斥鎖一次,鎖定計(jì)數(shù)就增加1。線程每解除鎖定該互斥鎖一次,鎖定計(jì)數(shù)就減小1。鎖定計(jì)數(shù)達(dá)到0時(shí),該互斥鎖即可供其他線程獲取。如果某個(gè)線程嘗試解除鎖定的互斥鎖不是由該線程鎖定或者未鎖定,則將返回錯(cuò)誤。鎖定互斥鎖intpthread_mutex_lock(pt56解除鎖定互斥鎖intpthread_mutex_unlock(pthread_mutex_t*mutex);釋放引用的互斥鎖對(duì)象?;コ怄i的釋放方式取決于互斥鎖的類型屬性。在成功完成之后會(huì)返回零。其他任何返回值都表示出現(xiàn)了錯(cuò)誤。解除鎖定互斥鎖intpthread_mutex_unlo57使用非阻塞互斥鎖鎖定intpthread_mutex_trylock(pthread_mutex_t*mutex);在成功完成之后會(huì)返回零。其他任何返回值都表示出現(xiàn)了錯(cuò)誤。

是pthread_mutex_tlock的非阻塞版本。如果所引用的互斥對(duì)象當(dāng)前被任何線程(包括當(dāng)前線程)鎖定,則將立即返回該調(diào)用。否則,該互斥鎖將處于鎖定狀態(tài),調(diào)用線程是其屬主。使用非阻塞互斥鎖鎖定intpthread_mutex_tr58銷毀互斥鎖intpthread_mutex_destroy(pthread_mutex_t*mp);在成功完成之后會(huì)返回零。其他任何返回值都表示出現(xiàn)了錯(cuò)誤。銷毀互斥鎖intpthread_mutex_destroy59使用MUTEX的簡(jiǎn)單代碼pthread_mutex_tmylock;mylock=PTHREAD_MUTEX_INITIALIZER;pthread_mutex_lock(&mylock);Dosomething….pthread_mutex_unlock(&mylock);使用MUTEX的簡(jiǎn)單代碼pthread_mutex_tmy60Mutex例子#include<stdio.h>#include<stdlib.h>#include<pthread.h>#include<errno.h>#defineTHREAD_NUMBER10staticpthread_mutex_tmutex=PTHREAD_MUTEX_INITIALIZER;intsum=0;void*inc(void*arg){inti=(*(int*)arg);pthread_mutex_lock(&mutex);sum=sum+i;pthread_mutex_unlock(&mutex);returnNULL;}Mutex例子#include<stdio.h>61Mutex例子(續(xù))intmain(intargc,char*argv[]){pthread_tpt[THREAD_NUMBER];inti;intarg[THREAD_NUMBER]; for(i=0;i<THREAD_NUMBER;i++){arg[i]=i; if(pthread_create(&pt[i],NULL,inc,(void*)&arg[i])!=0){printf("pthread_createerror\n");exit(1);}}Mutex例子(續(xù))intmain(intargc,c62Mutex例子(續(xù))for(i=0;i<THREAD_NUMBER;i++)if(pthread_join(pt[i],NULL)!=0){printf("pthread_joinerror\n");exit(1);}printf("sumis%d\n",sum);pthread_mutex_destroy(&mutex);return0;}Mutex例子(續(xù))for(i=0;i<THREAD_NU63條件變量可以使得一個(gè)線程在執(zhí)行過程中,因滿足某個(gè)條件而發(fā)出信號(hào)通知另一個(gè)線程。而另一個(gè)線程可以處于掛起狀態(tài),等待某個(gè)條件的滿足后,才繼續(xù)執(zhí)行。條件變量必須和mutex一起使用來避免競(jìng)爭(zhēng)。條件變量可以使得一個(gè)線程在執(zhí)行過程中,因滿足某個(gè)條件而發(fā)出64條件變量相關(guān)的操作函數(shù)pthread_cond_tcond=PTHREAD_COND_INITIALIZER;intpthread_cond_init(pthread_cond_t*cond,pthread_condattr_t*cond_attr);intpthread_cond_signal(pthread_cond_t*cond);intpthread_cond_broadcast(pthread_cond_t*cond);intpthread_cond_wait(pthread_cond_t*cond,pthread_mutex_t*mutex);intpthread_cond_timedwait(pthread_cond_t*cond,pthread_mutex_t*mutex,conststructtimespec*abstime);intpthread_cond_destroy(pthread_cond_t*cond);在成功完成之后會(huì)返回零。其他任何返回值都表示出現(xiàn)了錯(cuò)誤。

條件變量相關(guān)的操作函數(shù)pthread_cond_tcon65初始化條件變量intpthread_cond_init(pthread_cond_t*cv,constpthread_condattr_t*cattr);使用PTHREAD_COND_INITIALIZER宏可以將以靜態(tài)方式定義的條件變量初始化為其缺省屬性。PTHREAD_COND_INITIALIZER宏與動(dòng)態(tài)分配具有null屬性的pthread_cond_init等效,但是不進(jìn)行錯(cuò)誤檢查。多個(gè)線程決不能同時(shí)初始化或重新初始化同一個(gè)條件變量。如果要重新初始化或銷毀某個(gè)條件變量,則應(yīng)用程序必須確保該條件變量未被使用。初始化條件變量intpthread_cond_init(p66基于條件變量阻塞intpthread_cond_wait(pthread_cond_t*cond,pthread_mutex_t*mutex);阻塞的線程可以通過pthread_cond_signal或pthread_cond_broadcast喚醒,也可以在信號(hào)傳送將其中斷時(shí)喚醒。該條件獲得信號(hào)之前,該函數(shù)一直被阻塞。該函數(shù)會(huì)在被阻塞之前以原子方式釋放相關(guān)的互斥鎖,并在返回之前以原子方式再次獲取該互斥鎖。通常,對(duì)條件表達(dá)式的評(píng)估是在互斥鎖的保護(hù)下進(jìn)行的。如果條件表達(dá)式為假,線程會(huì)基于條件變量阻塞。然后,當(dāng)該線程更改條件值時(shí),另一個(gè)線程會(huì)針對(duì)條件變量發(fā)出信號(hào)。這種變化會(huì)導(dǎo)致所有等待該條件的線程解除阻塞并嘗試再次獲取互斥鎖。必須重新測(cè)試導(dǎo)致等待的條件,然后才能從pthread_cond_wait處繼續(xù)執(zhí)行。喚醒的線程重新獲取互斥鎖并從pthread_cond_wait返回之前,條件可能會(huì)發(fā)生變化。等待線程可能并未真正喚醒。建議使用的測(cè)試方法是,將條件檢查編寫為調(diào)用pthread_cond_wait的while循環(huán):pthread_mutex_lock();while(condition_is_false)pthread_cond_wait();pthread_mutex_unlock();基于條件變量阻塞intpthread_cond_wait67解除阻塞一個(gè)線程intpthread_cond_signal(pthread_cond_t*cond);應(yīng)在互斥鎖的保護(hù)下修改相關(guān)條件,該互斥鎖用于獲得信號(hào)的條件變量中。否則,可能在條件變量的測(cè)試和pthread_cond_wait阻塞之間修改該變量,這會(huì)導(dǎo)致無限期等待。解除阻塞一個(gè)線程intpthread_cond_sign68在指定的時(shí)間之前阻塞intpthread_cond_timedwait(pthread_cond_t*cond,pthread_mutex_t*mutex,conststructtimespec*abstime);

每次返回時(shí)調(diào)用線程都會(huì)鎖定并且擁有互斥鎖,即使返回錯(cuò)誤時(shí)也是如此。函數(shù)會(huì)一直阻塞,直到該條件獲得信號(hào),或者最后一個(gè)參數(shù)所指定的時(shí)間已過為止。在指定的時(shí)間之前阻塞intpthread_cond_69解除阻塞所有線程intpthread_cond_broadcast(pthread_cond_t*cond);使用pthread_cond_broadcast()可以解除阻塞所有這些線程。解除阻塞所有線程intpthread_cond_broa70銷毀條件變量狀態(tài)intpthread_cond_destroy(pthread_cond_t*cond);用pthread_cond_destroy()可以銷毀與cond所指向的條件變量相關(guān)聯(lián)的任何狀態(tài)。銷毀條件變量狀態(tài)intpthread_cond_dest71例子1#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<pthread.h>#defineTHREAD_NUMBER2staticpthread_cond_tcond=PTHREAD_COND_INITIALIZER;staticpthread_mutex_tmutex=PTHREAD_MUTEX_INITIALIZER;void*thread1(void*arg){pthread_mutex_lock(&mutex);printf("thread1lockedthemutex\n");printf("thread1iswaitingforconditionsignal...\n");pthread_cond_wait(&cond,&mutex);printf("thread1receivedconditionsignal!\n");pthread_mutex_unlock(&mutex);printf("thread1unlockedthemutex\n");pthread_exit(0);}例子1#include<stdio.h>72例子1(續(xù))void*thread2(void*arg){inti=0;structtimevalold,new;gettimeofday(&old);new=old;pthread_mutex_lock(&mutex);printf("thread2lockedthemutex\n");while(new.tv_sec-old.tv_sec<5){sleep(1);gettimeofday(&new);i++;printf("thread2sleep%dseconds\n",i);}printf("thread1callspthread_cond_signal...\n");pthread_cond_signal(&cond);pthread_mutex_unlock(&mutex);printf("thread2unlockedthemutex\n");pthread_exit(0);}例子1(續(xù))void*thread2(void*arg)73例子1(續(xù))intmain(intargc,char*argv[]){inti;intret_val;pthread_tpt[THREAD_NUMBER];ret_val=pthread_create(&pt[0],NULL,thread1,NULL);if(ret_val!=0){printf("pthread_createerror!\n");exit(1);}ret_val=pthread_create(&pt[1],NULL,thread2,NULL);if(ret_val!=0){printf("pthread_createerror!\n");exit(1);}

例子1(續(xù))intmain(intargc,char74例子1(續(xù))for(i=0;i<THREAD_NUMBER;i++){ret_val=pthread_join(pt[i],NULL);if(ret_val!=0){printf("pthread_joinerror!\n"); exit(1);}}pthread_mutex_destroy(&mutex);pthread_cond_destroy(&cond);return0;}例子1(續(xù))for(i=0;i<THREAD_N75例子2……#defineTHREAD_NUMBER2staticpthread_cond_tcond=PTHREAD_COND_INITIALIZER;staticpthread_mutex_tmutex=PTHREAD_MUTEX_INITIALIZER;staticintx=0,y=0;void*thread1(void*arg){structtimevalnow;structtimespectimeout;intretcode;pthread_mutex_lock(&mutex);gettimeofday(&now);timeout.tv_sec=now.tv_sec+5;timeout.tv_nsec=now.tv_usec*1000;retcode=0;

例子2……76例子2(續(xù))while(x>=y&&retcode!=ETIMEDOUT){retcode=pthread_cond_timedwait(&cond,&mutex,&timeout);}if(retcode==ETIMEDOUT){printf("pthread_cond_timedwaittimeout!\n");}else{printf("thread1gotconditionsignal!\n");}pthread_mutex_unlock(&mutex);pthread_exit(0);}例子2(續(xù))while(x>=y&&retcode77例子2(續(xù))void*thread2(void*arg){inti;for(i=0;i<5;i++){x=rand()%5;y=rand()%5;sleep(1);printf("xis%d,yis%d\n",x,y);if(x<y) break;}pthread_mutex_lock(&mutex);if(x<y){pthread_cond_broadcast(&cond);}pthread_mutex_unlock(&mutex); pthread_exit(0);}例子2(續(xù))void*thread2(void*arg)78例子2(續(xù))intmain(intargc,char*argv[]){inti;intret_val;pthread_tpt[THREAD_NUMBER];ret_val=pthread_create(&pt[0],NULL,thread1,NULL);if(ret_val!=0){printf("pthread_createerror!\n");exit(1);}ret_val=pthread_create(&pt[1],NULL,thread2,NULL);if(ret_val!=0){printf("pthread_createerror!\n");exit(1);}

例子2(續(xù))intmain(intargc,char79例子2(續(xù))for(i=0;i<THREAD_NUMBER;i++){ret_val=pthread_join(pt[i],NULL);if(ret_val!=0){printf("pthread_joinerror!\n"); exit(1);}}pthread_mutex_destroy(&mutex);pthread_cond_destroy(&cond);return0;}例子2(續(xù))for(i=0;i<THREAD_N80操作系統(tǒng)-Linux環(huán)境下C語(yǔ)言編程課件81Linux環(huán)境下C語(yǔ)言編程2007年10月Linux環(huán)境下C語(yǔ)言編程2007年10月82GCC簡(jiǎn)介GCC簡(jiǎn)介83C語(yǔ)言和LinuxLINUX中包含了很多軟件開發(fā)工具。它們中的很多是用于C和C++應(yīng)用程序開發(fā)的。C是一種能在UNIX的早期就被廣泛使用的通用編程語(yǔ)言。它最早是由Bell實(shí)驗(yàn)室的DennisRitchie為了UNIX的輔助開發(fā)而寫的,從此C就成為世界上使用最廣泛的計(jì)算機(jī)語(yǔ)言。C能在編程領(lǐng)域里得到如此廣泛支持的原因有:(1)它是一種非常通用的語(yǔ)言,并且它的語(yǔ)法和函數(shù)庫(kù)在不同的平臺(tái)上都是統(tǒng)一的,對(duì)開發(fā)者非常有吸引力;(2)用C寫的程序執(zhí)行速度很快;(3)C是所有版本UNIX上的系統(tǒng)語(yǔ)言;C語(yǔ)言和LinuxLINUX中包含了很多軟件開發(fā)工具。它們中84GNUC編譯器-gccLINUX上可用的C編譯器是GNUC編譯器,它建立在自由軟件基金會(huì)編程許可證的基礎(chǔ)上,因此可以自由發(fā)布。LINUX上的GNUC編譯器(gcc)是一個(gè)全功能的ANCIC兼容編譯器,而一般UNIX(如SCOUNIX)用的編譯器是CC。GNUC編譯器-gccLINUX上可用的C編譯器是GNU85文件后綴文件后綴86Gcc編譯文件gcc指令的一般格式為:gcc[選項(xiàng)]要編譯的文件[選項(xiàng)][目標(biāo)文件]其中,目標(biāo)文件可缺省,gcc默認(rèn)生成可執(zhí)行的文件為:編譯文件.out如:gcc–ohellohello.cGcc編譯文件gcc指令的一般格式為:87GCC編譯流程預(yù)處理(Preprocessing)編譯(Compiling)匯編(Assembling)連接(Linking)GCC編譯流程預(yù)處理(Preprocessing)88hello.c#include<stdio.h>intmain(){printf("Hello!Thisisourworld!\n");return0;}hello.c#include<stdio.h>89預(yù)處理階段

在該階段,編譯器將上述代碼中的stdio.h編譯進(jìn)來,并且用戶可以使用Gcc的選項(xiàng)“-E”進(jìn)行查看,該選項(xiàng)的作用是讓Gcc在預(yù)處理結(jié)束后停止編譯過程。編譯命令:

gcc–Ehello.c–ohello.igcc進(jìn)行了預(yù)處理,它把“stdio.h”的內(nèi)容插入到hello.i文件中。預(yù)處理階段

在該階段,編譯器將上述代碼中的stdio.h編譯90編譯階段在這個(gè)階段中,Gcc首先要檢查代碼的規(guī)范性、是否有語(yǔ)法錯(cuò)誤等,以確定代碼的實(shí)際要做的工作,在檢查無誤后,Gcc把代碼翻譯成匯編語(yǔ)言。用戶可以使用“-S”選項(xiàng)來進(jìn)行查看,該選項(xiàng)只進(jìn)行編譯而不進(jìn)行匯編,生成匯編代碼。編譯命令: gcc–Shello.i–ohello.s編譯階段在這個(gè)階段中,Gcc首先要檢查代碼的規(guī)范性、是否有91匯編階段匯編階段是把編譯階段生成的“.s”文件轉(zhuǎn)成目標(biāo)文件,在此可使用選項(xiàng)“-c”就可看到匯編代碼已轉(zhuǎn)化為“.o”的二進(jìn)制目標(biāo)代碼了。編譯命令:gcc–chello.s–ohello.o匯編階段匯編階段是把編譯階段生成的“.s”文件轉(zhuǎn)成目標(biāo)文件,92鏈接階段系統(tǒng)把”stdio.h”中的實(shí)現(xiàn)都在libc.so.6庫(kù)文件中,在沒有特別指定時(shí),gcc會(huì)到系統(tǒng)默認(rèn)的搜索路徑“/usr/lib”下進(jìn)行查找,也就是鏈接到libc.so.6庫(kù)函數(shù)中去,這樣就能實(shí)現(xiàn)函數(shù)“printf”了。編譯命令: gcchello.o–ohello鏈接階段系統(tǒng)把”stdio.h”中的實(shí)現(xiàn)都在libc.so.93運(yùn)行程序[root@localhost]#./hello Hello!Thisisourworld!運(yùn)行程序[root@localhost]#./hello94Gcc常用編譯選項(xiàng)Gcc常用編譯選項(xiàng)95Gdb調(diào)試器Gdb調(diào)試器是一款GNU開發(fā)組織并發(fā)布的UNIX/Linux下的程序調(diào)試工具。雖然,它沒有圖形化的友好界面,但是它強(qiáng)大的功能也足以與微軟的VC工具等媲美。能監(jiān)視程序中變量的值能設(shè)置斷點(diǎn)以使程序在指定的代碼行上停止執(zhí)行能一行行執(zhí)行代碼Gdb調(diào)試器Gdb調(diào)試器是一款GNU開發(fā)組織并發(fā)布的U96基本gdb命令命令 描述file 裝入想要調(diào)試的可執(zhí)行文件.kill 終止正在調(diào)試的程序.list 列出產(chǎn)生執(zhí)行文件的源代碼的一部分.next 執(zhí)行一行源代碼但不進(jìn)入函數(shù)內(nèi)部.step 執(zhí)行一行源代碼而且進(jìn)入函數(shù)內(nèi)部.run 執(zhí)行當(dāng)前被調(diào)試的程序quit 終止gdbwatch 使你能監(jiān)視一個(gè)變量的值而不管它何時(shí)被改變.print 顯示表達(dá)式的值break 在代碼里設(shè)置斷點(diǎn),這將使程序執(zhí)行到這里時(shí)被掛起.make 能不退出gdb就可以重新產(chǎn)生可執(zhí)行文件.shell 能不離開gdb就執(zhí)行UNIXshell命令.基本gdb命令命令 描述97一個(gè)調(diào)試的例子-gdbtest.c#include<stdio.h>intsum(intm);intmain(){inti,n=0;sum(50);for(i=1;i<=50;i++){n+=i;}printf("Thesumof1-50is%d\n",n);}intsum(intm){inti,n=0;for(i=1;i<=m;i++)n+=i;printf("Thesumof1-mis%d\n",n);}一個(gè)調(diào)試的例子-gdbtest.c#include<std98編譯程序使用Gcc對(duì)test.c進(jìn)行編譯,注意一定要加上選項(xiàng)“-g”,這樣編譯出的可執(zhí)行代碼中才包含調(diào)試信息,否則之后Gdb無法載入該可執(zhí)行文件。gcc-ggdbtest.c-ogdbtest編譯程序使用Gcc對(duì)test.c進(jìn)行編譯,注意一定要加上選項(xiàng)99用Gdb調(diào)試1開始調(diào)試:gdbgdbtest……(gdb)2查看文件命令:l列出帶有行號(hào)的代碼用Gdb調(diào)試1開始調(diào)試:100用Gdb調(diào)試(續(xù))3設(shè)置斷點(diǎn)設(shè)置斷點(diǎn)是調(diào)試程序中是一個(gè)非常重要的手段,它可以使程序到一定位置暫停它的運(yùn)行。因此,程序員在該位置處可以方便地查看變量的值、堆棧情況等,從而找出代碼的癥結(jié)所在。在Gdb中設(shè)置斷點(diǎn)非常簡(jiǎn)單,只需在“b”后加入對(duì)應(yīng)的行號(hào)即可。如:(Gdb)b6Breakpoint1at0x804846d:filegdbtest.c,line6.用Gdb調(diào)試(續(xù))3設(shè)置斷點(diǎn)101用Gdb調(diào)試(續(xù))查看斷點(diǎn)情況:鍵入“infob”來查看設(shè)置斷點(diǎn)情況:(Gdb)infobNumTypeDispEnbAddressWhat1breakpointkeepy0x0804846dinmainattest.c:64運(yùn)行代碼:Gdb默認(rèn)從首行開始運(yùn)行代碼,可鍵入“r”(run)即可(若想從程序中指定行開始運(yùn)行,可在r后面加上行號(hào))。(Gdb)rStartingprogram:/root/workplace/Gdb/testReadingsymbolsfromsharedobjectreadfromtargetmemory...done.LoadedsystemsuppliedDSOat0x5fb000Breakpoint1,main()attest.c:66sum(50);用Gdb調(diào)試(續(xù))查看斷點(diǎn)情況:鍵入“infob”來查看102用Gdb調(diào)試(續(xù))5查看變量值在Gdb中只需鍵入“p”+變量值即可,如下所示:(Gdb)pn$1=0(Gdb)pi$2=134518440用Gdb調(diào)試(續(xù))5查看變量值103用Gdb調(diào)試(續(xù))6單步運(yùn)行單步運(yùn)行可以使用命令“n”(next)或“s”(step),它們之間的區(qū)別在于:若有函數(shù)調(diào)用的時(shí)候,“s”會(huì)進(jìn)入該函數(shù)而“n”不會(huì)進(jìn)入該函數(shù)。(Gdb)nThesumof1-mis12757for(i=1;i<=50;i++)(Gdb)ssum(m=50)attest.c:1616inti,n=0;用Gdb調(diào)試(續(xù))6單步運(yùn)行104用Gdb調(diào)試(續(xù))7恢復(fù)程序運(yùn)行在查看完所需變量及堆棧情況后,就可以使用命令“c”(continue)恢復(fù)程序的正常運(yùn)行了。這時(shí),它會(huì)把剩余還未執(zhí)行的程序執(zhí)行完,并顯示剩余程序中的執(zhí)行結(jié)果。(Gdb)cContinuing.Thesumof1-50is:1275Programexitedwithcode031.用Gdb調(diào)試(續(xù))7恢復(fù)程序運(yùn)行105Linux多線程技術(shù)Linux多線程技術(shù)106POSIX線程庫(kù)Pthreads使用fork()創(chuàng)建進(jìn)程代價(jià)昂貴進(jìn)程間通信方式較復(fù)雜操作系統(tǒng)在實(shí)現(xiàn)進(jìn)程間的切換比線程切換更費(fèi)時(shí)

使用pthreads庫(kù)創(chuàng)建線程創(chuàng)建進(jìn)程比創(chuàng)建線程更快線程間的通信方式更容操作系統(tǒng)對(duì)線程的切換比對(duì)進(jìn)程的切換更容易和快速

POSIX線程庫(kù)Pthreads使用fork()創(chuàng)建進(jìn)107線程的創(chuàng)建#include<pthread.h>intpthread_create(pthread_t*thread,pthread_attr_t*attr,void*(*start_routine)(void*),void*arg );第一個(gè)參數(shù)為指向線程標(biāo)識(shí)符的指針。第二個(gè)參數(shù)用來設(shè)置線程屬性。第三個(gè)參數(shù)是線程運(yùn)行函數(shù)的起始地址。最后一個(gè)參數(shù)是運(yùn)行函數(shù)的參數(shù)。當(dāng)創(chuàng)建線程成功時(shí),函數(shù)返回0,若不為0則說明創(chuàng)建線程失敗,常見的錯(cuò)誤返回代碼為EAGAIN和EINVAL。前者表示系統(tǒng)限制創(chuàng)建新的線程,例如線程數(shù)目過多了;后者表示第二個(gè)參數(shù)代表的線程屬性值非法。線程的創(chuàng)建#include<pthread.h>108一個(gè)簡(jiǎn)單例子#include<stdio.h>

#include<pthread.h>

#include<string.h>

#include<sys/types.h>

#include<unistd.h>

pthread_tntid;

void*thr_fn(void*arg){

printids("newthread:");

return((void*)0);

}

intmain(){

interr;

err=pthread_create(&ntid,NULL,thr_fn,NULL);

if(err!=0){

printf("can'tcreatethread:%s\n",strerror(err));

return1;

}

sleep(1);

return0;

}一個(gè)簡(jiǎn)單例子#include<stdio.h>

#inclu109編譯多線程程序gcc-omypthread-lpthreadmypthread.c

編譯多線程程序gcc-omypthread-lpthr110線程的退出調(diào)用pthread_exit()結(jié)束線程執(zhí)行voidpthread_exit(void*retval);讓線程處理程序返回使用pthread_cancel()函數(shù)終止其他線程的執(zhí)行intpthread_cancel(pthread_tthread);向線程t發(fā)送取消請(qǐng)求,默認(rèn)情況下線程thread自己調(diào)用pthread_exi

溫馨提示

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

最新文檔

評(píng)論

0/150

提交評(píng)論