信号量集控制控制进程读写共享内存
#include<stdio.h>
#include<sys/sem.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<unistd.h>
#include<string.h>
union semun
{
int val;
};
int main()
{
pid_t pid = 0;
key_t key = ftok("sem_and_shm.c", 1); //以当前文件名为引子获得唯一的键值
int shmid = shmget(key, sizeof(int), IPC_CREAT|0640); //创建共享内存
int semid = semget(key, 1, IPC_CREAT|0644); 创建信号量集
union semun su;
su.val = 0; //设置信号量中信号的初值
if(semctl(semid, 0, SETVAL, su) == -1) //把初值赋给信号量集中的semid号信号
perror("semctl");
struct sembuf v[1] = {{0, 1, 0}}; //设置semop操作所需的结构体(加一操作)
struct sembuf p[1] = {{0, -1, 0}}; //设置semop操作所需的结构体(减一操作)
if((pid = fork()) == 0) //创建子进程
{
char *chp = (char *)shmat(shmid, NULL, 0); //子进程将共享内存映射进自己的虚拟地址空间
while(1)
{
semop(semid, p, 1); //子进程从共享内存中读数据,在读之前进行一次P操作
printf("读取。。。");
printf("%s\n", chp);
}
}
else if(pid > 0)
{
char *pap = (char *)shmat(shmid, NULL, 0); //父进程将共享内存映射进自己的虚拟地址空间
while(1)
{ //父进程不断地往共享内存中写数据,在每次写完后都进行一次V操作
sleep(1);
memset(pap, 0, sizeof(pap));
printf("写入。。\n");
sprintf(pap, "a");
}
}
else
perror("fork");
return 0;
}
SEM_UNDO
struct sembuf{
int sem_num; //第几个信号量
int sem_op; //P -1, v +1
int sem_flag; //0006
};
当操作信号量(semop)时,semop函数中第二个参数struct sembuf中,sem_flg可以设置SEM_UNDO标识;SEM_UNDO用于将修改的信号量值在进程正常退出(调用exit退出或main执行完)或异常退出(如段异常、除0异常、收到KILL信号等)时归还给信号量。
如信号量初始值是20,进程以SEM_UNDO方式操作信号量减2,减5,加1;在进程未退出时,信号量变成20-2-5+1=14;在进程退出时,将修改的值归还给信号量,信号量变成14+2+5-1=20。