• Linux--信号量共享内存


    1.基础知识:

    (1)共享内存是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间的数据传递不再涉及内核,即进程不再通过执行进入内核的系统调用来传递彼此的数据。

    (2)共享内存的生命周期随内核。

    (3)注意:共享内存未提供任何保护资源,即共享内存自身没有同步与互斥机制,但它是临界资源,所以我们需要利用其它机制来保证数据的正确性,Linux下就可以用信号量达到同步的目的。

    (4)linux共享内存有两种方式(本文主要介绍shmget方式):

                    1)mmap方式,适用于父子进程之间,创建的内存非常大时;

                    2)shmget方式,适用于同一台电脑上不同进程之间,创建的内存相对较小。

    (5)进程间利用共享内存实现消息队列的基本原理如下图

     2.相关函数

    1.semget

    1.函数原型

    2.函数功能

    创建或者获取一个已经存在的信号量;

    如果为全新创建,也就是不知道是否有人创建过,IPC_CREATE|IPC_EXCEL,就是如果没

    有则创建 , 如果有则创建失败 ;

    3.参数

    key:两个进程使用相同的key,就可以使用同一个信号量;

    nsems:创建几个信号量;

    semflg:标志位;如果为创建:IPC_CREAT;

    4.返回值

    成功返回一个非负整数即该信号集的标识码;失败返回-1

    2.semop

    1.函数原型

    2.函数功能

    对信号量进行改变,P操作或者V操作;

    3.参数

    semid:信号量的id,也就是刚才semget的返回值;说明对哪个信号量进行操作;

    sops:结构体指针,指向sembuf的结构体指针,sembuf结构体有三个成员变量:sem_num

    示信号量的编号 ( 即指定信号量集中的信号量下标 );

    nsops:表示是p还是v操作;1v操作 (1),-1p操作(1);sem_flg为标志位;

    4.返回值

    成功返回0;失败返回-1

    5.说明

    unsigned short sem_num;  /* semaphore number */第几个信号量
    short          sem_op;   /* semaphore operation */p(-1)操作还是v操作(+1)
    short          sem_flg;  /* operation flags */标志位

    3.semctl

    1.函数原型

    **注意**:联合体semun,这个联合体需要自己定义; 

    2.函数功能

    控制信号量集 对信号量进行控制:初始化/删除信号量

    3.参数

    semid:信号量id;  由semget函数返回的信号量集标识码

    semnum:信号量编号信号量集中信号量的序号

    cmd:命令:SETVAL:初始化信号量; IPC_RMID:删除信号量将要采取的动作(有三个可取值)

    4.返回值

    成功返回0,失败返回-1

    3.思路:

    4.代码

    1. sem.h

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. union semun
    7. {
    8. int val;
    9. };
    10. void sem_init();
    11. void sem_p(int index);
    12. void sem_v(int index);
    13. void sem_destroy();

    2.sem.c

    1. #include "sem.h"
    2. #define SEM_NUM 2
    3. static int semid = -1;
    4. void sem_init()
    5. {
    6. semid = semget((key_t)1234,SEM_NUM,IPC_CREAT|IPC_EXCL|0600);//全新创建
    7. if (semid == -1 )
    8. {
    9. semid = semget((key_t)1234,SEM_NUM,0600);
    10. if ( semid == -1)
    11. {
    12. printf("semget err\n");
    13. return;
    14. }
    15. }
    16. else
    17. {
    18. int arr[SEM_NUM] = {1,0};
    19. for( int i = 0; i < SEM_NUM; i++ )
    20. {
    21. union semun a;
    22. a.val = arr[i];
    23. if ( semctl(semid,i,SETVAL,a) == -1 )//全新创建成功,就初始化
    24. {
    25. printf("semctl err\n");
    26. }
    27. }
    28. }
    29. }
    30. void sem_p(int index)
    31. {
    32. if ( index < 0 || index >= SEM_NUM )
    33. {
    34. return;
    35. }
    36. struct sembuf buf;
    37. buf.sem_num = index;
    38. buf.sem_op = -1;//p
    39. buf.sem_flg = SEM_UNDO;
    40. if ( semop(semid,&buf,1) == -1 )
    41. {
    42. printf("sem p err\n");
    43. }
    44. }
    45. void sem_v(int index)
    46. {
    47. if ( index < 0 || index >= SEM_NUM )
    48. {
    49. return;
    50. }
    51. struct sembuf buf;
    52. buf.sem_num = index;
    53. buf.sem_op = 1;//v
    54. buf.sem_flg = SEM_UNDO;
    55. if ( semop(semid,&buf,1) == -1 )
    56. {
    57. printf("sem v err\n");
    58. }
    59. }
    60. void sem_destroy()
    61. {
    62. if ( semctl(semid,0,IPC_RMID) == -1 )
    63. {
    64. printf("semctl del err\n");
    65. }
    66. }

    3.a.c

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include "sem.h"
    7. int main()
    8. {
    9. int shmid = shmget((key_t)1234,256,0600|IPC_CREAT);//创建/获取共享内存
    10. if ( shmid == -1 )
    11. {
    12. printf("shmget err\n");
    13. exit(0);
    14. }
    15. char* s = (char*)shmat(shmid,NULL,0);
    16. if ( s == (char*)-1 )
    17. {
    18. printf("shmat err\n");
    19. exit(0);
    20. }
    21. sem_init();//2 1,0
    22. while( 1 )
    23. {
    24. printf("input\n");
    25. char buff[128] = {0};
    26. fgets(buff,128,stdin);
    27. sem_p(0);
    28. strcpy(s,buff);
    29. sem_v(1);
    30. if ( strncmp(buff,"end",3) == 0 )
    31. {
    32. break;
    33. }
    34. }
    35. shmdt(s);
    36. exit(0);
    37. }

    4.b.c

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include "sem.h"
    7. int main()
    8. {
    9. int shmid = shmget((key_t)1234,256,0600|IPC_CREAT);//创建/获取共享内存
    10. if ( shmid == -1 )
    11. {
    12. printf("shmget err\n");
    13. exit(0);
    14. }
    15. char* s = (char*)shmat(shmid,NULL,0);
    16. if ( s == (char*)-1 )
    17. {
    18. printf("shmat err\n");
    19. exit(0);
    20. }
    21. sem_init();//2 1,0
    22. while( 1 )
    23. {
    24. printf("input\n");
    25. char buff[128] = {0};
    26. fgets(buff,128,stdin);
    27. sem_p(0);
    28. strcpy(s,buff);
    29. sem_v(1);
    30. if ( strncmp(buff,"end",3) == 0 )
    31. {
    32. break;
    33. }
    34. }
    35. shmdt(s);
    36. exit(0);
    37. }

     

     只运行b.c,会阻塞

  • 相关阅读:
    快捷方式变白解决方法
    记一次神奇的 pipe 错误
    数据面最流行的工具包dpdk的前世-现在和未来
    基于Eigen的椭圆拟合
    叶子数和深度
    设备监理师证书含金量怎样?值得考吗?
    Java加密2-MAC 对称密钥加密
    IB商管IA占多少?写什么?
    InputStream输入字节流
    第二章 C API稳定性
  • 原文地址:https://blog.csdn.net/m0_59052131/article/details/127970222