Chinaunix首页 | 论坛 | 博客
  • 博客访问: 7688809
  • 博文数量: 961
  • 博客积分: 15795
  • 博客等级: 上将
  • 技术积分: 16612
  • 用 户 组: 普通用户
  • 注册时间: 2010-08-07 14:23
文章分类

全部博文(961)

文章存档

2016年(1)

2015年(61)

2014年(41)

2013年(51)

2012年(235)

2011年(391)

2010年(181)

分类: C/C++

2011-06-17 21:11:12

  1. /*
  2.  * 共享内存
  3.  * 创建共享内存
  4.  * Lzy 2011-6-16
  5.  */

  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <sys/ipc.h>
  9. #include <sys/shm.h>

  10. int main(void)
  11. {
  12.     int shmid;        //保存共享内存ID
  13.     key_t key;        //共享内存键值
  14.     
  15.     key = ftok("main", 1);    //获取键值
  16.     if(key < 0)
  17.     {
  18.         perror("ftok");
  19.         exit(0);
  20.     }
  21.     
  22.     shmid = shmget(key, 10, IPC_CREAT | 0666);    //获取共享内存ID
  23.     if(shmid < 0)
  24.     {
  25.         perror("shmget");
  26.         exit(0);
  27.     }
  28.     
  29.     return 0;
  30. }
  1. /*
  2.  * 共享内存
  3.  * 信号量控制共享内存的同步,实现父子进程通信,
  4.  * 思路:
  5.      第一步,创建信号量,映像共享内存
  6.     第二步,创建子进程,让子进程继承父进程所有上下文
  7.     第三步,父进程睡眠一秒,让子进程获得CPU时间
  8.     第四步,子进程运行,立刻进行P操作
  9.     第五步,子进程睡眠4秒,主动放弃CPU
  10.     第六步,父进程获得CPU,但信号量已为0,无法进行P操作,只能继续打酱油,父进程被阻塞
  11.     第七步,子进程接着运行,最后释放共享内存,进行V操作,
  12.     第八步,父进程被换醒,获得信号锁,运行,最后,删除共享内存,退出程序    
  13.  * Lzy 2011-6-16
  14.  */

  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <sys/ipc.h>
  18. #include <sys/shm.h>
  19. #include <sys/types.h>
  20. #include <unistd.h>
  21. #include <string.h>
  22. #include <sys/sem.h>

  23. #define SHM_SIZE 1024    //共享内存的大小

  24. int main(void)
  25. {
  26.     int ret,        //临时变量
  27.      pid,        //进程id
  28.      sme_id,        //保存信号量描述符
  29.      shm_id;        //保存共享内存描述符
  30.     
  31.     key_t     sme_key,    //保存信号量键值
  32.         shm_key;    //保存共享内存键值

  33.     char *shmp;        //指向共享内存的首地址
  34.     struct shmid_ds dsbuf;    //定义共享内存信息结构变量

  35.     struct sembuf lock = {0, -1, SEM_UNDO};        //信号量上锁操作的数组指针
  36.     struct sembuf unlock = {0, 1, SEM_UNDO | IPC_NOWAIT};//信号量解锁操作的数组指针

  37.     shm_key = ftok("main", 2);    //获取信号量键值
  38.     if(shm_key < 0)
  39.     {
  40.         perror("ftok");
  41.         exit(0);
  42.     }

  43.     sme_id = semget(shm_key, 1, IPC_CREAT | 0666);    //获取信号量ID
  44.     if(sme_id < 0)
  45.     {
  46.         perror("semget");
  47.         exit(0);
  48.     }

  49.     shm_key = ftok("main", 1);    //获取共享内存键值
  50.     if(shm_key < 0)
  51.     {
  52.         perror("ftok");
  53.         exit(0);
  54.     }
  55.     
  56.     shm_id = shmget(shm_key, SHM_SIZE, IPC_CREAT | 0666);        //获取共享内存ID
  57.     if(shm_id < 0)
  58.     {
  59.         perror("shmget");
  60.         exit(0);
  61.     }

  62.     shmp = shmat(shm_id, NULL, 0);        //映像共享内存
  63.     if((int)shmp == -1)
  64.     {
  65.         perror("shmat");
  66.         exit(0);
  67.     }

  68.     pid = fork();            //创建子进程
  69.     if(pid < 0)
  70.     {
  71.         perror("fork");
  72.         exit(0);
  73.     }
  74.     else if(pid == 0)        //子进程
  75.     {
  76.         ret = semctl(sme_id, 0, SETVAL, 1);        //初始化信号量,初值设为1
  77.         if(ret == -1)
  78.         {
  79.             perror("semctl");
  80.             exit(0);
  81.         }
  82.         
  83.         ret = semop(sme_id, &lock, 1);        //申请访问共享资源,锁定临界资源
  84.         if(ret == -1)
  85.         {
  86.             perror("semop lock");
  87.             exit(0);
  88.         }
  89.         sleep(4);            //让子进程睡眠4秒
  90.         strcpy(shmp, "hello\n");    //往共享内存写入数据
  91.     
  92.         if(shmdt((void *)shmp) < 0)    //使共享内存脱离进程地址空间
  93.         {
  94.             perror("shmdt");            
  95.         }
  96.         
  97.         ret = semop(sme_id, &unlock, 1);        //解锁临界资源
  98.         if(ret == -1)
  99.         {
  100.             perror("semop unlock");
  101.             exit(0);
  102.         }
  103.     }
  104.     else                //父进程
  105.     {
  106.         sleep(1);        //先让子进程运行
  107.         ret = semop(sme_id, &lock, 1);        //申请访问共享资源,锁定临界资源
  108.         if(ret == -1)
  109.         {
  110.             perror("semop lock");
  111.             exit(0);
  112.         }

  113.         if(shmctl(shm_id, IPC_STAT, &dsbuf) < 0)    //获取共享内存信息
  114.         {
  115.             perror("shmctl");
  116.             exit(0);
  117.         }
  118.         else            /* 共享内存的状态信息获取成功 */
  119.         {
  120.              printf("Shared Memory Information:\n");
  121.                  printf("\tCreator PID: %d\n", dsbuf.shm_cpid);         /* 输出创建共享内存进程的标识符 */
  122.                  printf("\tSize(bytes): %d\n",dsbuf.shm_segsz);         /* 输出共享内存的大小 */
  123.                  printf("\tLast Operator PID: %d\n",dsbuf.shm_lpid);     /* 输出上一次操作共享内存进程的标识符 */
  124.               printf("Received message : %s\n", (char *)shmp);        /* 从共享内存中读取数据 */
  125.         }

  126.         if(shmdt((void *)shmp) < 0)    //使共享内存脱离进程地址空间
  127.         {
  128.             perror("shmdt");
  129.             exit(0);            
  130.         }        
  131.         
  132.         ret = semop(sme_id, &unlock, 1);        //解锁临界资源
  133.         if(ret == -1)
  134.         {
  135.             perror("semop unlock");
  136.             exit(0);
  137.         }

  138.         if(shmctl(shm_id, IPC_RMID, NULL) < 0)    /* 删除前面创建的共享内存 */
  139.         {
  140.             perror("shmctl");
  141.             exit(0);            
  142.         }

  143.         ret = semctl(sme_id, 0, IPC_RMID, NULL);    //删除信号量
  144.         if(ret == -1)
  145.         {        
  146.             perror("semctl");
  147.             exit(0);        
  148.         }
  149.     }    
  150.     
  151.     return 0;
  152. }
阅读(1580) | 评论(0) | 转发(2) |
0

上一篇:队列

下一篇:管道

给主人留下些什么吧!~~