深圳營銷型網(wǎng)頁設(shè)計公司鄭州seo外包v1
1.進程間通信
1.1 進程間通信目的
- 數(shù)據(jù)傳輸:一個進程需要將它的數(shù)據(jù)發(fā)送給另一個進程
- 資源共享:多個進程之間共享同樣的資源。
- 通知事件:一個進程需要向另一個或一組進程發(fā)送消息,通知它(它們)發(fā)生了某種事件(如進程終止時要通知父進程)。
- 進程控制:有些進程希望完全控制另一個進程的執(zhí)行(如Debug進程),此時控制進程希望能夠攔截另一個進程的所有陷入和異常,并能夠及時知道它的狀態(tài)改變。?
數(shù)據(jù)傳輸:一個進程需要將它的數(shù)據(jù)發(fā)送給另一個進程
資源共享:多個進程之間共享同樣的資源。
通知事件:一個進程需要向另一個或一組進程發(fā)送消息,通知它(它們)發(fā)生了某種事件(如進程終止
時要通知父進程)。
進程控制:有些進程希望完全控制另一個進程的執(zhí)行(如Debug進程),此時控制進程希望能夠攔截另
一個進程的所有陷入和異常,并能夠及時知道它的狀態(tài)改變。
1.2 進程間通信發(fā)展?
- 管道
- System V進程間通信
- POSIX進程間通信
1.3 進程間通信分類
1.3.1 管道
- 匿名管道pipe
- 命名管道
1.3.2 System V IPC
- System V 消息隊列
- System V 共享內(nèi)存
- System V 信號量
1.3.3 POSIX IPC
- 消息隊列
- 共享內(nèi)存
- 信號量
- 互斥量
- 條件變量
- 讀寫鎖
2.管道(具有親緣關(guān)系)
管道是Unix中最古老的進程間通信的形式。
我們把從一個進程連接到另一個進程的一個數(shù)據(jù)流稱為一個“管道”
2.1 用fork來共享管道原理
2.2?匿名管道?
#include <unistd.h>
功能:創(chuàng)建一無名管道
原型
int pipe(int fd[2]);
參數(shù)
fd:文件描述符數(shù)組,其中fd[0]表示讀端, fd[1]表示寫端
返回值:成功返回0,失敗返回錯誤代碼
實例代碼?
打開管道
獲取鍵盤stdin的數(shù)據(jù)讀到buf中
把buf中的數(shù)據(jù)寫到管道中
從管道中把數(shù)據(jù)寫到回buf中
再把buf中的數(shù)據(jù)寫到stdout中
2.3?站在文件描述符角度-深度理解管道
2.4 站在內(nèi)核角度-管道本質(zhì)?
所以,看待管道,就如同看待文件一樣!管道的使用和文件一致,迎合了“Linux一切皆文件思想”。?
在my_shell中添加管道的實現(xiàn):
添加功能
2.5 管道讀寫規(guī)則
當(dāng)沒有數(shù)據(jù)可讀時
O_NONBLOCK disable:read調(diào)用阻塞,即進程暫停執(zhí)行,一直等到有數(shù)據(jù)來到為止。
O_NONBLOCK enable:read調(diào)用返回-1,errno值為EAGAIN。
當(dāng)管道滿的時候
O_NONBLOCK disable: write調(diào)用阻塞,直到有進程讀走數(shù)據(jù)
O_NONBLOCK enable:調(diào)用返回-1,errno值為EAGAIN
如果所有管道寫端對應(yīng)的文件描述符被關(guān)閉,則read返回0
如果所有管道讀端對應(yīng)的文件描述符被關(guān)閉,則write操作會產(chǎn)生信號SIGPIPE,進而可能導(dǎo)致write進程
退出
當(dāng)要寫入的數(shù)據(jù)量不大于PIPE_BUF時,linux將保證寫入的原子性。
當(dāng)要寫入的數(shù)據(jù)量大于PIPE_BUF時,linux將不再保證寫入的原子性。
2.6 管道特點
linux中一個匿名管道的文件描述符被關(guān)閉就不能再被打開了,所以只能實現(xiàn)單向通信
只能用于具有共同祖先的進程(具有親緣關(guān)系的進程)之間進行通信;通常,一個管道由一個進程創(chuàng)
建,然后該進程調(diào)用fork,此后父、子進程之間就可應(yīng)用該管道。
管道提供流式服務(wù)
一般而言,進程退出,管道釋放,所以管道的生命周期隨進程
一般而言,內(nèi)核會對管道操作進行同步與互斥
管道是半雙工的,數(shù)據(jù)只能向一個方向流動;需要雙方通信時,需要建立起兩個管道
3. 命名管道
- 管道應(yīng)用的一個限制就是只能在具有共同祖先(具有親緣關(guān)系)的進程間通信。
- 如果我們想在不相關(guān)的進程之間交換數(shù)據(jù),可以使用FIFO文件來做這項工作,它經(jīng)常被稱為命名管道。
- 命名管道是一種特殊類型的文件
3.1 創(chuàng)建命名管道
命令行方式創(chuàng)建
mkfifo filename
在代碼中創(chuàng)建
int mkfifo(const char *filename,mode_t mode);
真實權(quán)限收到umask的影響
匿名管道與命名管道的區(qū)別
匿名管道由pipe函數(shù)創(chuàng)建并打開。
命名管道由mkfifo函數(shù)創(chuàng)建,打開用open
FIFO(命名管道)與pipe(匿名管道)之間唯一的區(qū)別在它們創(chuàng)建與打開的方式不同,一但這些工作完
成之后,它們具有相同的語義。
命名管道的打開規(guī)則
如果當(dāng)前打開操作是為讀而打開FIFO時
O_NONBLOCK disable:阻塞直到有相應(yīng)進程為寫而打開該FIFO
O_NONBLOCK enable:立刻返回成功
如果當(dāng)前打開操作是為寫而打開FIFO時
O_NONBLOCK disable:阻塞直到有相應(yīng)進程為讀而打開該FIFO
O_NONBLOCK enable:立刻返回失敗,錯誤碼為ENXIO
實驗1-用命名管道實現(xiàn)文件拷貝
實驗2-用命名管道實現(xiàn)server&client通信
3. system V共享內(nèi)存
共享內(nèi)存區(qū)是最快的IPC形式。一旦這樣的內(nèi)存映射到共享它的進程的地址空間,這些進程間數(shù)據(jù)傳遞不再涉及到 內(nèi)核,換句話說是進程不再通過執(zhí)行進入內(nèi)核的系統(tǒng)調(diào)用來傳遞彼此的數(shù)據(jù)
共享內(nèi)存數(shù)據(jù)結(jié)構(gòu)
struct shmid_ds {struct ipc_perm shm_perm; /* operation perms */int shm_segsz; /* size of segment (bytes) */__kernel_time_t shm_atime; /* last attach time */__kernel_time_t shm_dtime; /* last detach time */__kernel_time_t shm_ctime; /* last change time */__kernel_ipc_pid_t shm_cpid; /* pid of creator */__kernel_ipc_pid_t shm_lpid; /* pid of last operator */unsigned short shm_nattch; /* no. of current attaches */unsigned short shm_unused; /* compatibility */void *shm_unused2; /* ditto - used by DIPC */void *shm_unused3; /* unused */
};
?
共享內(nèi)存函數(shù)
shmget函數(shù)
功能:用來創(chuàng)建共享內(nèi)存
原型int shmget(key_t key, size_t size, int shmflg);
參數(shù)key:這個共享內(nèi)存段名字size:共享內(nèi)存大小shmflg:由九個權(quán)限標(biāo)志構(gòu)成,它們的用法和創(chuàng)建文件時使用的mode模式標(biāo)志是一樣的
返回值:成功返回一個非負整數(shù),即該共享內(nèi)存段的標(biāo)識碼;失敗返回-1
shmat函數(shù)
功能:將共享內(nèi)存段連接到進程地址空間
原型void *shmat(int shmid, const void *shmaddr, int shmflg);
參數(shù)shmid: 共享內(nèi)存標(biāo)識shmaddr:指定連接的地址shmflg:它的兩個可能取值是SHM_RND和SHM_RDONLY
返回值:成功返回一個指針,指向共享內(nèi)存第一個節(jié);失敗返回-1shmaddr為NULL,核心自動選擇一個地址
shmaddr不為NULL且shmflg無SHM_RND標(biāo)記,則以shmaddr為連接地址。
shmaddr不為NULL且shmflg設(shè)置了SHM_RND標(biāo)記,則連接的地址會自動向下調(diào)整為SHMLBA的整數(shù)倍。公式:shmaddr -
(shmaddr % SHMLBA)
shmflg=SHM_RDONLY,表示連接操作用來只讀共享內(nèi)存
shmdt函數(shù)
功能:將共享內(nèi)存段與當(dāng)前進程脫離
原型int shmdt(const void *shmaddr);
參數(shù)shmaddr: 由shmat所返回的指針
返回值:成功返回0;失敗返回-1
注意:將共享內(nèi)存段與當(dāng)前進程脫離不等于刪除共享內(nèi)存段
shmctl函數(shù)
功能:用于控制共享內(nèi)存
原型int shmctl(int shmid, int cmd, struct shmid_ds *buf);
參數(shù)shmid:由shmget返回的共享內(nèi)存標(biāo)識碼cmd:將要采取的動作(有三個可取值)buf:指向一個保存著共享內(nèi)存的模式狀態(tài)和訪問權(quán)限的數(shù)據(jù)結(jié)構(gòu)
返回值:成功返回0;失敗返回-1
cmd | IPC_STAT:得到共享內(nèi)存的狀態(tài),把共享內(nèi)存的shmid_ds結(jié)構(gòu)復(fù)制到buf中 |
IPC_SET:改變共享內(nèi)存的狀態(tài),把buf所指的shmid_ds結(jié)構(gòu)中的uid、gid、mode復(fù)制到共享內(nèi)存的shmid_ds結(jié)構(gòu)內(nèi) | |
IPC_RMID:刪除這片共享內(nèi)存 |
?
- 鍵就是共享內(nèi)存的key;
- shmid是共享內(nèi)存的編號;
- semid是信號量數(shù)組的編號;
- nsems對應(yīng)信號量集中信號量的個數(shù)
- pid就是進程ip,可通過 ps -ef | grep pid 查看詳情
- semnum是信號量的編號
- ncount是等待該信號的進程數(shù)
- 擁有者就是創(chuàng)建它的用戶(owner);
- 權(quán)限也就是perms;
- 字節(jié)為創(chuàng)建的大小bytes;
- 連接數(shù)為連接到共享內(nèi)存的進程數(shù)nattach;
- 狀態(tài)是共享內(nèi)存的狀態(tài)status。
?
4.?system V消息隊列
5. system V信號量
6.進程互斥
- 由于各進程要求共享資源,而且有些資源需要互斥使用,因此各進程間競爭使用這些資源,進程的這種關(guān)系為進程的互斥
- 系統(tǒng)中某些資源一次只允許一個進程使用,稱這樣的資源為臨界資源或互斥資源。在進程中涉及到互斥資源的程序段叫臨界區(qū)
- 特性上:IPC資源必須刪除,否則不會自動清除,除非重啟,所以system V IPC資源的生命周期隨內(nèi)核