linux C学习笔记05--信号量与共享内存(进程同步)
花了半天时间把信号量与共享内存整合到了一起,先来看信号量代码,semaphore.c 当中sem_P()和sem_V()函数分别为信号量等待和信号量释放。
两个进程同时访问共享内存,为了避免发生同时读写产生不必要的错误,加入了信号量进行同步。对使用共享内存的区域加上互斥锁,同时只有一个进程能访问共享内存,时其他进程必须等待信号量资源释放后才能继续访问
/************************************************************************* > File Name: semaphore.c > Author: hailin.ma > Mail: mhl2018@126.com > Created Time: Thu 28 May 2015 09:29:35 AM CST ************************************************************************/ #include <stdio.h> #include <sys/ipc.h> #include <sys/types.h> #include <sys/shm.h> #include <errno.h> #include <sys/sem.h> #define SEM_KEY 27 union semun { int val; /* Value for SETVAL */ struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */ unsigned short *array; /* Array for GETALL, SETALL */ struct seminfo *__buf; /* Buffer for IPC_INFO (Linux-specific) */ }; int create_semaphore() { int semid; union semun sembuf; sembuf.val = 1; if((semid = semget(SEM_KEY,1, IPC_CREAT|IPC_EXCL|0666)) == -1) { if(errno == EEXIST) { semid = semget(SEM_KEY,0,0); if(semid == -1) { perror("semget"); return -1; } else { if (semctl(semid,0,SETVAL,sembuf) == -1) { perror("semctl"); return -1; } else { return semid; } } } else { perror("semget"); return -1; } } else { if (semctl(semid,0,SETVAL,sembuf) == -1) { perror("semctl"); return -1; } } return semid; } int delete_semaphore(int semid) { union semun sembuf; if(semctl(semid,0,IPC_RMID,sembuf) == -1) { perror("delete_semaphore"); return -1; } } int sem_P(int semid) { struct sembuf sbuf; sbuf.sem_num = 0; sbuf.sem_op = -1; sbuf.sem_flg = SEM_UNDO; if(semop(semid,&sbuf,1) == -1) { perror("sem_P"); return -1; } return 0; } int sem_V(int semid) { struct sembuf sbuf; sbuf.sem_num = 0; sbuf.sem_op = 1; sbuf.sem_flg = SEM_UNDO; if(semop(semid,&sbuf,1) == -1) { perror("sem_P"); return -1; } }
下面是共享内存代码:
/************************************************************************* > File Name: share_memory.c > Author: hailin.ma > Mail: mhl2018@126.com > Created Time: Wed 27 May 2015 11:19:26 PM CST ************************************************************************/ #include<stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/shm.h> #include <sys/ipc.h> #include <errno.h> #define SHARE_MEM_KEY 26 #define MEMORY_SIZE 1000 int create_shm(char **shmptr) { int shmid; //if((shmid = shmget(IPC_PRIVATE,200,IPC_CREAT|IPC_EXCL|0666)) == -1) if((shmid = shmget(SHARE_MEM_KEY,MEMORY_SIZE,IPC_CREAT|IPC_EXCL|0666)) == -1) { if(errno == EEXIST) { shmid = shmget(SHARE_MEM_KEY,0,0); if(shmid == -1) { perror("shmget"); return -1; } else { if((*shmptr = shmat(shmid,0,0666)) == (void*)-1) { perror("shmat"); return -1; } else { return shmid; } } } else { perror("shmget"); return -1; } } if((*shmptr = shmat(shmid,0,0)) == (void*)-1) { perror("shmat"); return -1; } return shmid; } int delete_shm(int shmid,char *shmptr) { shmdt(shmptr); if(shmctl(shmid,IPC_RMID,NULL) == -1) { perror("delete_shm"); return -1; } return 0; }
main函数代码:
#include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> extern int create_shm(char **shmptr); extern int create_semaphore(); extern int delete_semaphore(); extern int sem_P(int semid); extern int sem_V(int semid); extern int delete_shm(int shmid,char *shmptr); int main(int argc,char* argv[]) { int shmid; char *shmptr; int semid; if((shmid =create_shm(&shmptr)) == -1) { printf("create_shm error \n"); return -1; } if(argc > 1) { semid = *(int*)shmptr; //get semid from share memory //this is client while(1) { printf("input str to share memory:"); sem_P(semid); gets(shmptr); sem_V(semid); if(shmptr[0] == 'q') //quit { shmdt(shmptr); //disconnect to the share memory but will not dellect the memery break; } } } else { if((semid = create_semaphore()) == -1) { perror("main create_semaphore"); delete_shm(shmid,shmptr); return -1; } *(int*)shmptr = semid; printf("share memory is: %d \n",*(int*)shmptr); //this is server while(1) { sleep(2); sem_P(semid); printf("share memory is: %s \n",shmptr); sem_V(semid); if(shmptr[0] == 'q') { delete_shm(shmid,shmptr); delete_semaphore(semid); break; } } } printf("into sleeping\n"); sleep(3); printf("out sleeping\n"); return 0; }
运行效果图: