IPC_EXCL        只有在共享内存不存在的时候,新的共享内存才建立,否则就产生错误

例子一:假设键值为key,创建一个共享内存大小为4k,访问权限为066,如果已经存在则返回其标识号 
int shmid;
if( (shmid = shmget(key,4 * 1024,0666 | IPC_CREAT)) < 0)
{
    perror("Fail to shmget");
    exit(EXIT_FAILURE)
}
例子二、假设键值为key,创建一个共享内存大小为1k,访问权限为0666,如果已经存在则报错
int shmid;
if((shmid  = shmget(key,1024,0666 | IPC_CREAT | IPC_EXCL)) < 0)
{
    perror("Fail to shmget");
    exit(EXIT_FAILURE);
}
B.共享内存的映射

函数shmat将标识号为shmid共享内存映射到调用进程的地址空间中。
参数说明:
shmid  :  要映射的共享内存区标识符
shmaddr  :  将共享内存映射到指定地址(若为NULL,则表示由系统自动完成映射)
shmflg  :  SHM_RDONLY  共享内存只读
                默认0:共享内存可读写。
返回值 :调用成功放回映射后的地址 ,出错放回(void *)-1;
C.取消共享内存与用户进程之间的映射

参数shmaddr是shmat映射成功放回的地址。
注意:当一个进程不再需要共享内存段时,它将调用shmdt()系统调用取消这个段,但是,这并不是从内核真正地删除这个段,而是把相关shmid_ds结构的shm_nattch域的值减1,当这个值为0时,内核才从物理上删除这个共享段。
D.控制共享内存

参数说明:
shmid  共享内存标识ID
cmd      IPC_STAT得到共享内存的状态
              IPC_SET改变共享内存的状态
              IPC_RMID删除共享内存
buf  是一个结构体指针。IPC_STAT的时候,取得的状态放在这个结构体中。如果要改变共享内存的状态,用这个结构体指定;

注意:
1.IPC_RMID命令实际上不从内核删除一个段,而是仅仅把这个段标记为删除,实际的删除发生最后一个进程离开这个共享段时。
2.当cmd为IPC_RMID时,第三个参数应为NULL。呵呵,大部分我们都是这样做,用这个函数删除共享内存。
案例探究:
- #include <sys/shm.h>
 - #include <stdio.h>
 - #include <stdlib.h>
 - #include <string.h>
 - #include <semaphore.h>
 - #include <fcntl.h>
 - #include <sys/stat.h>
 
- #define BUFF_SIZE 1024
 
- int father_do_work(int shmid)
 - {
 -     char *buf;
 -     void *shmaddr;
 -     sem_t *prsem;
 -     sem_t *pwsem;
 
-     //有名信号量
 -     if((prsem = sem_open("rsem",O_CREAT,0666,0)) == SEM_FAILED)
 -     {
 -         perror("Fail to sem open");
 -         return -1;
 -     }
 -         
 -         //有名信号量
 -     if((pwsem = sem_open("wsem",O_CREAT,0666,1)) == SEM_FAILED)
 -     {
 -         perror("Fail to sem open");
 -         return -1;
 -     }
 
-     //映射共享内存
 -     if((shmaddr = shmat(shmid,NULL,0)) == (void *)-1)
 -     {
 -         perror("Fail to shmat");
 -         exit(EXIT_FAILURE);
 -     }
 
-     buf = (char *)shmaddr;
 
-     while(1)
 -     {
 -         if(sem_wait(pwsem) < 0)
 -         {
 -             perror("Fail to sem wait");
 -             break;
 -         }
 
-         printf(">");
 -         fgets(buf,BUFF_SIZE,stdin);
 -         buf[strlen(buf) - 1] = ‘\0‘;
 -         
 -         if(sem_post(prsem) < 0)
 -         {
 -             perror("Fail to sem post");
 -             break;
 -         }
 -         
 -         if(strncmp(buf,"quit",4) == 0)
 -         {
 -             if(shmdt(shmaddr) < 0)
 -             {
 -                 perror("Fail to shmaddr");
 -                 exit(EXIT_FAILURE);
 -             }
 
-             break;
 -         }
 -     
 -         usleep(500);
 -     }
 -     
 -     return 0;
 - }
 
- int child_do_work(int shmid)
 - {
 -     char *buf;
 -     void *shmaddr;
 -     sem_t *prsem;
 -     sem_t *pwsem;
 
-     //
 -     if((prsem = sem_open("rsem",O_CREAT,0666,0)) == SEM_FAILED)
 -     {
 -         perror("Fail to sem open");
 -         return -1;
 -     }
 
-     if((pwsem = sem_open("wsem",O_CREAT,0666,1)) == SEM_FAILED)
 -     {
 -         perror("Fail to sem open");
 -         return -1;
 -     }
 
-     //映射共享内存
 -     if((shmaddr = shmat(shmid,NULL,0)) == (void *)-1)
 -     {
 -         perror("Fail to shmat");
 -         exit(EXIT_FAILURE);
 -     }
 
-     buf = (char *)shmaddr;
 
-     while(1)
 -     {
 -         if(sem_wait(prsem) < 0)
 -         {
 -             perror("Fail to prsem");
 -             break;
 -         }
 
-         printf("read buf : %s.\n",buf);
 
-         if(sem_post(pwsem) < 0)
 -         {
 -             perror("Fail to pwsem");
 -             break;
 -         }
 
-         if(strncmp(buf,"quit",4) == 0)
 -         {
 -             if(shmdt(shmaddr) < 0)
 -             {
 -                 perror("Fail to shmaddr");
 -                 exit(EXIT_FAILURE);
 -             }
 
-             break;
 -         }
 -     }
 -     
 -     return 0;
 - }
 
- int main()
 - {
 -     int shmid;
 -     int pid;
 -     void *shmaddr;
 -     
 -     //创建共享内存
 -     if((shmid = shmget(IPC_PRIVATE,BUFF_SIZE,0666 | IPC_CREAT)) < 0)
 -     {
 -         perror("Fail to shmget");
 -         exit(EXIT_FAILURE);
 -     }
 
-     if((pid = fork()) < 0)
 -     {
 
-         perror("Fail to fork");
 -         exit(EXIT_FAILURE);
 -     
 -     }else if(pid == 0){
 -     
 -         child_do_work(shmid);
 -     
 -     }else{
 -         
 -         father_do_work(shmid);
 -         wait(NULL);
 
-         if(shmctl(shmid,IPC_RMID,NULL) < 0)
 -         {
 -             perror("Fail to shmctl");
 -             exit(EXIT_FAILURE);
 -         }
 -     }
 
-     exit(EXIT_SUCCESS);
 - }
 
 运行结果:
