您的位置:首页 > 其它

进程通信之共享内存与信号量

2016-04-30 14:41 405 查看
信号量:通过设置一个值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混合出现。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息