??進(jìn)程間通信(IPC),是指在不同進(jìn)程間傳播或交換信息的。其常用方式:管道(無名管道和命名管道)、消息隊列、共享內(nèi)存、信號、Socket、Streams等。其中 Socket和Streams支持不同主機(jī)上的兩個進(jìn)程IPC。
平橋ssl適用于網(wǎng)站、小程序/APP、API接口等需要進(jìn)行數(shù)據(jù)傳輸應(yīng)用場景,ssl證書未來市場廣闊!成為創(chuàng)新互聯(lián)的ssl證書銷售渠道,可以享受市場價格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:028-86922220(備注:SSL證書合作)期待與您的合作!一、管道(無名管道)函數(shù)原型:int pipe(int pipefd[2]);
包含頭文件:#include
成功調(diào)用返回0,否則返回-1;
參數(shù)pipdfd是數(shù)組,存放文件描述符;(pipefd[0]-讀,pipefd[1]-寫)
特點:1.它是半雙工的,具有固定的讀端和寫端;2.只能用于具有親緣關(guān)系進(jìn)程之間的通信(父子進(jìn)程或兄弟進(jìn)程);3.不是普通文件,但是可以使用read、write等,不屬于系統(tǒng)文件(即ls指令看不到該管道),只存在于內(nèi)存中。
上面代碼的中我們在父進(jìn)程中寫內(nèi)容到子進(jìn)程中,并且我們讓父進(jìn)程等待子進(jìn)程。
二、管道(命名管道FIFO)函數(shù)原型:int mkfifo(const char *pathname, mode_t mode);
包含頭文件:#include
、#include ; 參數(shù)1:文件路徑;參數(shù)2:與open函數(shù)中mode參數(shù)一樣;
成功返回0,否則返回-1;
特點:1.可以在無關(guān)進(jìn)程中通信;2.以一種特殊文件形式存在于系統(tǒng)文件中(ls看查看到);
這里要注意的是:當(dāng) open 一個FIFO時,是否設(shè)置非阻塞標(biāo)志(
O_NONBLOCK
)的區(qū)別:
若沒有指定
O_NONBLOCK
(默認(rèn)),只讀 open 要阻塞到某個其他進(jìn)程為寫而打開此 FIFO。類似的,只寫 open 要阻塞到某個其他進(jìn)程為讀而打開它。若指定了
O_NONBLOCK
,則只讀 open 立即返回。而只寫 open 將出錯返回 -1 如果沒有進(jìn)程已經(jīng)為讀而打開該 FIFO,其errno置ENXIO。
read.c:
write.c :
read.c執(zhí)行結(jié)果:?
write.c執(zhí)行結(jié)果:
這里我們實現(xiàn)了兩個無關(guān)進(jìn)程的通信,fife1就相當(dāng)于接口。
三、消息隊列消息隊列是消息的鏈接表,存放在內(nèi)核中,一個消息隊列由一個標(biāo)識符來標(biāo)識;
函數(shù)原型:
1.int msgget(key_t key, int msgflg);? ? ? ? //創(chuàng)建或打開消息隊列;
成功返回隊列ID,否則返回-1;
2.int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);? ? ? ? //發(fā)送消息;
參數(shù)1:隊列ID;參數(shù)2:消息相關(guān)的結(jié)構(gòu)體(包括消息類型和消息內(nèi)容);參數(shù)3:消息大小;參數(shù)4:取0即可(表示阻塞);
成功返回0,否則返回-1;
3.ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);? ? //讀取消息
和msgsnd函數(shù)參數(shù)不同的是多了long msgtye,msgtye對應(yīng)的就是消息類型,一般>0;
成功返回消息數(shù)據(jù)長度,否則返回-1;
4.int msgctl(int msqid, int cmd, struct msqid_ds *buf);? ? ? ? //控制消息隊列
參數(shù)1:隊列ID;參數(shù)2:對消息隊列控制命令;參數(shù)3:由參數(shù)2決定,一般為NULL;
成功返回0,否則返回-1;
特點:1.消息隊列是面向記錄的,消息具有特定的格式和特定的優(yōu)先級;2.獨立于發(fā)送和接收進(jìn)程,進(jìn)程終止消息隊列和其內(nèi)容不會被刪除;3.可以實現(xiàn)消息的隨機(jī)查詢;
receive.c
send.c
receivc.c運(yùn)行結(jié)果:
send.c運(yùn)行結(jié)果:
上面代碼表示:receive進(jìn)程在一直等待send進(jìn)程發(fā)數(shù)據(jù),當(dāng)receive進(jìn)程收到數(shù)據(jù)后給send進(jìn)程回應(yīng);?
四、共享內(nèi)存共享內(nèi)存是指兩個或兩個以上進(jìn)程共享一個給定的存儲區(qū);
函數(shù)原型:
1.int shmget(key_t key, size_t size, int shmflg);? ? ? ? //創(chuàng)建或獲取一個共享內(nèi)存;
(當(dāng)創(chuàng)建一個共享內(nèi)存時,參數(shù)2-size需指定其大小,并且以M為單位,引用一個存在的共享內(nèi)存時,size寫0即可)
成功返回共享內(nèi)存ID,否則返回-1;
2.void *shmat(int shmid, const void *shmaddr, int shmflg);????????//連接共享內(nèi)存到當(dāng)前進(jìn)程的地址空間;
成功連接后把共享內(nèi)存區(qū)對象映射到調(diào)用進(jìn)程的地址空間,隨后可像本地空間一樣訪問;
參數(shù)1:共享內(nèi)存ID;參數(shù)2:指定共享內(nèi)存的空間地址(為0時由系統(tǒng)默認(rèn)指定);參數(shù)3:與參數(shù)2相關(guān),參賽2為0時,參數(shù)3也為0;
成功返回指向共享內(nèi)存的指針(即地址),否則返回-1;
3.int shmdt(const void *shmaddr);? ? ? ? //端口與共享內(nèi)存的連接;
注意:這并不是從系統(tǒng)中刪除該共享內(nèi)存,只是當(dāng)前進(jìn)程不能再訪問該共享內(nèi)存而已;
成功返回0,否則返回-1;
4.int shmctl(int shmid, int cmd, struct shmid_ds *buf);? ? ? ? //控制共享內(nèi)存的相關(guān)信息;
參數(shù)1:共享內(nèi)存ID;參數(shù)2:對共享內(nèi)存控制命令;參數(shù)3:與參數(shù)2相關(guān),控制一些信息;
成功返回0,否則返回-1;
特點:1.共享內(nèi)存時最快的一種IPC,因為進(jìn)程直接對內(nèi)存進(jìn)行存??;2.因為多個進(jìn)程可以同時操作,因此需要進(jìn)行同步;3.共享內(nèi)存一般搭配信息量使用(同步信息);
shmwrite.c:
shmread.c:?
shmwrite.c運(yùn)行結(jié)果:?
shmread.c運(yùn)行結(jié)果:
以上代碼就是使用了共享內(nèi)存進(jìn)行通信,大家可以發(fā)我們在shmwrite.c里面發(fā)數(shù)據(jù)時運(yùn)用了sleep函數(shù),防止共享內(nèi)存提前銷毀了。
五、信號信號就是軟件中斷,信號提供了一種異步處理事件的方法,它允許進(jìn)程和內(nèi)核中斷其他進(jìn)程,一個信號就是一條消息,它通知進(jìn)程系統(tǒng)發(fā)生了某一種類型的事件;
信號的處理:1.忽略信號;2.捕捉信號;3.默認(rèn)動作;
忽略信號:大多數(shù)信號可以使用這個方式,注意:SIGKILL和SIGSTOP信號不能被忽略;
捕捉信號:當(dāng)該信號產(chǎn)生時,由內(nèi)核來調(diào)用用戶自定義的函數(shù)來實現(xiàn)某一種信號的處理;
默認(rèn)動作:當(dāng)發(fā)生該信號時,系統(tǒng)會自動執(zhí)行;
函數(shù)原型:
信號處理函數(shù)的注冊:
1.void ( *signal(int signum, void (*handler)(int)) ) (int);或者
typedef void (*sighandler_t)(int);
1.sighandler_t signal(int signum, sighandler_t handler);????????//設(shè)置某一信號對應(yīng)動作(入門版)
再講解這個函數(shù)之前我們先來補(bǔ)充一點知識——typedef用法之一:定義函數(shù)指針類型;就拿上面這個函數(shù)為例:sighandler_t是一個函數(shù)指針,其有一個整形類型的形參,并且返回值為空,使用typedef之后,sighandler_t就可以來定義一個函數(shù),其就相當(dāng)于是一個類型了(和int這種一樣),所有signal函數(shù)形參中handler就是一個形參為int,返回值為空的函數(shù)指針。再看signal函數(shù),通過其原型(即void ( *signal(int signum, void (*handler)(int)) ) (int))可知signal是一個指針函數(shù),即返回值為 指針的函數(shù),那么這樣sighandler_t signal(int signum, sighandler_t handler)就好理解了,就是signal的返回值是指針(這里是函數(shù)指針),其類型是sighandler_t(即形參為int,返回值為空的函數(shù)指針),這里要注意的是sighandler_t是signal返回值的類型,而不是signal的類型,但是是handler的類型。
參數(shù)1:信號名;參數(shù)2:信號處理函數(shù),當(dāng)信號發(fā)生時調(diào)用此函數(shù);
成功返回處理函數(shù)的指針,否則返回SIG_ERR;
2.int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);? ? ? ? //檢測或修改以及指定信號相關(guān)聯(lián)的處理動作(高級版,可攜帶消息)
參數(shù)1:信號名;參數(shù)2:結(jié)構(gòu)體指針(包含信號處理函數(shù)相關(guān)內(nèi)容);參數(shù)3:結(jié)構(gòu)體指針(用來備份);
成功返回0,否則返回-1;
信號處理發(fā)送函數(shù):
3.int kill(pid_t pid, int sig);? ? ? ? //將信號發(fā)送給進(jìn)程或者進(jìn)程組(入門版)
參數(shù)1:進(jìn)程PID;參數(shù)2:信號名;
成功返回0,否則返回-1;
4.int sigqueue(pid_t pid, int sig, const union sigval value);? ? ? ? //將信號發(fā)送給進(jìn)程或者進(jìn)組(高級版,可攜帶信息)
參數(shù)1:進(jìn)程PID;參數(shù)2:信號名;參數(shù)3:要發(fā)送的消息內(nèi)容;
成功返回0,否則返回-1;
一般signal函數(shù)搭配kill函數(shù)來使用:
signal.c:
kill.c:
一般sigaction函數(shù)搭配sigqueue函數(shù)使用:
sigaction.c:
sigqueue.c:?
sigqueue.c運(yùn)行結(jié)果:
sigaction.c運(yùn)行結(jié)果:
六、信號量信號量本質(zhì)上來說不屬于進(jìn)程間通信的方式之一,它是一個計數(shù)器。信號量用于實現(xiàn)進(jìn)程間的互斥與同步,而不是用于存儲進(jìn)程間通信數(shù)據(jù);
最簡單的信號量只能取0和1變量,稱為二值變量;可以取多個正整數(shù)的信號量稱為通用信號量;
函數(shù)原型:
1.int semget(key_t key, int nsems, int semflg);? ? ? ? //創(chuàng)建或獲取一個信號量組;
其中nsems為信號量的個數(shù),必須指定;若為現(xiàn)有的信號量集則為0;
成功返回信號量集ID,否則返回-1;
2.int semop(int semid, struct sembuf *sops, unsigned nsops);? ? ? ? //對信號量組進(jìn)行操作,改變信號量的值;
參數(shù)1:信號量集ID;參數(shù)2:結(jié)構(gòu)體指針,包含信號量相關(guān)信息;參數(shù)3:信號量數(shù)組;
成功返回0,否則返回-1;
3.int semctl(int semid, int semnum, int cmd, ...);? ? ? ? //控制信號兩個的相關(guān)信息;
參數(shù)1:信號量集ID;參數(shù)2:信號量編號;參數(shù)3;信號量的信息命令;參數(shù)4:與參數(shù)3有關(guān);
成功返回的值與cmd有關(guān),否則返回-1;
特點:1.信號量用于進(jìn)程間同步,一般配合共享內(nèi)存使用;2.信號量基于操作系統(tǒng)的PV操作,程序?qū)π盘柫康牟僮鞫际窃硬僮鳎?.每次對信號量的PV操作不僅限于信號量值+1或-1,而且可以加減任意數(shù);4.支持信號量組;
這個代碼就通過信號量來讓子進(jìn)程先運(yùn)行,子進(jìn)程先放信號量,父進(jìn)程等待信號量,一般不這樣用,因為要父進(jìn)程等待子進(jìn)程用wait函數(shù)即可,信號量一般是搭配共享內(nèi)存使用的。?
總結(jié)1.無名管道:速度慢,容量有限,只有親緣進(jìn)程之間才能通信;
2.有名管道:速度慢,但是任何進(jìn)程間都能通信;
3.消息隊列:容量受系統(tǒng)限制,第一次讀時,要考慮上次沒有讀完的數(shù)據(jù)問題;
4.共享內(nèi)存:能夠容易控制容量,速度快,但要考慮同步問題;
5.信號量:用來同步消息;
以上就是進(jìn)程間通信相關(guān)內(nèi)容,有不對的地方歡迎大家批評指正。
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧