1、linux程序間通訊
繼承unix程序間通訊:管道 信号
AT&T :system V IPC 通訊程序隻能在單個計算機 :信号量 消息隊列 共享記憶體
BSD:形成了基于socket的程序間通訊機制 TCP/IP
2、管道
(1)無名管道:父子程序
#include <unistd.h>
int pipe(int pipefd[2]);
建立一個管道
fd[0]:讀端
fd[1]:寫端
傳回值:
0:成功
-1:失敗
注意:(1)當管道已經滿了 write pipe 會阻塞
(2) 當管道為空 read pipe 會阻塞
(2)有名管道:任何程序之間
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
3、信号
信号在軟體層次上對中斷的一種模拟 異步通訊方式
中斷:對cpu上的中斷 (硬體)
信号:對程序的中斷 (軟體)
(1)信号的來源
(1)程式執行錯誤 如 記憶體通路越界
(2)其他程序發送
(3)通過控制終端發送 ctrl + c;
(4)子程序結束向父程序發送信号 SIGCLD
(5)定時器SIGALRM
(2)信号
kill -l 檢視目前系統所有的信号
(3)信号處理方式
忽略信号:對信号不做任何處理
捕捉信号:定義處理函數 當信号發生的時候 執行相應的處理函數
預設操作:在linux系統中間都規定了預設操作
(4)信号的發送與捕捉
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
pid:接受信号的程序的PID
sig:信号
傳回值:0:成功
-1:出錯
int raise(int sig);
//kill(getpid(),SIGSTOP);
給程序本身發送信号
(5)定時器的信号捕捉
unsigned int alarm(unsigned int seconds);
程序定時器
定時時間到 發送SIGALRM
SIGALRM:預設操作:終止程序
在調用之前 如果已經設定過鬧鐘 傳回上一次的剩餘時間
否則傳回0
-1:出錯
int pause(void);
暫停程序
當收到信号時 會喚醒程序繼續執行
(6)信号處理
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
參數:
signum:信号
handler:SIG_IGN:忽略該信号
SIG_DFL:采用預設方式處理信号
自定義的信号處理函數的指針
傳回值:傳回一個指向信号處理函數的位址
1)父程序捕捉子程序的信号
2)從終端輸入文字再次輸出到終端,如果3s沒有輸入就輸出提示
//SIGALRM
alarm()和signal()
4、信号的阻塞處理
(1)通知系統核心停止向程序發送指定的信号
(2)核心對程序接收到的相應的信号進行緩存
(3)當程序解除相應的信号的阻塞
設定阻塞的原因:
(1)正在執行信号處理函數時有其他的信号到來
(2)信号處理函數和其他程序對某個共享區域進行讀寫
sigset_t:信号集
int sigemptyset(sigset_t *set);
把信号集合清空
int sigfillset(sigset_t *set);
把信号集合填滿
int sigaddset(sigset_t *set, int signum);
把對應的信号加到阻塞信号集合中
int sigdelset(sigset_t *set, int signum);
把對應的信号從阻塞信号集合中删除
int sigismember(const sigset_t *set, int signum);
判斷信号是否是在阻塞信号集合中
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
//設定阻塞信号集合
how:設定信号阻塞掩碼的方式
SIG_BLOCK:阻塞信号集
SIG_UNBLOCK:解除信号集
SIG_SETMASK:設定阻塞掩碼
oldset:舊的阻塞集合
int sigpending(sigset_t *set);
//擷取阻塞的信号 未決信号
int flag = 0;
int flag = 1;
while(flag == 0){
int sigsuspend(const sigset_t *mask);
}
//等待信号
(1)設定信号掩碼并阻塞程序
(2)收到信号 恢複原來的屏蔽字
(3)調用程序設定的信号處理函數
(4)等待信号處理函數傳回後 sigsuspend()傳回
原子操作
pause() -----等待信号(阻塞的信号除外)
5、消息隊列
(1)消息的清單
隊列ID
消息ID
(2)建立
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
key:指定的ID來生成隊列ID key:ftok()通過轉換檔案來擷取
msgflg:IPC_CREAT:建立新的消息隊列
IPC_EXCL:存在報錯
IPC_NOWAIT:非阻塞
傳回值:傳回隊列ID
#include <sys/types.h>
key_t ftok(const char *pathname, int proj_id);
功能:擷取key
pathname:檔案名---->inode節點号
proj_id:自己指定
由inode節點号和proj_id合成
65538:0x10002
38:0x26
key: 0x2610002
(4)接收消息
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
參數:
msqid:消息隊列ID ----- msgget()
msgp:消息的緩沖區
msgsz:消息結構的大小
msgtyp:0:接收消息隊列中的第一個消息
大于0:接收消息隊列中第一個為msgtyp的消息
小于0:接收消息隊列中第一個不小于msgtyp的絕對值由最小的消息
msgflg:
0:忽略
MSG_NOERROR:接收的消息大于size 則消息就會截短到size位元組 不通知消息發送程序
IPC_NOWAIT:沒有指定類型的消息 就會傳回錯誤ENOMSG
傳回值:實際接收的位元組數
會删除對應的消息
(5)發送消息
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
msgp:發送的消息緩沖區
struct msgbuf{
long mtype;//消息類型
char mtext[1];//消息内容
};
msgsz:消息内容的大小
IPC_NOWAIT:發送條件不滿足的時 就會立即傳回
a):隊列消息已經滿了
建立2個子程序 父程序負責發送 子程序1:發送類型為1的消息 子程序2:發送消息類型為2的消息
子程序1接收類型為1的消息
子程序2接收類型為2的消息
(5)控制函數
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
msqid:消息隊列ID
cmd:
IPC_STAT:擷取struct msqid_ds結構 儲存到buf
IPC_SET:設定struct msgqid_ds結構
IPC_RMID:删除消息隊列
buf:存儲struct msqid_ds結構
傳回值:成功:0(IPC_STAT,IPC_SET,IPC_RMID)
失敗:-1