当我们使用共享内存时,必然要面对一个问题:并发。信号量可以控制共享资源的申请和释放,起到锁的目的,有效的解决了并发带来的种种问题。
共享内存的使用见《linux下C语言编程4-使用共享内存实现进程间通信2》。
信号量的函数见《linux下C语言编程6-信号量函数semget() semop() semctl() 》。
下面给出一个例子:
服务端:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#define SEGSIZE 1024
// 生成信号量
int sem_create(key_t key)
{
int semid;
semid = semget(key, 250, IPC_CREAT|0666);
if (semid == -1)
{
printf("create semaphore error/n");
exit(0);
}
semctl(semid,0,SETVAL);
return semid;
}
//删除信号量
void del_sem(int semid)
{
semctl(semid,0,IPC_RMID);
}
//p
int p(int semid) {
/*
sembuf第2个参数sem_op:
如果其值为正数,该值会加到现有的信号内含值中。通常用于释放所控资源的使用权;
如果sem_op的值为负数,而其绝对值又大于信号的现值,操作将会阻塞,直到信号值大于或等于sem_op的绝对值。通常用于获取资源的使用权;
如果sem_op的值为0,则操作将暂时阻塞,直到信号的值变为0。
*/
struct sembuf sops = {1,-1,SEM_UNDO}; // sops数组大小为1
return semop(semid,&sops,1);
}
//v
int v(int semid) {
struct sembuf sops = {1,+1,SEM_UNDO};
return semop(semid,&sops,1);
}
int main()
{
key_t key;
int shmid,semid;
char *shm;
char msg[32] = "xiaoshe-";
char i;
struct semid_ds buf;
key = ftok("/",0);
shmid = shmget(key,SEGSIZE,IPC_CREAT|0604);
if (-1 == shmid){
printf(" create shared memory error/n");
return -1;
}
printf("shmid = %d/n", shmid);
shm = (char *)shmat(shmid, 0, 0);
if (-1 == (int)shm){
printf(" attach shared memory error/n");
return -1;
}
semid = sem_create(key);
printf("semid = %d/n", semid);
for (i=0; i<3; i++)
{
sleep(2);
p(semid);
printf("[%d] p ", i);fflush(stdout);
sleep(1);
// 修改共享内存
msg[8] = '0' + i;
memcpy(shm, msg, 32);
printf("-> wirte ");fflush(stdout);
sleep(3);
v(semid);
printf("-> v/n");
}
shmdt(shm);
shmctl(shmid,IPC_RMID,&buf);
del_sem(semid);
return 0;
//gcc -o s s.c -g
}
客户端:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/sem.h>
#include <time.h>
#include <sys/ipc.h>
#define SEGSIZE 1024
//创建信号量
int get_sem(key_t key)
{
int semid;
semid = semget(key,20,0);
if (-1 == semid){
printf("create semaphore error/n");
exit(1);
}
return semid;
}
//等待信号量变成0
void wait_v(int semid)
{
struct sembuf sops={1,0,0};
semop(semid,&sops,1);
}
int main(void)
{
key_t key;
int shmid, semid;
char *shm;
char msg[100];
char i;
key = ftok("/",0);
shmid = shmget(key,SEGSIZE,0);
if(-1 == shmid)
{
printf(" create shared memory error/n");
return -1;
}
shm = (char *)shmat(shmid,0,0);
if (-1 == (int)shm){
printf(" attach shared memory error/n");
return -1;
}
semid = get_sem(key);
printf("semid = %d/n", semid);
for (i=0; i<4; i++)
{
sleep(1);
wait_v(semid);
printf("[%d] msg = '%s'/n", i, shm);
}
shmdt(shm);
return 0;
// gcc -o c c.c
}