3、For Example
下面這個例子,使用了【共享內存+信號量+消息隊列】的組合來實現服務器進程與客戶進程間的通信。
- 共享內存用來傳遞數據;
- 信號量用來同步;
- 消息隊列用來 在客戶端修改了共享內存后 通知服務器讀取。
server.c
// 消息隊列結構
struct msg_form {
long mtype;
char mtext;
};
// 聯合體,用于semctl初始化
union semun
{
int val; /for SETVAL/
struct semid_ds buf;
unsigned short *array;
};
// 初始化信號量
int init_sem(int sem_id, int value)
{
union semun tmp;
tmp.val = value;
if(semctl(sem_id, 0, SETVAL, tmp) == -1)
{
perror("Init Semaphore Error");
return -1;
}
return 0;
}
// P操作:
// 若信號量值為1,獲取資源并將信號量值-1
// 若信號量值為0,進程掛起等待
int sem_p(int sem_id)
{
struct sembuf sbuf;
sbuf.sem_num = 0; /序號/
sbuf.sem_op = -1; /P操作/
sbuf.sem_flg = SEM_UNDO;
if(semop(sem_id, &sbuf, 1) == -1)
{
perror("P operation Error");
return -1;
}
return 0;
}
// V操作:
// 釋放資源并將信號量值+1
// 如果有進程正在掛起等待,則喚醒它們
int sem_v(int sem_id)
{
struct sembuf sbuf;
sbuf.sem_num = 0; /序號/
sbuf.sem_op = 1; /V操作/
sbuf.sem_flg = SEM_UNDO;
if(semop(sem_id, &sbuf, 1) == -1)
{
perror("V operation Error");
return -1;
}
return 0;
}
// 刪除信號量集
int del_sem(int sem_id)
{
union semun tmp;
if(semctl(sem_id, 0, IPC_RMID, tmp) == -1)
{
perror("Delete Semaphore Error");
return -1;
}
return 0;
}
// 創建一個信號量集
intcreat_sem(key_t key)
{
int sem_id;
if((sem_id = semget(key, 1, IPC_CREAT|0666)) == -1)
{
perror("semget error");
exit(-1);
}
init_sem(sem_id, 1); /初值設為1資源未占用/
return sem_id;
}
int main()
{
key_t key;
int shmid, semid, msqid;
char shm;
char data[] = "this is server";
struct shmid_ds buf1; /用于刪除共享內存/
struct msqid_ds buf2; /用于刪除消息隊列/
struct msg_form msg; /消息隊列用于通知對方更新了共享內存/
// 獲取key值
if((key = ftok(".", 'z')) < 0)
{
perror("ftok error");
exit(1);
}
// 創建共享內存
if((shmid = shmget(key, 1024, IPC_CREAT|0666)) == -1)
{
perror("Create Shared Memory Error");
exit(1);
}
// 連接共享內存
shm = (char*)shmat(shmid, 0, 0);
if((int)shm == -1)
{
perror("Attach Shared Memory Error");
exit(1);
}
// 創建消息隊列
if ((msqid = msgget(key, IPC_CREAT|0777)) == -1)
{
perror("msgget error");
exit(1);
}
// 創建信號量
semid = creat_sem(key);
// 讀數據
while(1)
{
msgrcv(msqid, &msg, 1, 888, 0); /讀取類型為888的消息/
if(msg.mtext == 'q') /quit - 跳出循環/
break;
if(msg.mtext == 'r') /read - 讀共享內存/
{
sem_p(semid);
printf("%s\\n",shm);
sem_v(semid);
}
}
// 斷開連接
shmdt(shm);
/刪除共享內存、消息隊列、信號量/
shmctl(shmid, IPC_RMID, &buf1);
msgctl(msqid, IPC_RMID, &buf2);
del_sem(semid);
return 0;
}
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。
舉報投訴
-
Linux
+關注
關注
87文章
11292瀏覽量
209332 -
IPC
+關注
關注
3文章
346瀏覽量
51902 -
進程間通信
+關注
關注
0文章
16瀏覽量
2434
發布評論請先 登錄
相關推薦
Linux現有的所有進程間IPC方式
在開始回答前,先簡單概括性地說說Linux現有的所有進程間IPC方式:1. **管道:**在創建時分配一個page大小的內存,緩存區大小比較有限;2. 消息隊列:信息復制兩次,額外的C
發表于 08-20 06:17
Linux進程間的五種通信方式介紹 3
進程間通信(IPC,InterProcess Communication)是指在不同進程之間傳播或交換信息。IPC的方式通常有管道(包括無名
Linux進程間的五種通信方式介紹 4
進程間通信(IPC,InterProcess Communication)是指在不同進程之間傳播或交換信息。IPC的方式通常有管道(包括無名
Linux進程間的五種通信方式介紹 6
進程間通信(IPC,InterProcess Communication)是指在不同進程之間傳播或交換信息。IPC的方式通常有管道(包括無名
評論