在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

電子發(fā)燒友App

硬聲App

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示
創(chuàng)作
電子發(fā)燒友網(wǎng)>電子資料下載>嵌入式開發(fā)>linux多線程編程技術(shù)

linux多線程編程技術(shù)

2017-10-24 | rar | 0.3 MB | 次下載 | 1積分

資料介紹

1 引言
  線程(thread)技術(shù)早在60年代就被提出,但真正應(yīng)用多線程到操作系統(tǒng)中去,是在80年代中期,solaris是這方面的佼佼者。傳統(tǒng)的 Unix也支持線程的概念,但是在一個進程(process)中只允許有一個線程,這樣多線程就意味著多進程。現(xiàn)在,多線程技術(shù)已經(jīng)被許多操作系統(tǒng)所支持,包括Windows/NT,當(dāng)然,也包括Linux
  為什么有了進程的概念后,還要再引入線程呢?使用多線程到底有哪些好處?什么的系統(tǒng)應(yīng)該選用多線程?我們首先必須回答這些問題。
  使用多線程的理由之一是和進程相比,它是一種非常“節(jié)儉”的多任務(wù)操作方式。我們知道,在Linux系統(tǒng)下,啟動一個新的進程必須分配給它獨立的地址空間,建立眾多的數(shù)據(jù)表來維護它的代碼段、堆棧段和數(shù)據(jù)段,這是一種“昂貴”的多任務(wù)工作方式。而運行于一個進程中的多個線程,它們彼此之間使用相同的地址空間,共享大部分數(shù)據(jù),啟動一個線程所花費的空間遠遠小于啟動一個進程所花費的空間,而且,線程間彼此切換所需的時間也遠遠小于進程間切換所需要的時間。據(jù)統(tǒng)計,總的說來,一個進程的開銷大約是一個線程開銷的30倍左右,當(dāng)然,在具體的系統(tǒng)上,這個數(shù)據(jù)可能會有較大的區(qū)別。
  使用多線程的理由之二是線程間方便的通信機制。對不同進程來說,它們具有獨立的數(shù)據(jù)空間,要進行數(shù)據(jù)的傳遞只能通過通信的方式進行,這種方式不僅費時,而且很不方便。線程則不然,由于同一進程下的線程之間共享數(shù)據(jù)空間,所以一個線程的數(shù)據(jù)可以直接為其它線程所用,這不僅快捷,而且方便。當(dāng)然,數(shù)據(jù)的共享也帶來其他一些問題,有的變量不能同時被兩個線程所修改,有的子程序中聲明為static的數(shù)據(jù)更有可能給多線程程序帶來災(zāi)難性的打擊,這些正是編寫多線程程序時最需要注意的地方。
  除了以上所說的優(yōu)點外,不和進程比較,多線程程序作為一種多任務(wù)、并發(fā)的工作方式,當(dāng)然有以下的優(yōu)點:
  1) 提高應(yīng)用程序響應(yīng)。這對圖形界面的程序尤其有意義,當(dāng)一個操作耗時很長時,整個系統(tǒng)都會等待這個操作,此時程序不會響應(yīng)鍵盤、鼠標、菜單的操作,而使用多線程技術(shù),將耗時長的操作(time consuming)置于一個新的線程,可以避免這種尷尬的情況。
  2) 使多CPU系統(tǒng)更加有效。操作系統(tǒng)會保證當(dāng)線程數(shù)不大于CPU數(shù)目時,不同的線程運行于不同的CPU上。
  3) 改善程序結(jié)構(gòu)。一個既長又復(fù)雜的進程可以考慮分為多個線程,成為幾個獨立或半獨立的運行部分,這樣的程序會利于理解和修改。
  下面我們先來嘗試編寫一個簡單的多線程程序。
  2 簡單的多線程編程
  Linux系統(tǒng)下的多線程遵循POSIX線程接口,稱為pthread。編寫Linux下的多線程程序,需要使用頭文件pthread.h,連接時需要使用庫libpthread.a。順便說一下,Linux下pthread的實現(xiàn)是通過系統(tǒng)調(diào)用clone()來實現(xiàn)的。clone()是Linux所特有的系統(tǒng)調(diào)用,它的使用方式類似fork,關(guān)于clone()的詳細情況,有興趣的讀者可以去查看有關(guān)文檔說明。下面我們展示一個最簡單的多線程程序 example1.c。
  /* example.c*/
  #include
  #include
  void thread(void)
  {
  int i;
  for(i=0;i《3;i++)
  printf(“This is a pthread.n”);
  }
  int main(void)
  {
  pthread_t id;
  int i,ret;
  ret=pthread_create(&id,NULL,(void *) thread,NULL);
  if(ret!=0){
  printf (“Create pthread error!n”);
  exit (1);
  }
  for(i=0;i《3;i++)
  printf(“This is the main process.n”);
  pthread_join(id,NULL);
  return (0);
  }
  我們編譯此程序:
  gcc example1.c -lpthread -o example1
  運行example1,我們得到如下結(jié)果:
  This is the main process.
  This is a pthread.
  This is the main process.
  This is the main process.
  This is a pthread.
  This is a pthread.
  再次運行,我們可能得到如下結(jié)果:
  This is a pthread.
  This is the main process.
  This is a pthread.
  This is the main process.
  This is a pthread.
  This is the main process.
  前后兩次結(jié)果不一樣,這是兩個線程爭奪CPU資源的結(jié)果。上面的示例中,我們使用到了兩個函數(shù),  pthread_create和pthread_join,并聲明了一個pthread_t型的變量。
  pthread_t在頭文件/usr/include/bits/pthreadtypes.h中定義:
  typedef unsigned long int pthread_t;
  它是一個線程的標識符。函數(shù)pthread_create用來創(chuàng)建一個線程,它的原型為:
  extern int pthread_create __P ((pthread_t *__thread, __const pthread_attr_t *__attr,
  void *(*__start_routine) (void *), void *__arg));
  第一個參數(shù)為指向線程標識符的指針,第二個參數(shù)用來設(shè)置線程屬性,第三個參數(shù)是線程運行函數(shù)的起始地址,最后一個參數(shù)是運行函數(shù)的參數(shù)。這里,我們的函數(shù)thread不需要參數(shù),所以最后一個參數(shù)設(shè)為空指針。第二個參數(shù)我們也設(shè)為空指針,這樣將生成默認屬性的線程。對線程屬性的設(shè)定和修改我們將在下一節(jié)闡述。當(dāng)創(chuàng)建線程成功時,函數(shù)返回0,若不為0則說明創(chuàng)建線程失敗,常見的錯誤返回代碼為EAGAIN和EINVAL。前者表示系統(tǒng)限制創(chuàng)建新的線程,例如線程數(shù)目過多了;后者表示第二個參數(shù)代表的線程屬性值非法。創(chuàng)建線程成功后,新創(chuàng)建的線程則運行參數(shù)三和參數(shù)四確定的函數(shù),原來的線程則繼續(xù)運行下一行代碼。
  函數(shù)pthread_join用來等待一個線程的結(jié)束。函數(shù)原型為:
  extern int pthread_join __P ((pthread_t __th, void **__thread_return));
  第一個參數(shù)為被等待的線程標識符,第二個參數(shù)為一個用戶定義的指針,它可以用來存儲被等待線程的返回值。這個函數(shù)是一個線程阻塞的函數(shù),調(diào)用它的函數(shù)將一直等待到被等待的線程結(jié)束為止,當(dāng)函數(shù)返回時,被等待線程的資源被收回。一個線程的結(jié)束有兩種途徑,一種是象我們上面的例子一樣,函數(shù)結(jié)束了,調(diào)用它的線程也就結(jié)束了;另一種方式是通過函數(shù)pthread_exit來實現(xiàn)。它的函數(shù)原型為:
  extern void pthread_exit __P ((void *__retval)) __attribute__ ((__noreturn__));
  唯一的參數(shù)是函數(shù)的返回代碼,只要pthread_join中的第二個參數(shù)thread_return不是NULL,這個值將被傳遞給 thread_return。最后要說明的是,一個線程不能被多個線程等待,否則第一個接收到信號的線程成功返回,其余調(diào)用pthread_join的線程則返回錯誤代碼ESRCH。
  在這一節(jié)里,我們編寫了一個最簡單的線程,并掌握了最常用的三個函數(shù)pthread_create,pthread_join和pthread_exit。下面,我們來了解線程的一些常用屬性以及如何設(shè)置這些屬性。
  3 修改線程的屬性
  在上一節(jié)的例子里,我們用pthread_create函數(shù)創(chuàng)建了一個線程,在這個線程中,我們使用了默認參數(shù),即將該函數(shù)的第二個參數(shù)設(shè)為NULL。的確,對大多數(shù)程序來說,使用默認屬性就夠了,但我們還是有必要來了解一下線程的有關(guān)屬性。
  屬性結(jié)構(gòu)為pthread_attr_t,它同樣在頭文件/usr/include/pthread.h中定義,喜歡追根問底的人可以自己去查看。屬性值不能直接設(shè)置,須使用相關(guān)函數(shù)進行操作,初始化的函數(shù)為pthread_attr_init,這個函數(shù)必須在pthread_create函數(shù)之前調(diào)用。屬性對象主要包括是否綁定、是否分離、堆棧地址、堆棧大小、優(yōu)先級。默認的屬性為非綁定、非分離、缺省1M的堆棧、與父進程同樣級別的優(yōu)先級。
  關(guān)于線程的綁定,牽涉到另外一個概念:輕進程(LWP:Light Weight Process)。輕進程可以理解為內(nèi)核線程,它位于用戶層和系統(tǒng)層之間。系統(tǒng)對線程資源的分配、對線程的控制是通過輕進程來實現(xiàn)的,一個輕進程可以控制一個或多個線程。默認狀況下,啟動多少輕進程、哪些輕進程來控制哪些線程是由系統(tǒng)來控制的,這種狀況即稱為非綁定的。綁定狀況下,則顧名思義,即某個線程固定的“綁”在一個輕進程之上。被綁定的線程具有較高的響應(yīng)速度,這是因為CPU時間片的調(diào)度是面向輕進程的,綁定的線程可以保證在需要的時候它總有一個輕進程可用。通過設(shè)置被綁定的輕進程的優(yōu)先級和調(diào)度級可以使得綁定的線程滿足諸如實時反應(yīng)之類的要求。
  設(shè)置線程綁定狀態(tài)的函數(shù)為pthread_attr_setscope,它有兩個參數(shù),第一個是指向?qū)傩越Y(jié)構(gòu)的指針,第二個是綁定類型,它有兩個取值:PTHREAD_SCOPE_SYSTEM(綁定的)和PTHREAD_SCOPE_PROCESS(非綁定的)。下面的代碼即創(chuàng)建了一個綁定的線程。
  #include
  pthread_attr_t attr;
  pthread_t tid;
  /*初始化屬性值,均設(shè)為默認值*/
  pthread_attr_init(&attr);
  pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
  pthread_create(&tid, &attr, (void *) my_function, NULL);
  線程的分離狀態(tài)決定一個線程以什么樣的方式來終止自己。在上面的例子中,我們采用了線程的默認屬性,即為非分離狀態(tài),這種情況下,原有的線程等待創(chuàng)建的線程結(jié)束。只有當(dāng)pthread_join()函數(shù)返回時,創(chuàng)建的線程才算終止,才能釋放自己占用的系統(tǒng)資源。而分離線程不是這樣子的,它沒有被其他的線程所等待,自己運行結(jié)束了,線程也就終止了,馬上釋放系統(tǒng)資源。程序員應(yīng)該根據(jù)自己的需要,選擇適當(dāng)?shù)姆蛛x狀態(tài)。設(shè)置線程分離狀態(tài)的函數(shù)為 pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)。第二個參數(shù)可選為PTHREAD_CREATE_DETACHED(分離線程)和 PTHREAD _CREATE_JOINABLE(非分離線程)。這里要注意的一點是,如果設(shè)置一個線程為分離線程,而這個線程運行又非常快,它很可能在 pthread_create函數(shù)返回之前就終止了,它終止以后就可能將線程號和系統(tǒng)資源移交給其他的線程使用,這樣調(diào)用pthread_create的線程就得到了錯誤的線程號。要避免這種情況可以采取一定的同步措施,最簡單的方法之一是可以在被創(chuàng)建的線程里調(diào)用 pthread_cond_timewait函數(shù),讓這個線程等待一會兒,留出足夠的時間讓函數(shù)pthread_create返回。設(shè)置一段等待時間,是在多線程編程里常用的方法。但是注意不要使用諸如wait()之類的函數(shù),它們是使整個進程睡眠,并不能解決線程同步的問題。
  另外一個可能常用的屬性是線程的優(yōu)先級,它存放在結(jié)構(gòu)sched_param中。用函數(shù)pthread_attr_getschedparam和函數(shù) pthread_attr_setschedparam進行存放,一般說來,我們總是先取優(yōu)先級,對取得的值修改后再存放回去。下面即是一段簡單的例子。
  #include
  #include
  pthread_attr_t attr;
  pthread_t tid;
  sched_param param;
  int newprio=20;
  pthread_attr_init(&attr);
  pthread_attr_getschedparam(&attr, ?m);
  param.sched_priority=newprio;
  pthread_attr_setschedparam(&attr, ?m);
  pthread_create(&tid, &attr, (void *)myfunction, myarg);
  4 線程的數(shù)據(jù)處理
  和進程相比,線程的最大優(yōu)點之一是數(shù)據(jù)的共享性,各個進程共享父進程處沿襲的數(shù)據(jù)段,可以方便的獲得、修改數(shù)據(jù)。但這也給多線程編程帶來了許多問題。我們必須當(dāng)心有多個不同的進程訪問相同的變量。許多函數(shù)是不可重入的,即同時不能運行一個函數(shù)的多個拷貝(除非使用不同的數(shù)據(jù)段)。在函數(shù)中聲明的靜態(tài)變量常常帶來問題,函數(shù)的返回值也會有問題。因為如果返回的是函數(shù)內(nèi)部靜態(tài)聲明的空間的地址,則在一個線程調(diào)用該函數(shù)得到地址后使用該地址指向的數(shù)據(jù)時,別的線程可能調(diào)用此函數(shù)并修改了這一段數(shù)據(jù)。在進程中共享的變量必須用關(guān)鍵字volatile來定義,這是為了防止編譯器在優(yōu)化時(如gcc中使用-OX參數(shù))改變它們的使用方式。為了保護變量,我們必須使用信號量、互斥等方法來保證我們對變量的正確使用。下面,我們就逐步介紹處理線程數(shù)據(jù)時的有關(guān)知識。
  4.1 線程數(shù)據(jù)
  在單線程的程序里,有兩種基本的數(shù)據(jù):全局變量和局部變量。但在多線程程序里,還有第三種數(shù)據(jù)類型:線程數(shù)據(jù)(TSD: Thread-Specific Data)。它和全局變量很象,在線程內(nèi)部,各個函數(shù)可以象使用全局變量一樣調(diào)用它,但它對線程外部的其它線程是不可見的。這種數(shù)據(jù)的必要性是顯而易見的。例如我們常見的變量errno,它返回標準的出錯信息。它顯然不能是一個局部變量,幾乎每個函數(shù)都應(yīng)該可以調(diào)用它;但它又不能是一個全局變量,否則在 A線程里輸出的很可能是B線程的出錯信息。要實現(xiàn)諸如此類的變量,我們就必須使用線程數(shù)據(jù)。我們?yōu)槊總€線程數(shù)據(jù)創(chuàng)建一個鍵,它和這個鍵相關(guān)聯(lián),在各個線程里,都使用這個鍵來指代線程數(shù)據(jù),但在不同的線程里,這個鍵代表的數(shù)據(jù)是不同的,在同一個線程里,它代表同樣的數(shù)據(jù)內(nèi)容。
下載該資料的人也在下載 下載該資料的人還在閱讀
更多 >

評論

查看更多

下載排行

本周

  1. 1GD100PIX120C6SNA規(guī)格書
  2. 0.98 MB   |  3次下載  |  免費
  3. 2一款入耳式耳機的仿真與分析
  4. 0.44 MB   |  2次下載  |  免費
  5. 3Eurotherm TKS Temperature 用戶手冊
  6. 1.46 MB  |  2次下載  |  免費
  7. 4人形機器人電機驅(qū)動和傳感報告
  8. 4.27 MB   |  2次下載  |  免費
  9. 5無線系統(tǒng)中天線和RF元件電磁建模
  10. 7.48 MB   |  1次下載  |  4 積分
  11. 6Multisim模擬電路仿真教程
  12. 1.93 MB   |  1次下載  |  3 積分
  13. 7DMP300C1型微機變壓器保護測控裝置技術(shù)說明書
  14. 4.11 MB   |  次下載  |  10 積分
  15. 8用MT3540芯片設(shè)計BOOST電路 1(可下載)
  16. 445.66 KB  |  次下載  |  免費

本月

  1. 1晶體三極管的電流放大作用詳細說明
  2. 0.77 MB   |  32次下載  |  2 積分
  3. 2Python從入門到精通背記手冊
  4. 18.77 MB   |  27次下載  |  1 積分
  5. 3雙極型三極管放大電路的三種基本組態(tài)的學(xué)習(xí)課件免費下載
  6. 4.03 MB   |  25次下載  |  1 積分
  7. 4AIWA HS-J303 MKⅡ維修手冊
  8. 22.47 MB   |  23次下載  |  10 積分
  9. 5多級放大電路的學(xué)習(xí)課件免費下載
  10. 1.81 MB   |  21次下載  |  2 積分
  11. 6九陽豆?jié){機高清原理圖
  12. 2.47 MB   |  20次下載  |  1 積分
  13. 7AIWA HS-J202/HS-J202M/HS-J800維修手冊
  14. 13.60 MB   |  15次下載  |  10 積分
  15. 81875功放原理圖
  16. 0.04 MB   |  11次下載  |  免費

總榜

  1. 1matlab軟件下載入口
  2. 未知  |  935127次下載  |  10 積分
  3. 2開源硬件-PMP21529.1-4 開關(guān)降壓/升壓雙向直流/直流轉(zhuǎn)換器 PCB layout 設(shè)計
  4. 1.48MB  |  420063次下載  |  10 積分
  5. 3Altium DXP2002下載入口
  6. 未知  |  233089次下載  |  10 積分
  7. 4電路仿真軟件multisim 10.0免費下載
  8. 340992  |  191382次下載  |  10 積分
  9. 5十天學(xué)會AVR單片機與C語言視頻教程 下載
  10. 158M  |  183337次下載  |  10 積分
  11. 6labview8.5下載
  12. 未知  |  81585次下載  |  10 積分
  13. 7Keil工具MDK-Arm免費下載
  14. 0.02 MB  |  73814次下載  |  10 積分
  15. 8LabVIEW 8.6下載
  16. 未知  |  65988次下載  |  10 積分
主站蜘蛛池模板: 亚洲 欧美 日韩 在线 中文字幕 | 国产做爰一区二区 | 欧美一区二区三区不卡片 | 99久久伊人一区二区yy5099 | 不卡免费在线视频 | 欧美xingai| 网全大全黄 | 天堂8中文在线bt | 欧美久久天天综合香蕉伊 | 天天干天天舔 | 欧美乱理伦另类视频 | 国产h在线 | 免费视频现线观看 | 在线观看免费视频 | 新天堂在线| 国产成人免费无庶挡视频 | 国产亚洲美女精品久久久久狼 | 日本免费在线视频 | 一级一黄在线观看视频免费 | 欧美日本综合 | 一二三区电影 | 色噜噜噜噜色 | 国产又色 | 2018天天操天天干 | 一区二区在线免费观看 | 午夜视频日本 | 久久99爰这里有精品国产 | 女人张开腿等男人桶免费视频 | 激情六月婷婷开心丁香开心 | 波多野结衣中文字幕教师 | 红怡院欧洲 | 韩剧天堂 | 天堂在线精品 | 一级不卡毛片免费 | 欧美videosex性欧美成人 | 国产精品天天看 | 国产婷婷色一区二区三区 | 免费在线看a | 丁香婷婷九月 | 天天干中文字幕 | 12306影院午夜入口 |