• 系统编程 day11 信号量 (我也不知道是什么东西,不好解释 )(和之前的信号有一些不同 (函数), 但是也有一些操作相同 ,比如说 p v 操作 , )


    1.先说一下 ,终端的命令

    pcs 命令用于报告进程间通信方式的状态

    语法

    ipcs    -m                m 共享内存段  

    ipcs  -q                   q 消息队列  

    ipcs   -s                  s 信号量  

    ipcs   -a                  a设施的类型。


     2      ipcrm- 删除IPC

    格式:ipcrm    [–q msgid]    [-m shmid]   [ -s semid]  [-Q msgkey]   [-M shmkey]   [-S semkey]

    参数说明:

    -q:通过msgid删除消息队列

    -Q:通过msgkey删除消息队列

    -m:通过shmid删除共享内存

    -M:通过shkey删除共享内存

    -s:通过semid删除信号量

    -S:通过semkey删除信号量


    3.信号量

    信号量:一个整数;  

    大于或等于0时代表可供并发进程使用的资源实体数;

      小于0时代表正在等待使用临界区的进程数;  

    用于互斥的信号量初始值应大于0;  

    只能通过P、V原语操作而改变;

    信号量也就是操作系统中所用到的PV 原语,它广泛用于进程或线程间的同步与互斥。信号量本质上是一个非负的整数计数器,它被用来控制对公共资源的访问。

    PV原语的工作原理:PV原语是对整数计数器信号量sem的操作。一次P操作使sem减一,而一次V操作使sem 加一。

    进程(或线程)根据信号量的值来判断是否对公共资源具有访问权限。当信号量sem 的值大于等于零时,该进程(或线程)具有公共资源的访问权限;相反,当信号量sem的值小于零时,该进程(或线程)就将阻塞直到信号量sem的值大于0 为止。

    为了达到安全访问共享资源的目的,就要同步共享资源,那么总要把访问的共享资源放在临界区中,能否进入临界区正好用信号量来控制, 进程需要执行下列操作:  (1) 访问控制该资源的信号量 。  (2) 若此信号量的值为正,则允许进行使用该资源。进程将信号量减1(P操作)  (3) 若此信号量为0,则该资源目前不可用,进程进入睡眠状态,直至信号量值大于0,进程被唤醒,转入步骤(1)。  (4) 当进程不再使用一个信号量控制的资源时,信号量值加1。(V操作),如果此时有进程正在睡眠等待此信号量,则唤醒此进程


    4.


     5.

     


    6.信号函数:

    1.ftok--获取一个IPC标识符

    头文件: # include # include

    函数原型:key_t ftok(const char *pathname, char proj_id);  

    参数:pathname为指定的文件路径,实际用到的是此文件的索引节点号,proj_id是子序号。

    返回值:成功返回一个系统中唯一的key,否则返回-1

    2.semget--获得一个信号量集合ID

    头文件: #include  

    #include

     #include

    原型:int semget(key_t key, int nsems, int flag)

    函数功能:用于创建一个新的信号量组或获取一个已经存在的信号量组

    参数:key是IPC结构的标识符,

    nsems是该集合中的信号量个数。如果是创建新集合(一般在服务器中),则必须指定        

    nsems;如果是引用一个现有的信号量集合(一般在客户机中)则将nsems指定为0。

    flag将来决定是创建新的信号量集合,还是引用一个现有的信号量集合。flag常用值为:以下|权限值

    IPC_CREAT 如果信号量不存在则创建

    IPC_EXCL 与IPC_CREAT合用,如果信号量已经存在则返回错误

    返回值:如果创建成功返回已创建信号量集标识符semid,如果不成功返回-1

    所创建的信号量可以通过 ipcs –s 命令查询

    3.semctl--实现对信号灯的各种控制操作

    原型:int semctl(int semid, int semnum, int cmd, semun arg );

    返回值:如果成功,则返回一个正数,否则返回-1

    参数:semid指定信号量集,

    semnum指定对哪个信号灯操作(从0开始),

    参数cmd指定具体的操作类型。

    参数cmd可为下列值: IPC_STAT获取信号量信息,信息由arg.buf返回,记录在semid_ds结构体                                         IPC_SET 设置信号量信息,待设置信息保存在arg.buf中。

                                            IPC_RMID 将信号量集从内存中删除。

                                            IPC_INFO 获取信息量集,由arg.buf返回,记录在struct seminfo结构体 GETALL 获取所有信号量的值,结果保存在 arg.array 中,

    GETNCNT 返回正在等待资源的进程数目。

    GETPID返回最后一个执行semop操作的进程的PID。

    GETVAL返回信号量集中的一个单个的信号量的值

     GETZCNT返回这在等待完全空闲的资源的进程数目(等待所有信号量值变成0的进程数)

    SETALL 通过arg.array更新所有信号量的值,同时更新与本信号相关的semid_ds结构的sem_ctime成员。

    SETVAL设置信号量semnum所代表的信号量的值为arg.val。

    4.semop--操作单个信号量

    原型int semop(int semid,struct sembuf*sops,unsign int nsops)

    函数功能:函数可以一次对一个或多个信号量进行PV操作。

    参数:semid为要操作的信号量集合标识符,由semget()返回得来

              sops是指向将要操作的结构体的指针。

              nsops规定该数组中操作的数量(元素数)。

     

    sem_op可以是下列值:

    sem_op>0:相应进程要释放sem_op数目的共享资源;(V操作)

    sem_op=0:用于对共享资源是否已用完的测试;(导致操作阻塞,直到信号量的值为0才继续) sem_op<0:进程要申请sem_op个共享资源。(P操作,信号量的值减去绝对值,如果小于零,进程阻塞,直到信号量的值至少等于其绝对值)

    sem_flg可以是下列值:

    IPC_NOWAIT用于防止操作阻塞,如果操作本应阻塞,则semop调用会失败。

    SEM_UNDO会在进程退出的时候自动撤消该次操作。 返回值:0,成功。-1,失败。

    看看代码  (看代码就懂了 真的)

    1. /************************************************************************************************************************************************************************************************************************
    2. *文件名:
    3. *作 者:She001
    4. *时 间:
    5. *版 本:
    6. *作 用:信号量的函数
    7. ****************************************************************************************************************************************************************************************************************************/
    8. #include
    9. #include
    10. #include
    11. #include
    12. #include
    13. #include
    14. #include
    15. #include
    16. #include
    17. #include
    18. #include
    19. #include
    20. #include
    21. #include
    22. #include
    23. #include
    24. #include
    25. #include
    26. #include
    27. #include
    28. #include
    29. #include
    30. #include
    31. #include
    32. #include
    33. #include
    34. #include
    35. #include
    36. #include
    37. #include
    38. //信号量函数的使用方法
    39. //ls -li //查看键值(唯一对应的值)
    40. //2.ftok //创建键值
    41. //3.semget  获得一个信号灯
    42. //终端:
    43. //4. ipcrm -s 信号量  删除信号量
    44. //5. ipcs -s 查看信号量
    45. //信号量的命令
    46. // ipcs -m
    47. // ipcs -q
    48. // ipcs -s
    49. // ipcs -a
    50. //6.semctl 实现对信号量的各种控制操作   设定灯的初始值,查看信号量
    51. //
    52. union semnum
    53. {
    54. int val;
    55. }value={1};//初始的值为1
    56. int main(int argc,char *argv[])
    57. {
    58. key_t key =ftok(".",50);//生成一个键 //50这里随便填
    59. if(key==-1)
    60. {
    61. perror("ftok error\n");
    62. return -1;
    63. }
    64. else
    65. {
    66. printf("ftok ok\n");
    67. printf("key =%d\n",key);
    68. }
    69. int sid =semget(key,1,IPC_CREAT|0666); //创建一个信号量
    70. printf("sid =%d\n",sid);//打印信号量的 id
    71. //6 设定值 1
    72. semctl(sid,0 ,SETVAL,value);//value 是上面的共用体 //初始化 开始是1
    73. //查看初始化的值
    74. int val1 = semctl(sid,0,GETVAL,0);
    75. printf("val1 =%d\n",val1);
    76. //P操作 v操作 
    77. //semop 函数 
    78. struct sembuf sem1 ={0};
    79. sem1.sem_num=0; //创建的第一个信号量
    80. sem1.sem_op=-1; //这里是-1 (注意)
    81. sem1.sem_flg=0;
    82. semop(sid ,&sem1,1); //p 操作
    83. val1 = semctl(sid,0,GETVAL,0);//查看初始化的值
    84. printf("p -> val1 =%d\n",val1);
    85. //对临界资源操作
    86. //v 操作 
    87. sem1.sem_op=1; //+1 开灯
    88. semop(sid,&sem1,1);
    89. val1 = semctl(sid,0,GETVAL,0);//查看初始化的值
    90. printf("v -> val1 =%d\n",val1);
    91. //销毁信号量
    92. semctl(sid,0,IPC_RMID,0);
    93. return 0;
    94. }

  • 相关阅读:
    Swoole Compiler 加密PHP源代码(简版)
    时序预测 | MATLAB实现EMD-iCHOA+GRU基于经验模态分解-改进黑猩猩算法优化门控循环单元的时间序列预测
    计算机毕业设计项目选题推荐(免费领源码)java+ssm+Mysq学科竞赛管理系统08604
    华理生物冲刺科创板:年营收2.26亿 拟募资8亿
    【软件工程】四、编码 & 维护
    理解Java程序的执行
    机器学习——正则化
    了解回归测试的作用
    AIGC 时代,Amazon DeepRacer 带你驶入机器学习的快车道
    Spring MVC 十:异常处理
  • 原文地址:https://blog.csdn.net/she666666/article/details/126273693