信号量实例—同步
//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; }