[Linux C編程]進程間通信

進程間通信

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章