進程間通信
1.管道有什麼特點?
管道是單向的、先進先出的,它把一個進程的輸出和另一個進程的輸入連接在一起。
一個進程(寫進程)在管道的尾部寫入數據,另一個進程(讀進程)從管道的頭部讀出數據。
數據被一個進程讀出後,將被從管道中刪除,其它讀進程將不能再讀到這些數據。
管道提供了簡單的流控制機制,進程試圖讀空管道時,進程將阻塞。同樣,管道已經滿時,進程再試圖向管道寫入數據,進程將阻塞
2.無名管道與有名管道的區別?
無名管道:用於父進程和子進程間的通信
有名管道:用於運行同一系統中的任意兩個進程間的通信。
3.無名管道的操作
創建管道pipe
讀管道read
寫管道write
關閉管道close
(1)pipe
函數的原型:int pipe(int fds[2])
函數的參數:新建的兩個描述符fds數組,fds[0]表示管道的讀取端,fds[1]表示管道的寫入端。
頭文件:#include <unistd.h>
返回值:成功返回0 出錯返回-1
4.無名管道讀寫:
先創建管道pipe
fork創建子進程:(管道用於不同進程間通信。通常先創建一個管道,再通過fork函數創建一個子進程,該子進程會繼承父進程所創建的管道)
(1)管道通訊是單向的,有固定的讀端和寫端。
(2)數據被進程從管道讀出後,在管道中該數據就不存在了。
(3)當進程去讀取空管道的時候,進程會阻塞。
(4)當進程往滿管道寫入數據時,進程會阻塞。
(5)管道容量爲64KB
5.有名管道操作:
創建管道mkfifo
打開管道open
讀管道read
寫管道write
關閉管道close
刪除管道unlink
(1)mkfifo
函數的作用:創建一個有名管道
函數的原型:int mkfifo(const char * pathname,mode_t mode)
參數的作用:pathname:FIFO的路徑名稱
mode:打開管道的方式
O_NONBLOCK:非阻塞
O_RDONLY:只讀
O_WRONLY:只寫
O_RDWR:可讀寫
6.管道使用和文件操作的區別?
(1)讀取fifo文件的進程只能以”RDONLY”方式打開fifo文件。
(2)寫fifo文件的進程只能以”WRONLY”方式打開fifo
(3) fifo文件裏面的內容被讀取後,就消失了。但是普通文件裏面的內容讀取後還存在。
7.什麼是信號機制?
信號(signal)機制是Unix系統中最爲古老的進程間通信機制,很多條件可以產生一個信號:
(1)當用戶按某些按鍵時,產生信號
(2)硬件異常產生信號:除數爲0、無效的存儲訪問等等。這些情況通常由硬件檢測到,將其通知內核,然後內核產生適當的信號通知進程,例如,內核對正訪問一個無效存儲區的進程產生一個SIGSEGV信號
(3)進程用kill函數將信號發送給另一個進程
(4)用戶可用kill命令將信號發送給其他進程
8.有哪幾種常見的信號?
下面是幾種常見的信號:
§ SIGHUP: 從終端上發出的結束信號
§ SIGINT: 來自鍵盤的中斷信號(Ctrl-C)
§ SIGKILL:該信號結束接收信號的進程,殺死進程
§ SIGTERM:kill 命令發出的信號
§ SIGCHLD:子進程停止或結束時通知父進程
§ SIGSTOP:來自鍵盤(Ctrl-Z)或調試程序的停止執行信號,暫停進程
9.信號處理的三種方式是什麼?
1、忽略此信號
大多數信號都按照這種方式進行處理,但有兩種信號決不能被忽略,它們是:
SIGKILL\SIGSTOP。這兩種信號不能被忽略的原因是:它們向超級用戶提供了一種終止或停止進程的方法
2、執行用戶希望的動作
通知內核在某種信號發生時,調用一個用戶函數。在用戶函數中,執行用戶希望的處理
3、執行系統默認動作
對大多數信號的系統默認動作是終止該進程
10.信號的發送,捕獲,處理如何操作?用什麼函數實現?
(1)kill
函數的作用:傳遞信號給指定的進程
函數的原型:int kill(pid_t pid,int sig)
函數的參數:pid > 0:指定的進程pid
pid == 0:將信號發送給同組的進程
pid < 0: 將信號發送給其進程組ID等於pid絕對值的進程
pid == -1:將信號發送給所有進程
頭文件:#include <sys/types.h>
#include <signal.h>
(2)raise
函數的作用:發送信號給自身
函數的原型:int raise(int sig)
頭文件:#include <signal.h>
kill與raise的區別:
kill既可以向自身發送信號,也可以向其他進程發送信號
raise:是向進程自身發送信號
(3)alarm
函數的作用:設置信號傳送鬧鐘
函數的原型:unsigned int alarm(unsigned int seconds)
頭文件:#include <unistd.h>
返回值:返回之前鬧鐘的剩餘秒數,如果之前未設鬧鐘則返回0
(4)pause
函數的作用:讓進程暫停,直到信號出現
函數的原型:int pause(void)
(5)signal
函數的作用:設置信號的處理方式
函數的原型:void (*signal(int signo,void (*sighandler_t)(int)))(int)
typedef void (*sighandler_t)(int) sighandler_t
signal(int signum, sighandler_t handler))
func可能的值是:
(1)SIG_IGN:忽略此信號
(2)SIG_DFL: 按系統默認方式處理
(3)信號處理函數名:使用該函數處理
11.什麼是共享內存?
共享內存是被多個進程共享的一部分物理內存.共享內存是進程間共享數據的一種最快的方法,一個進程向共享內存區域寫入了數據,共享這個內存區域的所有進程就可以立刻看到其中的內容.
12.如何實現共享內存?
(1)創建共享、打開共享內存,使用shmget函數
(2)映射共享內存,將這段創建的共享內存映射到具體的進程空間去,使用shmat函數
(3)分離共享內存
(4)控制、刪除共享內存
(1)shmget
函數的作用:在內核中創建共享內存
函數的原型:int shmget ( key_t key, int size, int shmflg )
函數的參數:key:標識共享內存的鍵值: 0/IPC_PRIVATE。 當key的取值爲IPC_PRIVATE,
則函數shmget()將創建一塊新的共享內存;如果key的取值爲0,而參數
shmflg中又設置IPC_PRIVATE這個標誌,則同樣會創建一塊新的共享內存。
size:創建的內存的大小
shmflg:類似open權限
返回值:成功:返回共享內存標識符,出錯:-1
頭文件:#include<sys/ipc.h>
#include<sys/shm.h>
(2)shmat
函數的作用:映射共享內存,映射到各自的內存空間
函數的原型:char * shmat ( int shmid, char *shmaddr, int flag)
函數的參數:shmid:內存標識符
shmaddr:映射到共享內存到本進程的指定地址,如果爲NULL,則又內核自動分配
flag:決定以什麼方式來確定映射的地址(通常爲0)
返回值:成功:發揮共享內存映射到進程中的地址, 失敗-1
(3)shmdt
函數的作用:撤銷共享內存的映射
函數的原型:int shmdt(const void* shmaddr)
函數的參數:shmaddr:被映射的共享內存的地址
返回值:成功:0 出錯:-1
13.什麼是消息隊列?
消息隊列就是一個消息的鏈表.可以把消息看作一個記錄,具有特定的格式.進程可以向中按照一定的規則添加新消息;另一些進程則可以從消息隊列中讀走消息。
14.消息隊列的操作:
創建打開消息隊列msgget()
讀數據從隊列msgrcv()
寫數據到隊列msgsnd()
控制消息隊列msgctl()
(1)ftok
函數的作用:獲取文件名對應的鍵值
函數的原型:key_t ftok (char*pathname, char proj)
函數的參數:pathname:文件名
proj:項目名(不爲0即可)
返回值:成功:返回文件名對應的鍵值,出錯:-1
頭文件:#include <sys/types.h>
#include <sys/ipc.h>
(2)msgget
函數的作用:創建消息隊列
函數的原型:int msgget(key_t key,int msgflg)
函數的參數:key:鍵值,由ftok獲得
msgflg:標誌位
返回值:成功:消息隊列的ID,出錯:-1
頭文件:#include<sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
(3)msgsnd
函數的作用:寫數據到消息隊列
函數的原型:int msgsnd(int msgid,struct msgbuf* msggp,int msgsz,int msgflg)
函數的參數:msggp:消息結構
struct msgbuf{
long msgtype;消息類型
char mtext[];消息正文
};
msgsz:消息的字節數
msgflg:IPC_NOWAIT:寫不進消息,直接退回
0:一直等待到能寫進去消息爲止
返回值:成功:0 出錯:-1
頭文件:#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
(4)msgrcv
函數的作用:從消息隊列接收消息
函數的原型:int msgrcv(int msqid, struct msgbuf *msgp, int msgsz, long msgtyp, int msgflg)
返回值:成功:0,出錯:-1
(5)msgctl
函數的作用:控制消息隊列,可以刪除消息隊列
函數的原型: int msgctl(int msgid,int cmd,struct msgid_ds * buf)
函數的參數:msgid:消息隊列的ID
cmd: IPC_STAT:讀取消息隊列的結構,存儲在buf中
IPC_SET:設置隊列的權限
IPC_RMID:刪除消息隊列
buf:消息隊列的結構類型
返回值:成功:0,出錯:-1
15.信號量的有什麼作用?
·可以保護臨界資源
·進程可以根據信號量判定是否能夠訪問某些共享資源。除了訪問控制外,還可用於進程同步
16.信號量的分類?
·二值信號燈:信號燈的值只能取0或1,類似於互斥鎖。但兩者有不同:
(1)信號燈強調共享資源,只要共享資源可用,其他進程同樣可以修改信號燈的值
(2)互斥鎖更強調進程,佔用資源的進程使用完資源後,必須由進程本身來解鎖
·計數信號燈:信號燈的值可以取任意非負值。
17.信號量的操作?
1.創建打開信號量,semget()
2.初始化信號量,semctl()的SETVAL操作。當使用二維信號量時將信號量初始化爲1;
3. 進行信號量的PV操作,調用semop()函數。
4.如果不用信號量,從系統中刪除他/她,使用semctl的IPC_RMID操作。
(1)semget
函數的作用:創建信號量
函數的原型:int semget(key_t key,int nsems,int semflg)
函數的參數:nsems:信號量的數目,通常取1個
semflg:同open函數權限位
返回值:成功:信號量的標識符 錯誤:-1
(2)semctl
函數的作用:信號量的控制、初始化、刪除
函數的原型:int semctl(int semid,int semnum,int cmd,union semun arg)
函數的參數:semnum:通常爲0,第一個信號量
cmd: IPC_STAT:
IPC_SETVAL:設置爲爲arg終的val的值
IPC_GETVAL:獲取信號量的值
IPC_RMID:刪除信號量
返回值:成功: cmd不同,返回值也不同
IPC_STAT、IPC_SETVAL、IPC_RMID:返回0
IPC_GETVAL:返回值信號量的值
出錯 -1
(3)semop
函數的作用:執行PV操作
函數的原型:int semop(int senid,struct sembuf *sops,size_t nsops)
函數的參數:struct sembuf * sops:
sem_op:-1 P操作
+1 V操作
nsops:-1
返回值:成功:信號量標識符,出錯:-1