信號量:通過設置一個值val大於0的整數,表示當前最多允許val個進程進入臨界區。同時定義P函數,函數中對val進行減1操作,每當一個進程進入臨界區時執行一次P函數,當val爲0時當前進程等待。定義V函數,對val進行加1操作,當一個進程離開臨界區執行V函數。
結構如下:
P();
//臨界區
V();
linux下封裝了對信號量的操作函數semget semop semctl需要引用頭文件#include <sys/sem.h>
有些情況下可能會用到頭文件sys/types.t和sys/ipc.h
semid = semget((key_t)1234,1,IPC_CREAT|0666);1表示創建信號量集中信號量的個數,常用1。
sem_union.val = 1;//設置信號量的值爲1,sem_union位聯合體自己定義
semctl(semid,0,SETVAL,sem_union);0爲常用,SETVAL表示設置信號量的值。
struct sembuf sem_b;
sem_b.sem_num = 0;//常用
sem_b.sem_op = 1;//1爲V操作 -1爲P操作
sem_b.sem_flg = SEM_UNDO;//常用
semop(semid,&sem_b,1);//1表示參數2表示的數組元素個數
共享內存用於多個進程之間互相通信。linux封裝以下函數進行操作。
shmget shmat shmdt shmctl
其中shmget((key_t)1234,1024,IPC_CREAT|0666),1024表示共享內存空間大小,IPC_CREAT|0666表示訪問權限和不存在就創建。
刪除共享內存空間:shmctl(shmid,IPC_RMID,NULL);shmid爲shmget的返回值。
使用共享內存之前需要將共享內存附加到進程的內存空間:shmat(shmid,NULL,0)表示由系統決定附加到的空間位置,不推薦自己指定。shmat返回一個void指針類型,可以強制轉化成其他數據類型,用來進行數據傳遞。如int *data = shmat();
當不使用該共享內存時,需要將它與進行分離。shmdt(data);將shmat的指針傳進來即可。
需要頭文件<sys/shm.h>
接下來給出兩段代碼綜合使用了信號量和共享內存。這兩段代碼大同小異。在semc1.c中將共享內存的值改爲1,在semc2.c中輸出共享值,並將共享值改爲2。分別睡眠不同時間。
//semc1.c
#include <stdio.h>
#include <unistd.h>
#include <sys/sem.h>
#include <sys/shm.h>
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
};
int sem_p();
int sem_v();
int semid;
int main(int argc,char *argv[])
{
int flag,i,shmid,*shmdata;
key_t key;
union semun sem_union;
flag = IPC_CREAT|0666;
key = ftok(".",'a');
if(key == -1)
return -1;
semid = semget(key,1,flag);//cluster contain 1 sem
if(semid == -1)
return -1;
shmid = shmget(key,1024,flag);
shmdata = (int *)shmat(shmid,NULL,0);
sem_union.val = 1;
semctl(semid,0,SETVAL,sem_union);
for(i=0;i<10;i++)
{
if(!sem_p())
return -1;
*shmdata = 1;
if(!sem_v())
return -1;
sleep(2);
}
shmdt(shmdata);
shmctl(shmid,IPC_RMID,NULL);
semctl(semid,0,IPC_RMID,sem_union);
return 0;
}
int sem_p()
{
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = -1;
sem_b.sem_flg = SEM_UNDO;
if(semop(semid,&sem_b,1)==-1)
return 0;
return 1;
}
int sem_v()
{
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = 1;
sem_b.sem_flg = SEM_UNDO;
if(semop(semid,&sem_b,1)==-1)
return 0;
return 1;
}
//semc2.c
#include <stdio.h>
#include <unistd.h>
#include <sys/sem.h>
#include <sys/shm.h>
int sem_p();
int sem_v();
int semid;
int main(int argc,char *argv[])
{
int flag,i,shmid,*shmdata;
key_t key;
flag = IPC_CREAT|0666;
key = ftok(".",'a');
if(key == -1)
return -1;
semid = semget(key,1,flag);//cluster contain 1 sem
if(semid == -1)
return -1;
shmid = shmget(key,1024,flag);
shmdata = (int *)shmat(shmid,NULL,0);
for(i=0;i<10;i++)
{
if(!sem_p())
return -1;
printf("%d",*shmdata);
*shmdata = 2;
if(!sem_v())
return -1;
usleep(1500000);
}
shmdt(shmdata);
return 0;
}
int sem_p()
{
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = -1;
sem_b.sem_flg = SEM_UNDO;
if(semop(semid,&sem_b,1)==-1)
return 0;
return 1;
}
int sem_v()
{
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = 1;
sem_b.sem_flg = SEM_UNDO;
if(semop(semid,&sem_b,1)==-1)
return 0;
return 1;
}
運行結果應該是1和2混合出現。