10月24日晚上,回到宿舍準備寫這周的總結時,看了下課表忽然意識到這已是第八週,不得不說時間過得真快,與前兩年輕鬆的、無任務的課程相比,今年真是充實了太多!這也許是感受時間過得快的緣由,可是最近我也遇到了許多問題,當接觸的知識多了之後,發現本身要學的東西太多了,僅僅上課所學遠遠不夠,因此課後自學了一些課程,遇到的問題一是本身好高騖遠,總想急於求成,這看一點那看一點,沒有系統的全面的琢磨一本書,問題二:對於應用方面的知識學到手很快,但也會很快的忘記,到了應用時只記得一些概念了。對於這兩個問題,我進行了一些思考,施行以下:在學習的時候把重要的知識點記錄下來,我本身用的是有道雲筆記,新學到的知識或者 不會的問題,經過查閱資料解決的 都把他們記錄下來。效果不錯,每週均可以回顧查看。最近開設了本身的博客,寫博客是爲了總結每日所學,反思自身。古人說「吾日三省吾身」仍是頗有道理的。在本身博客中進行知識總結,以及每週每個月思考回顧總結,感受收穫良多。另外,本身也有了一些新的感悟,咱們往往感嘆許多技術大牛,博客名人如何厲害,其實咱們本身就能夠成爲技術上的leader,其一就是知識及項目經驗的不斷積累,其二,我認爲就是學習知識時對細節的把握,其三,能夠鍥而不捨,不斷的學習新技術,平時不斷的回顧,「溫故而知新」。說了不少,實踐爲真,接下來還要繼續本身的求知之旅。好了下面進行本週的知識總結。shell
本週進行了兩天的授課,和三天的實訓;主要講解了Linux進程與線程編程中的進程之間的通訊這一方面知識。總結以下:編程
下面是我對這幾種方法的理解:異步
一、無名管道(pipe ):管道是一種半雙工的通訊方式,數據只能單向流動,並且只能在父子進程間通訊。管道的緩衝區是有限的(管道存在於內存中,在管道建立時,爲緩衝區分配一個頁面大小);管道所傳送的是無格式字節流,要求管道的讀出方和寫入方必須事先約定好數據的格式。函數
進程A fork()出一個進程B,進程B是複製進程A的副本,獲得了進程A的所有資源,所以,進程B也會有指向pd[1]的寫指針,指向pd[0]的讀指針。學習
因此管道這樣設計:spa
進程A:線程
Close( fd [0]);設計
Write( fd[1],buffer,sizeof(buffer));指針
進程B:blog
Close(fd [1]);
Read( fd[0],buf,sizeof(buf));
二、命名管道(fifo):命名管道也是半雙工的通訊方式,可是它容許無親緣關係進程間的通訊。嚴格遵循先進先出(first in first out),對管道及FIFO的讀老是從開始處返回數據,對它們的寫則把數據添加到末尾。諸如不支持lseek()等文件定位操做。
(1)管道應用的一個重大限制是它沒有名字,所以,只能用於具備親緣關係的進程間通訊,在有名管道(named pipe或FIFO)提出後,該限制獲得了克服。FIFO不一樣於管道之處在於它提供一個路徑名與之關聯,以FIFO的文件形式存在於文件系統中。這樣,即便與FIFO的建立進程不存在親緣關係的進程,只要能夠訪問該路徑,就可以彼此經過FIFO相互通訊(可以訪問該路徑的進程以及FIFO的建立進程之間),所以,經過FIFO不相關的進程也能交換數據。值得注意的是,FIFO嚴格遵循先進先出(first in first out),對管道及FIFO的讀老是從開始處返回數據,對它們的寫則把數據添加到末尾。它們不支持諸如lseek()等文件定位操做。
(2)有名管道的建立
int mkfifo(const char * pathname, mode_t mode);
該函數的第一個參數是一個普通的路徑名,也就是建立後FIFO的名字。第二個參數與打開普通文件的open()函數中的mode 參數相同。 若是mkfifo的第一個參數是一個已經存在的路徑名時,會返回EEXIST錯誤,因此通常典型的調用代碼首先會檢查是否返回該錯誤,若是確實返回該錯誤,那麼只要調用打開FIFO的函數就能夠了。通常文件的I/O函數均可以用於FIFO,如close、read、write等等。
(3)有名管道的打開規則
有名管道比管道多了一個打開操做:open。
FIFO的打開規則:
若是當前打開操做是爲讀而打開FIFO時,若已經有相應進程爲寫而打開該FIFO,則當前打開操做將成功返回;不然,可能阻塞直到有相應進程爲寫而打開該FIFO(當前打開操做設置了阻塞標誌);或者,成功返回(當前打開操做沒有設置阻塞標誌)。
若是當前打開操做是爲寫而打開FIFO時,若是已經有相應進程爲讀而打開該FIFO,則當前打開操做將成功返回;不然,可能阻塞直到有相應進程爲讀而打開該FIFO(當前打開操做設置了阻塞標誌);或者,返回ENXIO錯誤(當前打開操做沒有設置阻塞標誌)。
小結:
管道經常使用於兩個方面:(1)在shell中時常會用到管道(做爲輸入輸入的重定向),在這種應用方式下,管道的建立對於用戶來講是透明的;(2)用於具備親緣關係的進程間通訊,用戶本身建立管道,並完成讀寫操做。
FIFO能夠說是管道的推廣,克服了管道無名字的限制,使得無親緣關係的進程一樣能夠採用先進先出的通訊機制進行通訊。
管道和FIFO的數據是字節流,應用程序之間必須事先肯定特定的傳輸"協議",採用傳播具備特定意義的消息。要靈活應用管道及FIFO,理解它們的讀寫規則是關鍵。
三、消息隊列(message queue ):消息隊列是由消息的鏈表,存放在內核中並由消息隊列標識符標識。能夠用非先進先出方式處理;消息隊列是異步通訊的;消息隊列有大小限制,一般只用於小數據量的發送;只適用於單臺主機的進程間通訊;
消息隊列:
提供從一個進程向另外一個進程發送一個數據塊的方法
int msgget(key_t key,int msgflg);
int msgctl(int magid,int cmd,struct msgid_ds *buf);
int msgsnd(int msgid,void *msg_ptr,size_t msg_sz,int msgflag);
int msgrcv(int msgid,void *msg_ptr,size_t msg_sz,long int msg_type,int msgflag);
四、共享內存( shared memory):共享內存就是映射一段能被其餘進程所訪問的內存,這段共享內存由一個進程建立,但多個進程均可以訪問。共享內存是最快的IPC方式。效率高,進程能夠直接讀寫內存,而不須要任何數據的拷貝;在共享內存段中都是以字符串的默認結束符爲一條信息的結尾。每一個進程在讀寫時都遵照這個規則,就不會破壞數據的完整性。
共享內存
容許兩個不像關的進程訪問同一個邏輯地址
一、int shmget(key_t key,size_t size,int shmflag);
二、void *shmat(int shm_id,const void *shm_addr,int shm_flag);
三、int shmctl(int shm_id,int cmd,struct shmid_ds *buf);
四、int shmdt(const void *shm_addr);
5.信號量(semophore ):信號量是一個計數器,能夠用來控制多個進程對共享資源的訪問。主要做爲進程間以及同一進程內不一樣線程之間的同步手段。二元信號量:與Mutex相似。
信號量:
int semget(key_t key,int num_sems,int sem_flgs);
int semctl(int sem_id,int sem_num,int command...);
int semop(int sem_id,struct sembuf *sem_ops,size_t num_sem_ops);
每一個函數的功能和參數的意義在手冊中都能找到。
一、semge建立一個信號量或者獲取一個已知信號量的鍵
key:不相關的進程能夠經過他來訪問同一個信號量
num_sems:須要的信號量數目。幾乎老是1
sem_flags:一組標誌,例如IPC_CREAT;
返回值是信號量標誌符,給其餘信號量函數使用
二、semctl:
sem_id:信號量標誌符,semget的返回值
sem_ops:信號量編號,通常取0
command: 就不解釋了,在手冊中有詳細的解釋,我就偷偷懶吧。
三、semop
用於改變信號量的值
struct sembuf{
short sen_nums; //信號量編號,通常取0
short sem_op; //通常-1是P操做,1是V操做
short sem_flag; //一般設置爲UNDO
}