1. 程式人生 > >Linux 進程學習

Linux 進程學習

ask 恢復 tpi 如果 發送信號 消息 ise arm suspend

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>
#include <sys/ipc.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);
參數:
msqid:消息隊列ID ----- msgget()
msgp:發送的消息緩沖區
struct msgbuf{
long mtype;//消息類型
char mtext[1];//消息內容
};
msgsz:消息內容的大小
msgflg:
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

Linux 進程學習