信号量实例—同步

//reader_writer.c

//reader_writer.c

#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
#include <error.h>
#include <stdlib.h>
#include <wait.h>
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/sem.h>

/*
功能:写者写完通知读者读取
      读者读完通知写者再写
      共享资源为共享内存
*/

typedef struct{
    int value;
    int semid;
}Storage;

union semun{
    int val;
    struct semid_ds *buf;
    unsigned short *array;
};

/*
struct sembuf{
    unsigned short sem_num;//信号量集中信号量的编号(即哪个信号量),0代表第1个信号量
    short sem_op;
    short sem_flg;
}
*/
void writer(Storage *s)
{
    int i = 0;
    //int semop(int semid, struct sembuf *sops, unsigned nsops)
    struct sembuf v_s1 = {0, 1, SEM_UNDO};
    struct sembuf p_s2 = {1, -1, SEM_UNDO};
    for(; i < 10; i++){
        s->value = i;
        printf("writer write %d from sharememery\n",s->value);
        sleep(1);
        semop(s->semid, &v_s1, 1);
        semop(s->semid, &p_s2, 1);
    }
    return ;
}

void reader(Storage *s)
{
    int i = 0;
    struct sembuf p_s1 = {0, -1, SEM_UNDO};
    struct sembuf v_s2 = {1, 1, SEM_UNDO};
    for(; i < 10; i++){
        semop(s->semid, &p_s1, 1);
        s->value = i;
        printf("reader read %d from sharememery\n",s->value);
        sleep(1);
        semop(s->semid, &v_s2, 1);
    }
    return ;
}

int main()
{
    //int shmget(key_t key, size_t size, int shmflg);
    key_t key = ftok("/etc/passwd",1);
    int shmid = shmget(key, sizeof(Storage), IPC_CREAT | IPC_EXCL | 0664);
    if(shmid < 0){
        perror("shmget failed");
    }
    
    //void *shmat(int shmid, const void *shmaddr, int shmflg);
    Storage *s = (Storage *)shmat(shmid, 0, 0);
    if(s == (Storage *)-1){
        perror("shmat failed");
    }
    
    s->value = 0;
    //int semget(key_t key, int nsems, int semflg) 创建信号量集,nsems表示有多少个信号量
    s->semid = semget(key, 2, IPC_CREAT | IPC_EXCL | 0664); 
    if(s->semid < 0){
        perror("semget failed");
    }
    //int semctl(int semid,int semnum,int cmd,.../*union semun arg*/)初始化信号量集,semnum = 0:表示全部的信号量
    union semun un;
    un.array[0] = 0;
    un.array[1] = 0;//给两个信号量赋初值为0
    if(semctl(s->semid, 0, SETALL, un) < 0){
        perror("semctl failed");
    }
    
    pid_t pid = fork();
    if(pid < 0){
        perror("fork failed");
    }else if(pid == 0){//child process  writer
        writer(s);
        //解除共享内存
        if(shmdt(s) < 0){
            perror("shmdtc failed");
        }
    }else{//father process  reader
        reader(s);
        wait(NULL);
        //删除信号量集
        if(semctl(s->semid, 0, IPC_RMID, NULL) < 0){
            perror("semctl rm failed");
        }
        //解除共享内存映射
        if(shmdt(s) < 0){
            perror("shmdtf failed");
        }
        //删除共享内存
        if(shmctl(shmid, IPC_RMID, 0) < 0){
            perror("shmctl failed");
        }
    }

    return 0;
}

 

posted @ 2023-03-30 10:32  踏浪而来的人  阅读(25)  评论(0编辑  收藏  举报