3、For Example
// 聯(lián)合體,用于semctl初始化
union semun
{
int val; /for SETVAL/
struct semid_ds buf;
unsigned short *array;
};
// 初始化信號(hào)量
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操作:
// 若信號(hào)量值為1,獲取資源并將信號(hào)量值-1
// 若信號(hào)量值為0,進(jìn)程掛起等待
int sem_p(int sem_id)
{
struct sembuf sbuf;
sbuf.sem_num = 0; /序號(hào)/
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操作:
// 釋放資源并將信號(hào)量值+1
// 如果有進(jìn)程正在掛起等待,則喚醒它們
int sem_v(int sem_id)
{
struct sembuf sbuf;
sbuf.sem_num = 0; /序號(hào)/
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;
}
// 刪除信號(hào)量集
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;
}
int main()
{
int sem_id; // 信號(hào)量集ID
key_t key;
pid_t pid;
// 獲取key值
if((key = ftok(".", 'z')) < 0)
{
perror("ftok error");
exit(1);
}
// 創(chuàng)建信號(hào)量集,其中只有一個(gè)信號(hào)量
if((sem_id = semget(key, 1, IPC_CREAT|0666)) == -1)
{
perror("semget error");
exit(1);
}
// 初始化:初值設(shè)為0資源被占用
init_sem(sem_id, 0);
if((pid = fork()) == -1)
perror("Fork Error");
else if(pid == 0) /子進(jìn)程/
{
sleep(2);
printf("Process child: pid=%d\\n", getpid());
sem_v(sem_id); /釋放資源/
}
else /父進(jìn)程/
{
sem_p(sem_id); /等待資源/
printf("Process father: pid=%d\\n", getpid());
sem_v(sem_id); /釋放資源/
del_sem(sem_id); /刪除信號(hào)量集/
}
return 0;
}
上面的例子如果不加信號(hào)量,則父進(jìn)程會(huì)先執(zhí)行完畢。這里加了信號(hào)量讓父進(jìn)程等待子進(jìn)程執(zhí)行完以后再執(zhí)行。
五、共享內(nèi)存
共享內(nèi)存(Shared Memory),指兩個(gè)或多個(gè)進(jìn)程共享一個(gè)給定的存儲(chǔ)區(qū)。
1、特點(diǎn)
- 共享內(nèi)存是最快的一種 IPC,因?yàn)檫M(jìn)程是直接對(duì)內(nèi)存進(jìn)行存取。
- 因?yàn)槎鄠€(gè)進(jìn)程可以同時(shí)操作,所以需要進(jìn)行同步。
- 信號(hào)量+共享內(nèi)存通常結(jié)合在一起使用,信號(hào)量用來(lái)同步對(duì)共享內(nèi)存的訪問。
2、原型
// 創(chuàng)建或獲取一個(gè)共享內(nèi)存:成功返回共享內(nèi)存ID,失敗返回-1
intshmget(key_t key, size_t size, int flag);
// 連接共享內(nèi)存到當(dāng)前進(jìn)程的地址空間:成功返回指向共享內(nèi)存的指針,失敗返回-1
voidshmat(int shm_id, constvoid *addr, int flag);
// 斷開與共享內(nèi)存的連接:成功返回0,失敗返回-1
intshmdt(void addr);
// 控制共享內(nèi)存的相關(guān)信息:成功返回0,失敗返回-1
intshmctl(int shm_id, int cmd, struct shmid_ds *buf);
當(dāng)用shmget函數(shù)創(chuàng)建一段共享內(nèi)存時(shí),必須指定其size;而如果引用一個(gè)已存在的共享內(nèi)存,則將size指定為0 。
當(dāng)一段共享內(nèi)存被創(chuàng)建以后,它并不能被任何進(jìn)程訪問。必須使用shmat函數(shù)連接該共享內(nèi)存到當(dāng)前進(jìn)程的地址空間,連接成功后把共享內(nèi)存區(qū)對(duì)象映射到調(diào)用進(jìn)程的地址空間,隨后可像本地空間一樣訪問。
shmdt函數(shù)是用來(lái)斷開shmat建立的連接的。注意,這并不是從系統(tǒng)中刪除該共享內(nèi)存,只是當(dāng)前進(jìn)程不能再訪問該共享內(nèi)存而已。
shmctl函數(shù)可以對(duì)共享內(nèi)存執(zhí)行多種操作,根據(jù)參數(shù) cmd 執(zhí)行相應(yīng)的操作。常用的是IPC_RMID(從系統(tǒng)中刪除該共享內(nèi)存)。
-
Linux
+關(guān)注
關(guān)注
87文章
11304瀏覽量
209543 -
IPC
+關(guān)注
關(guān)注
3文章
347瀏覽量
51921 -
進(jìn)程間通信
+關(guān)注
關(guān)注
0文章
16瀏覽量
2434
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論