信号量集控制控制进程读写共享内存

信号量集控制控制进程读写共享内存

#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。

猜你喜欢

转载自blog.csdn.net/NeverWA/article/details/80719033