Chinaunix首页 | 论坛 | 博客
  • 博客访问: 268828
  • 博文数量: 84
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 927
  • 用 户 组: 普通用户
  • 注册时间: 2015-03-06 23:00
个人简介

growing

文章分类

全部博文(84)

文章存档

2017年(6)

2016年(61)

2015年(17)

我的朋友

分类: LINUX

2016-07-06 14:14:33

一、消息队列

特点:
1.相对管道来说接口使用较为复杂
2.生命周期:随内核
3.为数据块服务(管道是字节流)
4.长度会受到一定限制

ipcs - q 查看消息队列资源
ipcrm -q +key/msgid 删除消息队列资源

来看使用例子:

实现功能的文件:
  1. #include"common.h"

  2. static int com_creat_queue(int flags)
  3. {
  4.     key_t key = ftok(_PATH_,_PROJ_ID_);
  5.     if(key < 0){
  6.         printf("%d:%s\n",errno,strerror(errno));
  7.         return -1;
  8.     }
  9.     int msg_id = msgget(key,flags);
  10.     if(msg_id < 0){
  11.         printf("%d:%s\n",errno,strerror(errno));
  12.         return -2;
  13.     }
  14.     return msg_id;
  15. }

  16. int creat_queue()
  17. {
  18.     int flags = IPC_CREAT|IPC_EXCL|0666;
  19.     return com_creat_queue(flags);
  20. }

  21. int get_queue()
  22. {
  23.     int flags = IPC_CREAT;
  24.     return com_creat_queue(flags);
  25. }

  26. int send_msg(int msg_id,int who,char *msg)
  27. {
  28.     struct msgbuf _buf;
  29.     memset(&_buf,'\0',sizeof(_buf));
  30.     _buf.mtype = who;
  31.     strncpy(_buf.mtext,msg,sizeof(msg)+1);
  32.     printf("say : %s\n",msg);
  33.     return msgsnd(msg_id,&_buf,sizeof(_buf.mtext),0);
  34. }
  35. int recv_msg(int msg_id,int want,char out[],int out_len)
  36. {
  37.     struct msgbuf _buf;
  38.     memset(&_buf,'\0',sizeof(_buf));
  39.     int ret = msgrcv(msg_id,&_buf,sizeof(_buf.mtext),want,0);
  40.     if(ret <= -1)
  41.     {
  42.         printf("%d:%s\n",errno,strerror(errno));
  43.         return -1;
  44.     }
  45.     memset(out,'\0',out_len);
  46.     strcpy(out,_buf.mtext);
  47.     return 0;
  48. }
  49. int delete_queue(int msg_id)
  50. {
  51.     int ret = msgctl(msg_id,IPC_RMID,NULL);
  52.     if(ret < 0){
  53.         printf("%d:%s\n",errno,strerror(errno));
  54.         return -3;
  55.     }
  56.     return 0;
  57. }
客户端:

  1. #include"common.h"

  2. int client()
  3. {
  4.     int msg_id = get_queue();
  5.     char buf[_SIZE_];
  6.     while(1)
  7.     {
  8.         printf("Please Enter : ");
  9.         fflush(stdout);
  10.         memset(buf,'\0',sizeof(buf));
  11.         scanf("%s",buf);
  12.         send_msg(msg_id,CLIENT_TYPE,buf);
  13.         if(strncasecmp(buf,"quit",4) == 0){
  14.             printf("client quit\n");
  15.             return 0;
  16.         }
  17.         sleep(2);
  18.         memset(buf,'\0',sizeof(buf));
  19.         int ret = recv_msg(msg_id,SERVER_TYPE,buf,sizeof(buf));
  20.         if(ret == 0){
  21.             printf("server say : %s\n",buf);
  22.         }
  23.     }
  24. }
  25. int main()
  26. {
  27.     client();
  28.     return 0;
  29. }
服务端:

  1. int server()
  2. {
  3.     int msg_id = creat_queue();
  4.     if(msg_id < 0){
  5.         printf("%s\n",strerror(errno));
  6.         return -1;
  7.     }
  8.     char buf[_SIZE_];
  9.     while(1)
  10.     {
  11.         sleep(5);
  12.         memset(buf,'\0',sizeof(buf));
  13.         int ret = recv_msg(msg_id,CLIENT_TYPE,buf,sizeof(buf));
  14.         if(ret == 0){
  15.             if(strncasecmp(buf,"quit",4) == 0){
  16.                 printf("client leave!\n");
  17.                 break;
  18.             }
  19.             printf("client say : %s\n",buf);
  20.         }
  21.         printf("Please Enter :");
  22.         fflush(stdout);
  23.         memset(buf,'\0',sizeof(buf));
  24.         scanf("%s",buf);
  25.         send_msg(msg_id,SERVER_TYPE,buf);
  26.     }
  27.     return delete_queue(msg_id);
  28. }
  29. int main()
  30. {
  31.     server();
  32.     return 0;
  33. }

这样服务端和客户端就可以进行对话了。

二、信号量

特点:
1.本质其实为一个计数器,记录资源的数量
2.PV为原子操作
P(sv):如果sv的值大于零,就给它减1;如果它的值为零,就挂起该进程的执行
V(sv):如果有其他进程因等待sv而被挂起,就让它恢复运行,如果没有进程因等待sv而挂 起,就给它加1.  
3.保证临界资源的同步、互斥

ipcs -s 查看信号量
ipcrm -s 删除信号量

使用例子:

  1. #include"common.h"

  2. static int com_sem(int nsems,int flag)
  3. {
  4.     key_t key = ftok(_PATH_,_PROJ_ID_);
  5.     if(key < 0){
  6.         printf("%s\n",strerror(errno));
  7.         return -1;
  8.     }
  9.     int sem_id = semget(key,nsems,flag);
  10.     if(sem_id < 0){
  11.         printf("%s\n",strerror(errno));
  12.         return -2;
  13.     }
  14.     return sem_id;
  15. }

  16. int creat_sem(int nsems)
  17. {
  18.     int flag = IPC_CREAT|IPC_EXCL|0666;
  19.     return com_sem(nsems,flag);
  20. }

  21. int get_sem(int nsems)
  22. {
  23.     int flag = IPC_CREAT;
  24.     return com_sem(nsems,flag);
  25. }

  26. static int com_semop(int sem_id,unsigned short num,short op)
  27. {
  28.     struct sembuf semb[1];//only consider binary semaphore
  29.     semb[0].sem_num =num;
  30.     semb[0].sem_op = op;
  31.     semb[0].sem_flg = 0;//SEM_UNDO,对崩溃的信号量进行回滚操作
  32.     if(semop(sem_id,semb,1) < 0)
  33.     {
  34.         printf("%s\n",strerror(errno));
  35.         return -1;
  36.     }
  37.     return 0;
  38. }

  39. int P(int sem_id,unsigned short num)
  40. {
  41.     int op = -1;
  42.     return com_semop(sem_id,num,op);
  43. }

  44. int V(int sem_id,unsigned short num)
  45. {
  46.     int op = 1;
  47.     return com_semop(sem_id,num,op);
  48. }

  49. int init_sem(int sem_id,int num,int init_val)
  50. {
  51.     semun_t sem_val;
  52.     sem_val.val = init_val;
  53.     int ret = semctl(sem_id,num,SETVAL,sem_val);
  54.     if(ret < 0){
  55.         printf("%s\n",strerror(errno));
  56.         return -1;
  57.     }
  58.     return 0;
  59. }
  60. int destory_sem(int sem_id)
  61. {
  62.     int ret = semctl(sem_id,0,IPC_RMID);
  63.     if(ret < 0){
  64.         printf("%s\n",strerror(errno));
  65.         return -1;
  66.     }
  67.         printf("\ndestroy success!\n");
  68.         return 0;
  69. }
测试:

  1. int main()
  2. {
  3.         int f_sem_id = creat_sem(1);
  4.         init_sem(f_sem_id,0,1);
  5.         pid_t id = fork();
  6.         if( id == 0 ){//child
  7.             int c_sem_id = get_sem(1);
  8.             int count = 3;
  9.             while(1){
  10.                 P(c_sem_id,0);
  11.                 printf("A");
  12.                 fflush(stdout);
  13.                 sleep(3);
  14.                 printf("A");
  15.                 fflush(stdout);
  16.                 sleep(3);
  17.                 V(c_sem_id,0);
  18.                 count--;
  19.                 if(count == 0){
  20.                      break;
  21.                  }
  22.             }
  23.         }
  24.         else
  25.         {//father
  26.             int count = 3;
  27.              while(1) {
  28.                P(f_sem_id,0);
  29.                printf("B");
  30.                fflush(stdout);
  31.                sleep(3;
  32.                printf("B");
  33.                fflush(stdout);
  34.                sleep(2;
  35.                V(f_sem_id,0);
  36.                count--;
  37.                if(count == 0){
  38.                   break;
  39.                 }
  40.                     
  41.             }
  42.         }
  43. }


阅读(1898) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~