程序間通訊 記憶體共享訊號量例項理解
阿新 • • 發佈:2018-11-13
申請記憶體:
int shmget(key_t key, size_t size, int shmflg);
其中key為鑰匙,兩程序通過同一個鑰匙找到核心中的共享記憶體,可通過
key_t ftok(const char *pathname, int proj_id)
得到key,也可通過強制轉換自行制定數值。
size為申請共享記憶體空間的大小(B)
shmflg為標誌
返回值為共享記憶體的標示符。
記憶體對映:
void *shmat(int shmid, const void *shmaddr, int shmflg);
其中shmid為共享記憶體的ID。
shmaddr為映射向程序的地址,一般填NULL讓系統指配
返回值為程序內對映共享內粗的地址。
這樣通過操作程序內對映地址(記憶體),便可以在共享記憶體中寫入或讀取資料。
但該過程是不受控制的,因此我們需要通過阻塞來控制程序的執行。
訊號量
訊號量與共享記憶體類似,也是在核心空間中申請一段記憶體儲存資料
申請訊號量:
int semget(key_t key, int nsems, int semflg);
其中 key為鑰匙,兩程序通過鑰匙找到同一個訊號量
nsems 為申請的訊號量的個數
返回值為訊號量標示符
操作訊號量:
int semctl(int semid, int semnum, int cmd, ...);
其中semnum,為第semnum位訊號量,從0開始
cmd為指定的操作
後面跟對應資料
int semop(int semid, struct sembuf *sops, unsigned nsops);
其中
struct sembuf
{
unsigned short sem_num; /* 第sem_num位訊號量 */
short sem_op; /* 操作量 */
short sem_flg; /* 標誌對應操作 */
}
nsops為,對nsops個訊號量進行該操作
因為訊號量的值不能小於0,因此可以通過semop函式進行阻塞。
例項:
輸入程式:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/shm.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#include<string.h>
int main()
{
int running =1;
int shid;
int semid;
int value;
char *sharem=NULL;
struct sembuf sem_b,sem_c;
sem_b.sem_num=1;
sem_b.sem_flg=SEM_UNDO;
sem_c.sem_num=0;
sem_c.sem_flg=SEM_UNDO;
if((semid=semget((key_t)123456,2,0666|IPC_CREAT))==-1)//申請訊號量
{
perror("semget");
exit(1);
}
shid=shmget((key_t)654321,(size_t)2048,0600|IPC_CREAT);//申請共享記憶體
if(shid==-1)
exit(1);
sharem=shmat(shid,NULL,0);
if(sharem==NULL)
exit(1);
semctl(semid,1,SETVAL,1);//初始化將自己的訊號量設為1
semctl(semid,0,SETVAL,0);//將讀取程序的訊號量設為0使之堵塞
while(running)
{
sem_b.sem_op=-1;//設為-1
if(semop(semid,&sem_b,1)==-1)//讓訊號量0加-1,若此時訊號量為0則無法-1則阻塞
{
exit(1);
}
printf("write data operate\n");
printf("please input something:");
scanf("%s",sharem);
semctl(semid,0,SETVAL,1);//輸入完畢將讀取訊號訊號量置1使之不堵塞
semctl(semid,1,SETVAL,0);//將自己的訊號量設為0,使自身堵塞無法再寫入
if(strcmp(sharem,"end")==0)
running--;
}
shmdt(sharem);
return 0;
}
接收程式:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/shm.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#include<string.h>
int main()
{
int running =1;
int shid;
int semid;
int value;
char *sharem=NULL;
struct sembuf sem_b,sem_c;
sem_b.sem_num=1;
sem_b.sem_flg=SEM_UNDO;
sem_c.sem_num=0;
sem_c.sem_flg=SEM_UNDO;
if((semid=semget((key_t)123456,2,0666|IPC_CREAT))==-1)
{
perror("semget");
exit(1);
}
shid=shmget((key_t)654321,(size_t)2048,0600|IPC_CREAT);
if(shid==-1)
exit(1);
sharem=shmat(shid,NULL,0);
if(sharem==NULL)
exit(1);
semctl(semid,0,SETVAL,1);
//初始化,使自己堵塞,等待輸入程序的輸入
while(running)
{
sem_b.sem_op=-1;
if(semop(semid,&sem_b,1)==-1)//同輸入程序
{
exit(1);
}
printf("read data operate\n");
printf("%s\n",sharem);
semctl(semid,0,SETVAL,0);//將輸入程序的訊號量置1
semctl(semid,1,SETVAL,1);//將自己堵塞
if(strcmp(sharem,"end")==0)
running--;
}
shmdt(sharem);
if(shmctl(shid,IPC_RMID,0)!=0)//銷燬共享記憶體
{
exit(1);
}
if(semctl(semid,0,IPC_RMID,0)!=0)//銷燬訊號量
{
exit(1);
}
return 0;
}