Linux應用程式設計 12 程序間通訊 訊號燈

2021-09-22 08:28:21 字數 4135 閱讀 1489

訊號燈p/v操作 semop()

刪除訊號燈 semctl

程序間通訊方式比較

訊號燈集/共享記憶體—示例

訊號燈也叫訊號量,用於程序/執行緒同步或互斥的機制

訊號燈的型別

·posix 無名訊號燈

·posix有名訊號燈

·system v 訊號燈

訊號燈的含義

·計數訊號燈(訊號燈的值就是他代表的資源的數量,posix 無名訊號燈/posix有名訊號燈,都是計數訊號燈)

system v 訊號燈是乙個或多個計數訊號燈的集合

可同時操作集合中的多個訊號燈

申請多個資源時避免死鎖(訊號燈在乙個集合裡,需要的資源同時申請,都滿足時資源才能申請到)

對於訊號量,可以認為是乙個倉庫,有兩個概念,容量和當前的貨物個數。

p操作從倉庫拿貨,如果倉庫中沒有貨,執行緒一直等待,直到v操作,往倉庫裡新增了貨物,為了避免p操作一直等待下去,會有乙個超時時間。

v操作往倉庫送貨,如果倉庫滿了,執行緒等待,直到有p操作,從倉庫中拿走貨物,有空的位置。

建立訊號量,設定容量,先有v操作,才能p操作。

p操作:貨物個數減1,減過之後,貨物個數大於等於0,說明已經拿到貨物,執行緒繼續。否者執行緒阻塞。

v操作:貨物個數加1,加過之後,貨物個數小於等於容量,說明新增成功,執行緒繼續。否者執行緒阻塞。

訊號量:0≤ 訊號量≤容量 ,取值 表示當前可以使用的貨物;

訊號量<0 , 取值 表示當前等待使用貨物的執行緒;

訊號量》容量 , 訊號量-容量 表示當前等待新增貨物的執行緒。

通常,訊號量的容量設定很大,可以一直v操作,不會阻塞,但是p操作的時候,很可能阻塞。

當容量為1,也就是互斥,執行流程必定是v操作,p操作,v操作,p操作…

開啟/建立訊號燈 semget

訊號燈初始化 semctl

p/v操作 semop

刪除訊號燈 semctl

成功時返回訊號燈的id,失敗時返回-1

key 和訊號燈關聯的key ipc_private 或 ftok

nsems 集合中包含的計數訊號燈個數

sem*** 標誌位 ipc_creat|0666 ipc_excl(通常和ipc_creat一起使用,加上ipc_excl,如果訊號燈存在,則報錯)

-訊號燈在使用之前必須初始化,且只能初始化一次,通常第乙個程序初始化,後面的程序就不能初始化了。

成功時返回0,失敗時返回eof

semid 要操作的訊號燈集id

semnum 要操作的集合中的訊號燈編號

cmd 執行的操作 setval(設定訊號燈值) ipc_rmid(刪除整個訊號燈集)

union semun 取決於cmd(setval需要用到第四個引數,ipc_rmid不需要第四個引數),該共用體需要使用者自己定義

系統中union semun 共用體參考

union semun ;
要求:假設訊號燈集合中包含兩個訊號燈;第乙個初始化為2,第二個初始化為0

成功時返回0,失敗時返回-1

semid 要操作的訊號燈集id

sops 描述對訊號燈操作的結構體(陣列)

nsops 要操作的訊號燈的個數(一次操作sops陣列裡的前nsops個元素)

struct  sembuf 

;

semnum 訊號燈編號

sem_op -1:p操作 1:v操作 (也可以讓訊號數量增加或減少多個,將「1」換成「n」)

sem_*** 0(阻塞方式) / ipc_nowait

假設當前訊號燈集合中有3個訊號燈(意味著最多可以同時操作3個訊號燈),編號:0,1,2

現在同時對編號為0和2的訊號燈程序p操作

struct sembuf buf[3];//結構體陣列的大小應該和訊號燈集中訊號燈的數目保持一致

buf[0].sem_num = 0;

buf[0].sem_op = -1;

buf[0].sem_*** = 0;

buf[1].sem_num = 2;

buf[1].sem_op = -1;

buf[1].sem_*** = 0;

semop(semid,&buf,2);//2表示依次取出buf中的前兩個元素進行操作

要求:父子程序通過system v訊號燈同步對共享記憶體的讀寫 ·父程序從鍵盤輸入字串到共享記憶體 ·子程序刪除字串中的空格並列印

·父程序輸入quit後刪除共享記憶體和訊號燈集,程式結束

#include #include #include #include #include #include #include #include #define n 64  	//共享記憶體大小

#define read 0 //可讀緩衝區(個數)訊號燈在訊號燈集合中的編號為0

#define write 1 //可寫緩衝區(個數)訊號燈在訊號燈集合中的編號為1

union semun;

void init_sem(int semid,int s,int n);

void sem_pv(int semid,int num,int op);

int main(int argc, const char *ar**)

; pid_t pid;

key_t key;

char *shmaddr;

if((key = ftok(".",'s')) == -1)//生成key值

if((shmid = shmget(key,n,ipc_creat|0666)) < 0)//申請共享記憶體

if((semid = semget(key,2,ipc_creat|0666)) < 0)//申請訊號燈集

init_sem(semid,s,2);//訊號燈集初始化

if((shmaddr = shmat(shmid,null,0)) == (char *)-1)//對映共享記憶體位址

if((pid = fork()) < 0)//建立子程序

else if(pid == 0)

q++;

}*p = '\0';

printf("%s",shmaddr);

sem_pv(semid,write,1);//對寫訊號燈進行v操作

} }else

kill(pid,sigusr1);//給子程序發訊號,讓其結束

}_error2:

semctl(semid,0,ipc_rmid);//釋放申請的訊號燈集

_error1:

shmctl(shmid,ipc_rmid,null);//釋放申請的共享記憶體

return 0;

}void init_sem(int semid,int s,int n)//訊號燈集初始化函式

}void sem_pv(int semid,int num,int op)//訊號燈集p/v操作函式

Linux應用程式設計 程序通訊

通訊方式有管道pipe,訊號 一 pipe 管道分兩種無名管道,有名管道。1 無名管道 父程序和子程序可通過無名管道傳輸資料,管道有兩個口,一端寫一端讀,半雙工通訊。可以當作檔案進行操作,所以建立的管道會有兩個檔案描述符fds 0 和fds 1 fds 0 用於讀,fds 1 用於寫,關係如圖。實驗...

Linux應用程式設計之程序程式設計

程序同步 一組併發的程序按照一定的順序執行的過程稱為程序間的同步。獲取id include pid t getpid void 獲取本程序id pid t getppid void 在子程序中獲取父程序id 程序建立 include pid t fork void fork 的奇妙之處在於它被呼叫一...

Linux應用程式設計之程序程式設計

程序同步 一組併發的程序按照一定的順序執行的過程稱為程序間的同步。獲取id include pid t getpid void 獲取本程序id pid t getppid void 在子程序中獲取父程序id 程序建立 include pid t fork void fork 的奇妙之處在於它被呼叫一...